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/emulation/43bsd/43bsd_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 /*
    2  * 43BSD_SOCKET.C       - 4.3BSD compatibility socket syscalls
    3  *
    4  * Copyright (c) 1982, 1986, 1989, 1990, 1993
    5  *      The Regents of the University of California.  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  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by the University of
   18  *      California, Berkeley and its contributors.
   19  * 4. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  * The original versions of these syscalls used to live in
   36  * kern/uipc_syscalls.c.  These are heavily modified to use the
   37  * new split syscalls.
   38  */
   39 
   40 #include "opt_compat.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/sysproto.h>
   46 #include <sys/kern_syscall.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/proc.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 #include <sys/uio.h>
   53 
   54 #include <sys/mplock2.h>
   55 
   56 #include "43bsd_socket.h"
   57 
   58 /*
   59  * System call interface to the socket abstraction.
   60  */
   61 
   62 static int
   63 compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
   64 {
   65         struct sockaddr *sa;
   66         int error;
   67 
   68         *namp = NULL;
   69         if (len > SOCK_MAXADDRLEN)
   70                 return ENAMETOOLONG;
   71         if (len < offsetof(struct sockaddr, sa_data[0]))
   72                 return EDOM;
   73         sa = kmalloc(len, M_SONAME, M_WAITOK);
   74         error = copyin(uaddr, sa, len);
   75         if (error) {
   76                 kfree(sa, M_SONAME);
   77         } else {
   78                 /*
   79                  * Convert to the 4.4BSD sockaddr structure.
   80                  */
   81                 sa->sa_family = sa->sa_len;
   82                 sa->sa_len = len;
   83                 *namp = sa;
   84         }
   85         return error;
   86 }
   87 
   88 static int
   89 compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
   90 {
   91         int error;
   92 
   93         ((struct osockaddr *)sa)->sa_family = sa->sa_family;
   94         error = copyout(sa, uaddr, sa_len);
   95 
   96         return (error);
   97 }
   98 
   99 /*
  100  * MPALMOSTSAFE
  101  */
  102 int
  103 sys_oaccept(struct accept_args *uap)
  104 {
  105         struct sockaddr *sa = NULL;
  106         int sa_len;
  107         int error;
  108 
  109         if (uap->name) {
  110                 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
  111                 if (error)
  112                         return (error);
  113 
  114                 get_mplock();
  115                 error = kern_accept(uap->s, 0, &sa, &sa_len,
  116                                     &uap->sysmsg_iresult);
  117                 rel_mplock();
  118 
  119                 if (error) {
  120                         /*
  121                          * return a namelen of zero for older code which
  122                          * might ignore the return value from accept.
  123                          */
  124                         sa_len = 0;
  125                         copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
  126                 } else {
  127                         compat_43_copyout_sockaddr(sa, uap->name, sa_len);
  128                         if (error == 0) {
  129                                 error = copyout(&sa_len, uap->anamelen,
  130                                     sizeof(*uap->anamelen));
  131                         }
  132                 }
  133                 if (sa)
  134                         kfree(sa, M_SONAME);
  135         } else {
  136                 get_mplock();
  137                 error = kern_accept(uap->s, 0, NULL, 0, &uap->sysmsg_iresult);
  138                 rel_mplock();
  139         }
  140         return (error);
  141 }
  142 
  143 /*
  144  * MPALMOSTSAFE
  145  */
  146 int
  147 sys_ogetsockname(struct getsockname_args *uap)
  148 {
  149         struct sockaddr *sa = NULL;
  150         int error, sa_len;
  151 
  152         error = copyin(uap->alen, &sa_len, sizeof(sa_len));
  153         if (error)
  154                 return (error);
  155 
  156         get_mplock();
  157         error = kern_getsockname(uap->fdes, &sa, &sa_len);
  158         rel_mplock();
  159 
  160         if (error == 0)
  161                 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
  162         if (error == 0) {
  163                 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
  164         }
  165         if (sa)
  166                 kfree(sa, M_SONAME);
  167         return (error);
  168 }
  169 
  170 /*
  171  * MPALMOSTSAFE
  172  */
  173 int
  174 sys_ogetpeername(struct ogetpeername_args *uap)
  175 {
  176         struct sockaddr *sa = NULL;
  177         int error, sa_len;
  178 
  179         error = copyin(uap->alen, &sa_len, sizeof(sa_len));
  180         if (error)
  181                 return (error);
  182 
  183         get_mplock();
  184         error = kern_getpeername(uap->fdes, &sa, &sa_len);
  185         rel_mplock();
  186 
  187         if (error == 0) {
  188                 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
  189         }
  190         if (error == 0)
  191                 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
  192         if (sa)
  193                 kfree(sa, M_SONAME);
  194         return (error);
  195 }
  196 
  197 /*
  198  * MPALMOSTSAFE
  199  */
  200 int
  201 sys_osend(struct osend_args *uap)
  202 {
  203         struct thread *td = curthread;
  204         struct uio auio;
  205         struct iovec aiov;
  206         int error;
  207 
  208         aiov.iov_base = uap->buf;
  209         aiov.iov_len = uap->len;
  210         auio.uio_iov = &aiov;
  211         auio.uio_iovcnt = 1;
  212         auio.uio_offset = 0;
  213         auio.uio_resid = uap->len;
  214         auio.uio_segflg = UIO_USERSPACE;
  215         auio.uio_rw = UIO_WRITE;
  216         auio.uio_td = td;
  217 
  218         get_mplock();
  219         error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
  220                              &uap->sysmsg_szresult);
  221         rel_mplock();
  222 
  223         return (error);
  224 }
  225 
  226 /*
  227  * MPALMOSTSAFE
  228  */
  229 int
  230 sys_osendmsg(struct osendmsg_args *uap)
  231 {
  232         struct thread *td = curthread;
  233         struct msghdr msg;
  234         struct uio auio;
  235         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
  236         struct sockaddr *sa = NULL;
  237         struct mbuf *control = NULL;
  238         struct cmsghdr *cm;
  239         int error;
  240 
  241         error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
  242         if (error)
  243                 return (error);
  244 
  245         /*
  246          * Conditionally copyin msg.msg_name.
  247          */
  248         if (msg.msg_name) {
  249                 error = compat_43_getsockaddr(&sa, msg.msg_name,
  250                     msg.msg_namelen);
  251                 if (error)
  252                         return (error);
  253         }
  254 
  255         /*
  256          * Populate auio.
  257          */
  258         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
  259                              &auio.uio_resid);
  260         if (error)
  261                 goto cleanup2;
  262         auio.uio_iov = iov;
  263         auio.uio_iovcnt = msg.msg_iovlen;
  264         auio.uio_offset = 0;
  265         auio.uio_segflg = UIO_USERSPACE;
  266         auio.uio_rw = UIO_WRITE;
  267         auio.uio_td = td;
  268 
  269         /*
  270          * Conditionally copyin msg.msg_control.
  271          */
  272         if (msg.msg_control) {
  273                 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
  274                         error = EINVAL;
  275                         goto cleanup;
  276                 }
  277                 control = m_get(MB_WAIT, MT_CONTROL);
  278                 if (control == NULL) {
  279                         error = ENOBUFS;
  280                         goto cleanup;
  281                 }
  282                 control->m_len = msg.msg_controllen;
  283                 error = copyin(msg.msg_control, mtod(control, caddr_t),
  284                     msg.msg_controllen);
  285                 if (error) {
  286                         m_free(control);
  287                         goto cleanup;
  288                 }
  289                 /*
  290                  * In 4.3BSD, the only type of ancillary data was
  291                  * access rights and this data did not use a header
  292                  * to identify it's type.  Thus, we must prepend the
  293                  * control data with the proper cmsghdr structure
  294                  * so that the kernel recognizes it as access rights.
  295                  */
  296                 M_PREPEND(control, sizeof(*cm), MB_WAIT);
  297                 if (control == NULL) {
  298                         error = ENOBUFS;
  299                         goto cleanup;
  300                 } else {
  301                         cm = mtod(control, struct cmsghdr *);
  302                         cm->cmsg_len = control->m_len;
  303                         cm->cmsg_level = SOL_SOCKET;
  304                         cm->cmsg_type = SCM_RIGHTS;
  305                 }
  306         }
  307 
  308         get_mplock();
  309         error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
  310                              &uap->sysmsg_szresult);
  311         rel_mplock();
  312 
  313 cleanup:
  314         iovec_free(&iov, aiov);
  315 cleanup2:
  316         if (sa)
  317                 kfree(sa, M_SONAME);
  318         return (error);
  319 }
  320 
  321 /*
  322  * MPALMOSTSAFE
  323  */
  324 int
  325 sys_orecv(struct orecv_args *uap)
  326 {
  327         struct thread *td = curthread;
  328         struct uio auio;
  329         struct iovec aiov;
  330         int error;
  331 
  332         aiov.iov_base = uap->buf;
  333         aiov.iov_len = uap->len;
  334         auio.uio_iov = &aiov;
  335         auio.uio_iovcnt = 1;
  336         auio.uio_offset = 0;
  337         auio.uio_resid = uap->len;
  338         auio.uio_segflg = UIO_USERSPACE;
  339         auio.uio_rw = UIO_READ;
  340         auio.uio_td = td;
  341 
  342         get_mplock();
  343         error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
  344                              &uap->sysmsg_szresult);
  345         rel_mplock();
  346 
  347         return (error);
  348 }
  349 
  350 /*
  351  * MPALMOSTSAFE
  352  */
  353 int
  354 sys_orecvfrom(struct recvfrom_args *uap)
  355 {
  356         struct thread *td = curthread;
  357         struct uio auio;
  358         struct iovec aiov;
  359         struct sockaddr *sa = NULL;
  360         int error, fromlen;
  361 
  362         if (uap->from && uap->fromlenaddr) {
  363                 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
  364                 if (error)
  365                         return (error);
  366                 if (fromlen < 0)
  367                         return (EINVAL);
  368         } else {
  369                 fromlen = 0;
  370         }
  371         aiov.iov_base = uap->buf;
  372         aiov.iov_len = uap->len;
  373         auio.uio_iov = &aiov;
  374         auio.uio_iovcnt = 1;
  375         auio.uio_offset = 0;
  376         auio.uio_resid = uap->len;
  377         auio.uio_segflg = UIO_USERSPACE;
  378         auio.uio_rw = UIO_READ;
  379         auio.uio_td = td;
  380 
  381         get_mplock();
  382         error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
  383                              &uap->flags, &uap->sysmsg_szresult);
  384         rel_mplock();
  385 
  386         if (error == 0 && uap->from) {
  387                 if (sa != NULL) {
  388                         fromlen = MIN(fromlen, sa->sa_len);
  389                         error = compat_43_copyout_sockaddr(sa, uap->from,
  390                                                            fromlen);
  391                 } else
  392                         fromlen = 0;
  393                 if (error == 0)
  394                         /*
  395                          * Old recvfrom didn't signal an error if this
  396                          * next copyout failed.
  397                          */
  398                         copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
  399         }
  400         if (sa)
  401                 kfree(sa, M_SONAME);
  402 
  403         return (error);
  404 }
  405 
  406 /*
  407  * MPALMOSTSAFE
  408  */
  409 int
  410 sys_orecvmsg(struct orecvmsg_args *uap)
  411 {
  412         struct thread *td = curthread;
  413         struct msghdr msg;
  414         struct uio auio;
  415         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
  416         struct mbuf *m, *control = NULL;
  417         struct sockaddr *sa = NULL;
  418         caddr_t ctlbuf;
  419         socklen_t *ufromlenp, *ucontrollenp;
  420         int error, fromlen, controllen, len, flags, *uflagsp;
  421 
  422         /*
  423          * This copyin handles everything except the iovec.
  424          */
  425         error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
  426         if (error)
  427                 return (error);
  428 
  429         if (msg.msg_name && msg.msg_namelen < 0)
  430                 return (EINVAL);
  431         if (msg.msg_control && msg.msg_controllen < 0)
  432                 return (EINVAL);
  433 
  434         ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
  435             msg_namelen));
  436         ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
  437             msg_controllen));
  438         uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
  439             msg_flags));
  440 
  441         /*
  442          * Populate auio.
  443          */
  444         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
  445                              &auio.uio_resid);
  446         if (error)
  447                 return (error);
  448         auio.uio_iov = iov;
  449         auio.uio_iovcnt = msg.msg_iovlen;
  450         auio.uio_offset = 0;
  451         auio.uio_segflg = UIO_USERSPACE;
  452         auio.uio_rw = UIO_READ;
  453         auio.uio_td = td;
  454 
  455         flags = msg.msg_flags;
  456 
  457         get_mplock();
  458         error = kern_recvmsg(uap->s, (msg.msg_name ? &sa : NULL), &auio,
  459                              (msg.msg_control ? &control : NULL), &flags,
  460                              &uap->sysmsg_szresult);
  461         rel_mplock();
  462 
  463         /*
  464          * Copyout msg.msg_name and msg.msg_namelen.
  465          */
  466         if (error == 0 && msg.msg_name) {
  467                 if (sa != NULL) {
  468                         fromlen = MIN(msg.msg_namelen, sa->sa_len);
  469                         error = compat_43_copyout_sockaddr(sa, msg.msg_name,
  470                                                            fromlen);
  471                 } else
  472                         fromlen = 0;
  473                 if (error == 0)
  474                         /*
  475                          * Old recvfrom didn't signal an error if this
  476                          * next copyout failed.
  477                          */
  478                         copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
  479         }
  480 
  481         /*
  482          * Copyout msg.msg_control and msg.msg_controllen.
  483          */
  484         if (error == 0 && msg.msg_control) {
  485                 /*
  486                  * If we receive access rights, trim the cmsghdr; anything
  487                  * else is tossed.
  488                  */
  489                 if (mtod((struct mbuf *)msg.msg_control,
  490                     struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
  491                     mtod((struct mbuf *)msg.msg_control,
  492                     struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
  493                         int temp = 0;
  494                         error = copyout(&temp, ucontrollenp,
  495                             sizeof(*ucontrollenp));
  496                         goto cleanup;
  497                 }
  498                 ((struct mbuf *)msg.msg_control)->m_len -=
  499                     sizeof(struct cmsghdr);
  500                 ((struct mbuf *)msg.msg_control)->m_data +=
  501                     sizeof(struct cmsghdr);
  502 
  503                 len = msg.msg_controllen;
  504                 m = control;
  505                 ctlbuf = (caddr_t)msg.msg_control;
  506 
  507                 while(m && len > 0) {
  508                         unsigned int tocopy;
  509 
  510                         if (len >= m->m_len) {
  511                                 tocopy = m->m_len;
  512                         } else {
  513                                 msg.msg_flags |= MSG_CTRUNC;
  514                                 tocopy = len;
  515                         }
  516 
  517                         error = copyout(mtod(m, caddr_t), ctlbuf,
  518                             tocopy);
  519                         if (error)
  520                                 goto cleanup;
  521 
  522                         ctlbuf += tocopy;
  523                         len -= tocopy;
  524                         m = m->m_next;
  525                 }
  526                 controllen = ctlbuf - (caddr_t)msg.msg_control;
  527                 error = copyout(&controllen, ucontrollenp,
  528                     sizeof(*ucontrollenp));
  529         }
  530 
  531         if (error == 0)
  532                 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
  533 
  534 cleanup:
  535         if (sa)
  536                 kfree(sa, M_SONAME);
  537         iovec_free(&iov, aiov);
  538         if (control)
  539                 m_freem(control);
  540         return (error);
  541 }
  542 

Cache object: 0a1a5d157df1d045a845a336484bb12f


[ 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.