From 9d9bfaff8d8d573eb900c5a34eb73f5a6fa7a125 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 14 Oct 2013 16:14:19 +0200 Subject: [PATCH] Use send/recv functions from FreeBSD Use recvfrom(), recvmsg(), sendto() and sendmsg() from FreeBSD. --- Makefile | 1 - freebsd-to-rtems.py | 1 - freebsd/sys/kern/uipc_syscalls.c | 148 ++++- freebsd/sys/sys/sysproto.h | 12 +- .../include/machine/rtems-bsd-syscall-api.h | 8 + rtemsbsd/rtems/rtems-bsd-syscalls.c | 620 ------------------ testsuite/syscalls01/test_main.c | 207 ++++++ 7 files changed, 371 insertions(+), 626 deletions(-) delete mode 100644 rtemsbsd/rtems/rtems-bsd-syscalls.c diff --git a/Makefile b/Makefile index 0c39e3ba..2d5107ae 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,6 @@ LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-support.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sx.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-synch.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-syscall-api.c -LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-syscalls.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctlbyname.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctl.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctlnametomib.c diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py index d3c96372..73e6a5ea 100755 --- a/freebsd-to-rtems.py +++ b/freebsd-to-rtems.py @@ -636,7 +636,6 @@ rtems.addRTEMSSourceFiles( 'rtems/rtems-bsd-sx.c', 'rtems/rtems-bsd-synch.c', 'rtems/rtems-bsd-syscall-api.c', - 'rtems/rtems-bsd-syscalls.c', 'rtems/rtems-bsd-sysctlbyname.c', 'rtems/rtems-bsd-sysctl.c', 'rtems/rtems-bsd-sysctlnametomib.c', diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c index d5f97bb4..5ee11b0c 100644 --- a/freebsd/sys/kern/uipc_syscalls.c +++ b/freebsd/sys/kern/uipc_syscalls.c @@ -98,10 +98,10 @@ __FBSDID("$FreeBSD$"); #include #endif /* __rtems__ */ -#ifndef __rtems__ static int sendit(struct thread *td, int s, struct msghdr *mp, int flags); static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp); +#ifndef __rtems__ static int accept1(struct thread *td, struct accept_args *uap, int compat); static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat); static int getsockname1(struct thread *td, struct getsockname_args *uap, @@ -863,7 +863,13 @@ socketpair(struct thread *td, struct socketpair_args *uap) } return (error); } +#endif /* __rtems__ */ +#ifdef __rtems__ +static int +kern_sendit( struct thread *td, int s, struct msghdr *mp, int flags, + struct mbuf *control, enum uio_seg segflg); +#endif /* __rtems__ */ static int sendit(td, s, mp, flags) struct thread *td; @@ -986,9 +992,13 @@ kern_sendit(td, s, mp, flags, control, segflg) /* Generation of SIGPIPE can be controlled per socket */ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && !(flags & MSG_NOSIGNAL)) { +#ifndef __rtems__ PROC_LOCK(td->td_proc); tdksignal(td, SIGPIPE, NULL); PROC_UNLOCK(td->td_proc); +#else /* __rtems__ */ + /* FIXME: Determine if we really want to use signals */ +#endif /* __rtems__ */ } } if (error == 0) @@ -1004,8 +1014,13 @@ bad: return (error); } +#ifndef __rtems__ int sendto(td, uap) +#else /* __rtems__ */ +static int +rtems_bsd_sendto(td, uap) +#endif /* __rtems__ */ struct thread *td; struct sendto_args /* { int s; @@ -1033,7 +1048,37 @@ sendto(td, uap) error = sendit(td, uap->s, &msg, uap->flags); return (error); } +#ifdef __rtems__ +ssize_t +sendto(int socket, const void *message, size_t length, int flags, + const struct sockaddr *dest_addr, socklen_t dest_len) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct sendto_args ua = { + .s = socket, + .buf = (caddr_t) message, + .len = length, + .flags = flags, + .to = (caddr_t) dest_addr, + .tolen = dest_len + }; + int error; + if (td != NULL) { + error = rtems_bsd_sendto(td, &ua); + } else { + error = ENOMEM; + } + + if (error == 0) { + return td->td_retval[0]; + } else { + rtems_set_errno_and_return_minus_one(error); + } +} +#endif /* __rtems__ */ + +#ifndef __rtems__ #ifdef COMPAT_OLDSOCK int osend(td, uap) @@ -1087,9 +1132,15 @@ osendmsg(td, uap) return (error); } #endif +#endif /* __rtems__ */ +#ifndef __rtems__ int sendmsg(td, uap) +#else /* __rtems__ */ +static int +rtems_bsd_sendmsg(td, uap) +#endif /* __rtems__ */ struct thread *td; struct sendmsg_args /* { int s; @@ -1115,7 +1166,35 @@ sendmsg(td, uap) free(iov, M_IOV); return (error); } +#ifdef __rtems__ +ssize_t +sendmsg(int socket, const struct msghdr *message, int flags) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct sendmsg_args ua = { + .s = socket, + .msg = message, + .flags = flags + }; + int error; + if (td != NULL) { + error = rtems_bsd_sendmsg(td, &ua); + } else { + error = ENOMEM; + } + + if (error == 0) { + return td->td_retval[0]; + } else { + rtems_set_errno_and_return_minus_one(error); + } +} +#endif /* __rtems__ */ + +#ifdef __rtems__ +static +#endif /* __rtems__ */ int kern_recvit(td, s, mp, fromseg, controlp) struct thread *td; @@ -1300,8 +1379,13 @@ recvit(td, s, mp, namelenp) return (error); } +#ifndef __rtems__ int recvfrom(td, uap) +#else /* __rtems__ */ +static int +rtems_bsd_recvfrom(td, uap) +#endif /* __rtems__ */ struct thread *td; struct recvfrom_args /* { int s; @@ -1335,7 +1419,37 @@ recvfrom(td, uap) done2: return(error); } +#ifdef __rtems__ +ssize_t +recvfrom(int socket, void *__restrict buffer, size_t length, int flags, + struct sockaddr *__restrict address, socklen_t *__restrict address_len) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct recvfrom_args ua = { + .s = socket, + .buf = buffer, + .len = length, + .flags = flags, + .from = address, + .fromlenaddr = address_len + }; + int error; + if (td != NULL) { + error = rtems_bsd_recvfrom(td, &ua); + } else { + error = ENOMEM; + } + + if (error == 0) { + return td->td_retval[0]; + } else { + rtems_set_errno_and_return_minus_one(error); + } +} +#endif /* __rtems__ */ + +#ifndef __rtems__ #ifdef COMPAT_OLDSOCK int orecvfrom(td, uap) @@ -1409,9 +1523,15 @@ orecvmsg(td, uap) return (error); } #endif +#endif /* __rtems__ */ +#ifndef __rtems__ int recvmsg(td, uap) +#else /* __rtems__ */ +static int +rtems_bsd_recvmsg(td, uap) +#endif /* __rtems__ */ struct thread *td; struct recvmsg_args /* { int s; @@ -1443,6 +1563,30 @@ recvmsg(td, uap) free(iov, M_IOV); return (error); } +#ifdef __rtems__ +ssize_t +recvmsg(int socket, struct msghdr *message, int flags) +{ + struct thread *td = rtems_bsd_get_curthread_or_null(); + struct recvmsg_args ua = { + .s = socket, + .msg = message, + .flags = flags + }; + int error; + + if (td != NULL) { + error = rtems_bsd_recvmsg(td, &ua); + } else { + error = ENOMEM; + } + + if (error == 0) { + return td->td_retval[0]; + } else { + rtems_set_errno_and_return_minus_one(error); + } +} #endif /* __rtems__ */ /* ARGSUSED */ @@ -1961,6 +2105,7 @@ ogetpeername(td, uap) return (getpeername1(td, (struct getpeername_args *)uap, 1)); } #endif /* COMPAT_OLDSOCK */ +#endif /* __rtems__ */ int sockargs(mp, buf, buflen, type) @@ -2002,7 +2147,6 @@ sockargs(mp, buf, buflen, type) } return (error); } -#endif /* __rtems__ */ int getsockaddr(namp, uaddr, len) diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h index 15a65b5f..548bb337 100644 --- a/freebsd/sys/sys/sysproto.h +++ b/freebsd/sys/sys/sysproto.h @@ -127,6 +127,7 @@ struct ptrace_args { char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)]; char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)]; }; +#endif /* __rtems__ */ struct recvmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char msg_l_[PADL_(struct msghdr *)]; struct msghdr * msg; char msg_r_[PADR_(struct msghdr *)]; @@ -134,7 +135,11 @@ struct recvmsg_args { }; struct sendmsg_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; +#ifndef __rtems__ char msg_l_[PADL_(struct msghdr *)]; struct msghdr * msg; char msg_r_[PADR_(struct msghdr *)]; +#else /* __rtems__ */ + char msg_l_[PADL_(struct msghdr *)]; const struct msghdr * msg; char msg_r_[PADR_(struct msghdr *)]; +#endif /* __rtems__ */ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; }; struct recvfrom_args { @@ -145,7 +150,6 @@ struct recvfrom_args { char from_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict from; char from_r_[PADR_(struct sockaddr *__restrict)]; char fromlenaddr_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *__restrict)]; }; -#endif /* __rtems__ */ struct accept_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char name_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict name; char name_r_[PADR_(struct sockaddr *__restrict)]; @@ -462,15 +466,19 @@ struct mkfifo_args { char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; }; +#endif /* __rtems__ */ struct sendto_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)]; char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; char to_l_[PADL_(caddr_t)]; caddr_t to; char to_r_[PADR_(caddr_t)]; +#ifndef __rtems__ char tolen_l_[PADL_(int)]; int tolen; char tolen_r_[PADR_(int)]; -}; +#else /* __rtems__ */ + char tolen_l_[PADL_(__socklen_t)]; __socklen_t tolen; char tolen_r_[PADR_(__socklen_t)]; #endif /* __rtems__ */ +}; struct shutdown_args { char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)]; diff --git a/rtemsbsd/include/machine/rtems-bsd-syscall-api.h b/rtemsbsd/include/machine/rtems-bsd-syscall-api.h index 5d872c1d..97790212 100644 --- a/rtemsbsd/include/machine/rtems-bsd-syscall-api.h +++ b/rtemsbsd/include/machine/rtems-bsd-syscall-api.h @@ -69,6 +69,14 @@ int getsockopt(int, int, int, void * __restrict, socklen_t * __restrict); int listen(int, int); +ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict); + +ssize_t recvmsg(int, struct msghdr *, int); + +ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); + +ssize_t sendmsg(int, const struct msghdr *, int); + int setsockopt(int, int, int, const void *, socklen_t); int shutdown(int, int); diff --git a/rtemsbsd/rtems/rtems-bsd-syscalls.c b/rtemsbsd/rtems/rtems-bsd-syscalls.c deleted file mode 100644 index 9c7605f6..00000000 --- a/rtemsbsd/rtems/rtems-bsd-syscalls.c +++ /dev/null @@ -1,620 +0,0 @@ -/** - * @file - * - * @ingroup rtems_bsd_rtems - * - * @brief TODO. - */ - -/* - * Copyright (c) 2009, 2010 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static const rtems_filesystem_file_handlers_r socket_handlers; -extern int killinfo( pid_t pid, int sig, const union sigval *value ); - -/* - * Convert an RTEMS file descriptor to a BSD socket pointer. - */ - -struct socket *rtems_bsdnet_fdToSocket( - int fd -) -{ - rtems_libio_t *iop; - - /* same as rtems_libio_check_fd(_fd) but different return */ - if ((uint32_t)fd >= rtems_libio_number_iops) { - errno = EBADF; - return NULL; - } - iop = &rtems_libio_iops[fd]; - - /* same as rtems_libio_check_is_open(iop) but different return */ - if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) { - errno = EBADF; - return NULL; - } - - if (iop->data1 == NULL) - errno = EBADF; - return iop->data1; -} - -/* - * Create an RTEMS file descriptor for a socket - */ -static int rtems_bsdnet_makeFdForSocket (void *so) -{ - rtems_libio_t *iop; - int fd; - - iop = rtems_libio_allocate(); - if (iop == 0) - rtems_set_errno_and_return_minus_one( ENFILE ); - - fd = iop - rtems_libio_iops; - iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ; - iop->data0 = fd; - iop->data1 = so; - iop->pathinfo.handlers = &socket_handlers; - iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry; - rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo); - return fd; -} - -/* - * The following code is based on FreeBSD uipc_syscalls.c - */ - -int -sockargs(mp, buf, buflen, type) - struct mbuf **mp; - caddr_t buf; - int buflen, type; -{ - struct sockaddr *sa; - struct mbuf *m; - int error; - - if ((u_int)buflen > MLEN) { -#ifdef COMPAT_OLDSOCK - if (type == MT_SONAME && (u_int)buflen <= 112) - buflen = MLEN; /* unix domain compat. hack */ - else -#endif - if ((u_int)buflen > MCLBYTES) - return (EINVAL); - } - m = m_get(M_WAIT, type); - if ((u_int)buflen > MLEN) - MCLGET(m, M_WAIT); - m->m_len = buflen; - error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); - if (error) - (void) m_free(m); - else { - *mp = m; - if (type == MT_SONAME) { - sa = mtod(m, struct sockaddr *); - -#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN - if (sa->sa_family == 0 && sa->sa_len < AF_MAX) - sa->sa_family = sa->sa_len; -#endif - sa->sa_len = buflen; - } - } - return (error); -} - -/* - ********************************************************************* - * BSD-style entry points * - ********************************************************************* - */ - -int -kern_sendit(td, s, mp, flags, control, segflg) - struct thread *td; - int s; - struct msghdr *mp; - int flags; - struct mbuf *control; - enum uio_seg segflg; -{ - struct uio auio; - struct iovec *iov; - struct socket *so; - int i; - int len, error; -#ifdef KTRACE - struct uio *ktruio = NULL; -#endif - - if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { - error = EBADF; - return (error); - } - -#ifdef MAC - if (mp->msg_name != NULL) { - error = mac_socket_check_connect(td->td_ucred, so, - mp->msg_name); - if (error) - goto bad; - } - error = mac_socket_check_send(td->td_ucred, so); - if (error) - goto bad; -#endif - - auio.uio_iov = mp->msg_iov; - auio.uio_iovcnt = mp->msg_iovlen; - auio.uio_segflg = segflg; - auio.uio_rw = UIO_WRITE; - auio.uio_td = td; - auio.uio_offset = 0; /* XXX */ - auio.uio_resid = 0; - iov = mp->msg_iov; - for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if ((auio.uio_resid += iov->iov_len) < 0) { - error = EINVAL; - goto bad; - } - } -#ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) - ktruio = cloneuio(&auio); -#endif - len = auio.uio_resid; - error = sosend(so, mp->msg_name, &auio, 0, control, flags, td); - if (error) { - if (auio.uio_resid != len && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) - error = 0; - /* Generation of SIGPIPE can be controlled per socket */ - if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && - !(flags & MSG_NOSIGNAL)) { - killinfo(rtems_bsd_get_task_id(td), SIGPIPE, NULL); - } - } - if (error == 0) - td->td_retval[0] = len - auio.uio_resid; -#ifdef KTRACE - if (ktruio != NULL) { - ktruio->uio_resid = td->td_retval[0]; - ktrgenio(s, UIO_WRITE, ktruio, error); - } -#endif -bad: - return (error); -} - -static int -sendit(td, s, mp, flags) - struct thread *td; - int s; - struct msghdr *mp; - int flags; -{ - struct mbuf *control; - struct sockaddr *to; - int error; - - if (mp->msg_name != NULL) { - error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); - if (error) { - to = NULL; - goto bad; - } - mp->msg_name = to; - } else { - to = NULL; - } - - if (mp->msg_control) { - if (mp->msg_controllen < sizeof(struct cmsghdr) -#ifdef COMPAT_OLDSOCK - && mp->msg_flags != MSG_COMPAT -#endif - ) { - error = EINVAL; - goto bad; - } - error = sockargs(&control, mp->msg_control, - mp->msg_controllen, MT_CONTROL); - if (error) - goto bad; -#ifdef COMPAT_OLDSOCK - if (mp->msg_flags == MSG_COMPAT) { - struct cmsghdr *cm; - - M_PREPEND(control, sizeof(*cm), M_WAIT); - cm = mtod(control, struct cmsghdr *); - cm->cmsg_len = control->m_len; - cm->cmsg_level = SOL_SOCKET; - cm->cmsg_type = SCM_RIGHTS; - } -#endif - } else { - control = NULL; - } - - error = kern_sendit(td, s, mp, flags, control, UIO_USERSPACE); - -bad: - if (to) - free(to, M_SONAME); - return (error); -} - -/* - * All `transmit' operations end up calling this routine. - */ -ssize_t -sendmsg (int s, const struct msghdr *mp, int flags) -{ - struct thread *td; - struct msghdr msg; - struct iovec *iov; - int error; - - td = curthread; - error = copyin(mp, &msg, sizeof (msg)); - if (error) - return (error); - error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error) - return (error); - msg.msg_iov = iov; -#ifdef COMPAT_OLDSOCK - msg.msg_flags = 0; -#endif - error = sendit(td, s, &msg, flags); - free(iov, M_IOV); - if( error == 0 ) - { - return td->td_retval[0]; - } - errno = error; - return -1; -} - -/* - * Send a message to a host - */ -ssize_t -sendto (int s, const void *buf, size_t len, int flags, const struct sockaddr *to, int tolen) -{ - struct thread *td; - struct msghdr msg; - struct iovec aiov; - int error; - - td = curthread; - msg.msg_name = to; - msg.msg_namelen = tolen; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = 0; -#ifdef COMPAT_OLDSOCK - msg.msg_flags = 0; -#endif - aiov.iov_base = buf; - aiov.iov_len = len; - error = sendit(td, s, &msg, flags); - if( error == 0 ) - { - return td->td_retval[0]; - } - errno = error; - return -1; -} - -int -kern_recvit(td, s, mp, fromseg, controlp) - struct thread *td; - int s; - struct msghdr *mp; - enum uio_seg fromseg; - struct mbuf **controlp; -{ - struct uio auio; - struct iovec *iov; - int i; - socklen_t len; - int error; - struct mbuf *m, *control = 0; - caddr_t ctlbuf; - struct socket *so; - struct sockaddr *fromsa = 0; -#ifdef KTRACE - struct uio *ktruio = NULL; -#endif - - if(controlp != NULL) - *controlp = 0; - - if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) { - error = EBADF; - return (error); - } - -#ifdef MAC - error = mac_socket_check_receive(td->td_ucred, so); - if (error) { - return (error); - } -#endif - - auio.uio_iov = mp->msg_iov; - auio.uio_iovcnt = mp->msg_iovlen; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_rw = UIO_READ; - auio.uio_td = td; - auio.uio_offset = 0; /* XXX */ - auio.uio_resid = 0; - iov = mp->msg_iov; - for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if ((auio.uio_resid += iov->iov_len) < 0) { - return (EINVAL); - } - } -#ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) - ktruio = cloneuio(&auio); -#endif - len = auio.uio_resid; - CURVNET_SET(so->so_vnet); - error = soreceive(so, &fromsa, &auio, (struct mbuf **)0, - (mp->msg_control || controlp) ? &control : (struct mbuf **)0, - &mp->msg_flags); - CURVNET_RESTORE(); - if (error) { - if (auio.uio_resid != (int)len && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) - error = 0; - } -#ifdef KTRACE - if (ktruio != NULL) { - ktruio->uio_resid = (int)len - auio.uio_resid; - ktrgenio(s, UIO_READ, ktruio, error); - } -#endif - if (error) - goto out; - td->td_retval[0] = (int)len - auio.uio_resid; - if (mp->msg_name) { - len = mp->msg_namelen; - if (len <= 0 || fromsa == 0) - len = 0; - else { - /* save sa_len before it is destroyed by MSG_COMPAT */ - len = MIN(len, fromsa->sa_len); -#ifdef COMPAT_OLDSOCK - if (mp->msg_flags & MSG_COMPAT) - ((struct osockaddr *)fromsa)->sa_family = - fromsa->sa_family; -#endif - if (fromseg == UIO_USERSPACE) { - error = copyout(fromsa, mp->msg_name, - (unsigned)len); - if (error) - goto out; - } else - bcopy(fromsa, mp->msg_name, len); - } - mp->msg_namelen = len; - } - if (mp->msg_control && controlp == NULL) { -#ifdef COMPAT_OLDSOCK - /* - * We assume that old recvmsg calls won't receive access - * rights and other control info, esp. as control info - * is always optional and those options didn't exist in 4.3. - * If we receive rights, trim the cmsghdr; anything else - * is tossed. - */ - if (control && mp->msg_flags & MSG_COMPAT) { - if (mtod(control, struct cmsghdr *)->cmsg_level != - SOL_SOCKET || - mtod(control, struct cmsghdr *)->cmsg_type != - SCM_RIGHTS) { - mp->msg_controllen = 0; - goto out; - } - control->m_len -= sizeof (struct cmsghdr); - control->m_data += sizeof (struct cmsghdr); - } -#endif - len = mp->msg_controllen; - m = control; - mp->msg_controllen = 0; - ctlbuf = mp->msg_control; - - while (m && len > 0) { - unsigned int tocopy; - - if (len >= m->m_len) - tocopy = m->m_len; - else { - mp->msg_flags |= MSG_CTRUNC; - tocopy = len; - } - - if ((error = copyout(mtod(m, caddr_t), - ctlbuf, tocopy)) != 0) - goto out; - - ctlbuf += tocopy; - len -= tocopy; - m = m->m_next; - } - mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; - } -out: -#ifdef KTRACE - if (fromsa && KTRPOINT(td, KTR_STRUCT)) - ktrsockaddr(fromsa); -#endif - if (fromsa) - free(fromsa, M_SONAME); - - if (error == 0 && controlp != NULL) - *controlp = control; - else if (control) - m_freem(control); - - return (error); -} - -static int -recvit(td, s, mp, namelenp) - struct thread *td; - int s; - struct msghdr *mp; - void *namelenp; -{ - int error; - - error = kern_recvit(td, s, mp, UIO_USERSPACE, NULL); - if (error) - return (error); - if (namelenp) { - error = copyout(&mp->msg_namelen, namelenp, sizeof (socklen_t)); -#ifdef COMPAT_OLDSOCK - if (mp->msg_flags & MSG_COMPAT) - error = 0; /* old recvfrom didn't check */ -#endif - } - return (error); -} - -/* - * All `receive' operations end up calling this routine. - */ -ssize_t -recvmsg (int s, struct msghdr *mp, int flags) -{ - struct thread *td; - struct msghdr msg; - struct iovec *uiov, *iov; - int error; - - td = curthread; - error = copyin(mp, &msg, sizeof (msg)); - if (error == 0 ) - { - error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); - if (error == 0) - { - msg.msg_flags = flags; - #ifdef COMPAT_OLDSOCK - msg.msg_flags &= ~MSG_COMPAT; - #endif - uiov = msg.msg_iov; - msg.msg_iov = iov; - error = recvit(td, s, &msg, NULL); - if (error == 0) { - msg.msg_iov = uiov; - error = copyout(&msg, mp, sizeof(msg)); - } - free(iov, M_IOV); - } - } - if( error == 0 ) - { - return td->td_retval[0]; - } - errno = error; - return -1; -} - -/* - * Receive a message from a host - */ -ssize_t -recvfrom (int s, void *buf, size_t len, int flags, const struct sockaddr *from, socklen_t *fromlenaddr) -{ - struct thread *td; - struct msghdr msg; - struct iovec aiov; - int error; - - td = curthread; - if (fromlenaddr) { - error = copyin(fromlenaddr, - &msg.msg_namelen, sizeof (msg.msg_namelen)); - if (error) - goto done2; - } else { - msg.msg_namelen = 0; - } - msg.msg_name = from; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - aiov.iov_base = buf; - aiov.iov_len = len; - msg.msg_control = 0; - msg.msg_flags = flags; - error = recvit(td, s, &msg, fromlenaddr); -done2: - if( error == 0 ) - { - return td->td_retval[0]; - } - errno = error; - return -1; -} diff --git a/testsuite/syscalls01/test_main.c b/testsuite/syscalls01/test_main.c index 1b2c1846..cfac1354 100644 --- a/testsuite/syscalls01/test_main.c +++ b/testsuite/syscalls01/test_main.c @@ -230,6 +230,20 @@ init_addr(struct sockaddr_in *addr) assert(ok != 0); } +static void +init_msg(struct msghdr *msg, struct sockaddr_in *addr, struct iovec *iov, + void *buf, size_t n) +{ + memset(msg, 0, sizeof(*msg)); + memset(iov, 0, sizeof(*iov)); + iov->iov_base = buf; + iov->iov_len = n; + msg->msg_name = addr; + msg->msg_namelen = sizeof(*addr); + msg->msg_iov = iov; + msg->msg_iovlen = 1; +} + static void no_mem_task(rtems_task_argument arg) { @@ -996,6 +1010,197 @@ test_socket_read_and_write(void) assert(rtems_resource_snapshot_check(&snapshot)); } +static void +no_mem_socket_send_and_sendto_and_sendmsg(int fd) +{ + struct sockaddr_in addr; + struct iovec iov; + struct msghdr msg; + ssize_t n; + char buf[1]; + + init_addr(&addr); + init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); + + errno = 0; + n = send(fd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == ENOMEM); + + errno = 0; + n = sendto(fd, &buf[0], sizeof(buf), 0, + (const struct sockaddr *) &addr, sizeof(addr)); + assert(n == -1); + assert(errno == ENOMEM); + + errno = 0; + n = sendmsg(fd, &msg, 0); + assert(n == -1); + assert(errno == ENOMEM); +} + +static void +test_socket_send_and_sendto_and_sendmsg(void) +{ + rtems_resource_snapshot snapshot; + struct sockaddr_in addr; + struct iovec iov; + struct msghdr msg; + int sd; + int rv; + ssize_t n; + char buf[1]; + + puts("test socket send, sendto and sendmsg"); + + rtems_resource_snapshot_take(&snapshot); + + init_addr(&addr); + init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); + + sd = socket(PF_INET, SOCK_DGRAM, 0); + assert(sd >= 0); + + do_no_mem_test(no_mem_socket_send_and_sendto_and_sendmsg, sd); + + errno = 0; + n = send(sd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == EDESTADDRREQ); + + errno = 0; + n = sendto(sd, &buf[0], sizeof(buf), 0, + (const struct sockaddr *) &addr, sizeof(addr)); + assert(n == -1); + assert(errno == ENETUNREACH); + + errno = 0; + n = sendmsg(sd, &msg, 0); + assert(n == -1); + assert(errno == ENETUNREACH); + + rv = close(sd); + assert(rv == 0); + + errno = 0; + n = send(sd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == EBADF); + + errno = 0; + n = sendto(sd, &buf[0], sizeof(buf), 0, + (const struct sockaddr *) &addr, sizeof(addr)); + assert(n == -1); + assert(errno == EBADF); + + errno = 0; + n = sendmsg(sd, &msg, 0); + assert(n == -1); + assert(errno == EBADF); + + assert(rtems_resource_snapshot_check(&snapshot)); +} + +static void +no_mem_socket_recv_and_recvfrom_and_recvmsg(int fd) +{ + struct sockaddr_in addr; + socklen_t addr_len; + struct iovec iov; + struct msghdr msg; + ssize_t n; + char buf[1]; + + init_addr(&addr); + init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); + + errno = 0; + n = recv(fd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == ENOMEM); + + errno = 0; + addr_len = sizeof(addr); + n = recvfrom(fd, &buf[0], sizeof(buf), 0, + (struct sockaddr *) &addr, &addr_len); + assert(n == -1); + assert(errno == ENOMEM); + + errno = 0; + n = recvmsg(fd, &msg, 0); + assert(n == -1); + assert(errno == ENOMEM); +} + +static void +test_socket_recv_and_recvfrom_and_recvmsg(void) +{ + rtems_resource_snapshot snapshot; + struct sockaddr_in addr; + socklen_t addr_len; + struct iovec iov; + struct msghdr msg; + int sd; + int rv; + ssize_t n; + char buf[1]; + int enable = 1; + + puts("test socket recv, recvfrom and recvmsg"); + + rtems_resource_snapshot_take(&snapshot); + + init_addr(&addr); + init_msg(&msg, &addr, &iov, &buf[0], sizeof(buf)); + + sd = socket(PF_INET, SOCK_DGRAM, 0); + assert(sd >= 0); + + rv = ioctl(sd, FIONBIO, &enable); + assert(rv == 0); + + do_no_mem_test(no_mem_socket_recv_and_recvfrom_and_recvmsg, sd); + + errno = 0; + n = recv(sd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == EAGAIN); + + errno = 0; + addr_len = sizeof(addr); + n = recvfrom(sd, &buf[0], sizeof(buf), 0, + (struct sockaddr *) &addr, &addr_len); + assert(n == -1); + assert(errno == EAGAIN); + + errno = 0; + n = recvmsg(sd, &msg, 0); + assert(n == -1); + assert(errno == EAGAIN); + + rv = close(sd); + assert(rv == 0); + + errno = 0; + n = recv(sd, &buf[0], sizeof(buf), 0); + assert(n == -1); + assert(errno == EBADF); + + errno = 0; + addr_len = sizeof(addr); + n = recvfrom(sd, &buf[0], sizeof(buf), 0, + (struct sockaddr *) &addr, &addr_len); + assert(n == -1); + assert(errno == EBADF); + + errno = 0; + n = recvmsg(sd, &msg, 0); + assert(n == -1); + assert(errno == EBADF); + + assert(rtems_resource_snapshot_check(&snapshot)); +} + static void test_main(void) { @@ -1013,6 +1218,8 @@ test_main(void) test_socket_getpeername(); test_socket_getsockname(); test_socket_read_and_write(); + test_socket_send_and_sendto_and_sendmsg(); + test_socket_recv_and_recvfrom_and_recvmsg(); puts("*** END OF " TEST_NAME " TEST ***"); exit(0);