The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/netbsd32/netbsd32_socket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: netbsd32_socket.c,v 1.33 2008/06/24 11:18:15 ad Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1998, 2001 Matthew R. Green
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.33 2008/06/24 11:18:15 ad Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #define msg __msg /* Don't ask me! */
   35 #include <sys/malloc.h>
   36 #include <sys/mount.h>
   37 #include <sys/socket.h>
   38 #include <sys/sockio.h>
   39 #include <sys/socketvar.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/ktrace.h>
   42 #include <sys/file.h>
   43 #include <sys/filedesc.h>
   44 #include <sys/syscallargs.h>
   45 #include <sys/proc.h>
   46 #include <sys/dirent.h>
   47 
   48 #include <compat/netbsd32/netbsd32.h>
   49 #include <compat/netbsd32/netbsd32_syscallargs.h>
   50 #include <compat/netbsd32/netbsd32_conv.h>
   51 
   52 /* note that the netbsd32_msghdr's iov really points to a struct iovec, not a netbsd32_iovec. */
   53 static int recvit32(struct lwp *, int, struct netbsd32_msghdr *, struct iovec *, void *,
   54                          register_t *);
   55 
   56 int
   57 netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap, register_t *retval)
   58 {
   59         /* {
   60                 syscallarg(int) s;
   61                 syscallarg(netbsd32_msghdrp_t) msg;
   62                 syscallarg(int) flags;
   63         } */
   64         struct netbsd32_msghdr msg;
   65         struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
   66         int error;
   67 
   68         error = copyin(SCARG_P32(uap, msg), &msg, sizeof(msg));
   69                 /* netbsd32_msghdr needs the iov pre-allocated */
   70         if (error)
   71                 return (error);
   72         if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
   73                 if ((u_int)msg.msg_iovlen > IOV_MAX)
   74                         return (EMSGSIZE);
   75                 iov = (struct iovec *)malloc(
   76                        sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
   77                        M_WAITOK);
   78         } else 
   79                 iov = aiov;
   80         msg.msg_flags = SCARG(uap, flags);
   81         uiov = (struct iovec *)NETBSD32PTR64(msg.msg_iov);
   82         error = netbsd32_to_iovecin((struct netbsd32_iovec *)uiov,
   83                                    iov, msg.msg_iovlen);
   84         if (error)
   85                 goto done;
   86         if ((error = recvit32(l, SCARG(uap, s), &msg, iov, (void *)0,
   87             retval)) == 0) {
   88                 error = copyout(&msg, SCARG_P32(uap, msg), sizeof(msg));
   89         }
   90 done:
   91         if (iov != aiov)
   92                 FREE(iov, M_IOV);
   93         return (error);
   94 }
   95 
   96 int
   97 recvit32(struct lwp *l, int s, struct netbsd32_msghdr *mp, struct iovec *iov, void *namelenp, register_t *retsize)
   98 {
   99         struct uio auio;
  100         int i, len, error, iovlen;
  101         struct mbuf *from = 0, *control = 0;
  102         struct socket *so;
  103         struct proc *p;
  104         struct iovec *ktriov = NULL;
  105         p = l->l_proc;
  106 
  107         /* fd_getsock() will use the descriptor for us */
  108         if ((error = fd_getsock(s, &so)) != 0)
  109                 return (error);
  110         auio.uio_iov = iov;
  111         auio.uio_iovcnt = mp->msg_iovlen;
  112         auio.uio_rw = UIO_READ;
  113         auio.uio_vmspace = l->l_proc->p_vmspace;
  114         auio.uio_offset = 0;                    /* XXX */
  115         auio.uio_resid = 0;
  116         for (i = 0; i < mp->msg_iovlen; i++, iov++) {
  117 #if 0
  118                 /* cannot happen iov_len is unsigned */
  119                 if (iov->iov_len < 0) {
  120                         error = EINVAL;
  121                         goto out1;
  122                 }
  123 #endif
  124                 /*
  125                  * Reads return ssize_t because -1 is returned on error.
  126                  * Therefore we must restrict the length to SSIZE_MAX to
  127                  * avoid garbage return values.
  128                  */
  129                 auio.uio_resid += iov->iov_len;
  130                 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
  131                         error = EINVAL;
  132                         goto out1;
  133                 }
  134         }
  135 
  136         if (ktrpoint(KTR_GENIO)) {
  137                 iovlen = auio.uio_iovcnt * sizeof(struct iovec);
  138                 ktriov = (struct iovec *)malloc(iovlen, M_TEMP, M_WAITOK);
  139                 memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
  140         }
  141 
  142         len = auio.uio_resid;
  143         error = (*so->so_receive)(so, &from, &auio, NULL,
  144                           NETBSD32PTR64(mp->msg_control) ? &control : NULL,
  145                           &mp->msg_flags);
  146         if (error) {
  147                 if (auio.uio_resid != len && (error == ERESTART ||
  148                     error == EINTR || error == EWOULDBLOCK))
  149                         error = 0;
  150         }
  151 
  152         if (ktriov != NULL) {
  153                 ktrgeniov(s, UIO_READ, ktriov, len - auio.uio_resid, error);
  154                 FREE(ktriov, M_TEMP);
  155         }
  156 
  157         if (error)
  158                 goto out;
  159         *retsize = len - auio.uio_resid;
  160         if (NETBSD32PTR64(mp->msg_name)) {
  161                 len = mp->msg_namelen;
  162                 if (len <= 0 || from == 0)
  163                         len = 0;
  164                 else {
  165                         if (len > from->m_len)
  166                                 len = from->m_len;
  167                         /* else if len < from->m_len ??? */
  168                         error = copyout(mtod(from, void *),
  169                             (void *)NETBSD32PTR64(mp->msg_name),
  170                             (unsigned)len);
  171                         if (error)
  172                                 goto out;
  173                 }
  174                 mp->msg_namelen = len;
  175                 if (namelenp &&
  176                     (error = copyout((void *)&len, namelenp, sizeof(int))))
  177                         goto out;
  178         }
  179         if (NETBSD32PTR64(mp->msg_control)) {
  180                 len = mp->msg_controllen;
  181                 if (len <= 0 || control == 0)
  182                         len = 0;
  183                 else {
  184                         struct mbuf *m = control;
  185                         void *cp = (void *)NETBSD32PTR64(mp->msg_control);
  186 
  187                         do {
  188                                 i = m->m_len;
  189                                 if (len < i) {
  190                                         mp->msg_flags |= MSG_CTRUNC;
  191                                         i = len;
  192                                 }
  193                                 error = copyout(mtod(m, void *), cp,
  194                                     (unsigned)i);
  195                                 if (m->m_next)
  196                                         i = ALIGN(i);
  197                                 cp = (char *)cp + i;
  198                                 len -= i;
  199                                 if (error != 0 || len <= 0)
  200                                         break;
  201                         } while ((m = m->m_next) != NULL);
  202                         len = (char *)cp - (char *)NETBSD32PTR64(mp->msg_control);
  203                 }
  204                 mp->msg_controllen = len;
  205         }
  206  out:
  207         if (from)
  208                 m_freem(from);
  209         if (control)
  210                 m_freem(control);
  211  out1:
  212         fd_putfile(s);
  213         return (error);
  214 }
  215 
  216 int
  217 netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap, register_t *retval)
  218 {
  219         /* {
  220                 syscallarg(int) s;
  221                 syscallarg(const netbsd32_msghdrp_t) msg;
  222                 syscallarg(int) flags;
  223         } */
  224         struct msghdr msg;
  225         struct netbsd32_msghdr msg32;
  226         struct iovec aiov[UIO_SMALLIOV], *iov;
  227         int error;
  228 
  229         error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
  230         if (error)
  231                 return (error);
  232         netbsd32_to_msghdr(&msg32, &msg);
  233 
  234         if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
  235                 if ((u_int)msg.msg_iovlen > IOV_MAX)
  236                         return (EMSGSIZE);
  237                 iov = (struct iovec *)malloc(
  238                        sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
  239                        M_WAITOK);
  240         } else if ((u_int)msg.msg_iovlen > 0)
  241                 iov = aiov;
  242         else
  243                 return (EMSGSIZE);
  244 
  245         error = netbsd32_to_iovecin((struct netbsd32_iovec *)msg.msg_iov,
  246                                    iov, msg.msg_iovlen);
  247         if (error)
  248                 goto done;
  249         msg.msg_iov = iov;
  250         msg.msg_flags = 0;
  251 
  252         /* Luckily we can use this directly */
  253         /* XXX: dsl (June'07) The cmsg alignment rules differ ! */
  254         error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
  255 done:
  256         if (iov != aiov)
  257                 FREE(iov, M_IOV);
  258         return (error);
  259 }
  260 
  261 int
  262 netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap, register_t *retval)
  263 {
  264         /* {
  265                 syscallarg(int) s;
  266                 syscallarg(netbsd32_voidp) buf;
  267                 syscallarg(netbsd32_size_t) len;
  268                 syscallarg(int) flags;
  269                 syscallarg(netbsd32_sockaddrp_t) from;
  270                 syscallarg(netbsd32_intp) fromlenaddr;
  271         } */
  272         struct netbsd32_msghdr msg;
  273         struct iovec aiov;
  274         int error;
  275 
  276         if (SCARG_P32(uap, fromlenaddr)) {
  277                 error = copyin(SCARG_P32(uap, fromlenaddr),
  278                     &msg.msg_namelen, sizeof(msg.msg_namelen));
  279                 if (error)
  280                         return (error);
  281         } else
  282                 msg.msg_namelen = 0;
  283         msg.msg_name = SCARG(uap, from);
  284         NETBSD32PTR32(msg.msg_iov, 0); /* ignored in recvit32(), uses iov */
  285         msg.msg_iovlen = 1;
  286         aiov.iov_base = SCARG_P32(uap, buf);
  287         aiov.iov_len = (u_long)SCARG(uap, len);
  288         NETBSD32PTR32(msg.msg_control, 0);
  289         msg.msg_flags = SCARG(uap, flags);
  290         return (recvit32(l, SCARG(uap, s), &msg, &aiov,
  291             SCARG_P32(uap, fromlenaddr), retval));
  292 }
  293 
  294 int
  295 netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap, register_t *retval)
  296 {
  297         /* {
  298                 syscallarg(int) s;
  299                 syscallarg(const netbsd32_voidp) buf;
  300                 syscallarg(netbsd32_size_t) len;
  301                 syscallarg(int) flags;
  302                 syscallarg(const netbsd32_sockaddrp_t) to;
  303                 syscallarg(int) tolen;
  304         } */
  305         struct msghdr msg;
  306         struct iovec aiov;
  307 
  308         msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */
  309         msg.msg_namelen = SCARG(uap, tolen);
  310         msg.msg_iov = &aiov;
  311         msg.msg_iovlen = 1;
  312         msg.msg_control = 0;
  313         aiov.iov_base = SCARG_P32(uap, buf);    /* XXX kills const */
  314         aiov.iov_len = SCARG(uap, len);
  315         msg.msg_flags = 0;
  316         return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
  317 }

Cache object: 3793b2f941dc97e766303a9779987abf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.