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/linux/linux_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  * Copyright (c) 1995 Søren Schmidt
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer 
   10  *    in this position and unchanged.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.19.2.8 2001/11/07 20:33:55 marcel Exp $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/proc.h>
   33 #include <sys/systm.h>
   34 #include <sys/sysproto.h>
   35 #include <sys/fcntl.h>
   36 #include <sys/file.h>
   37 #include <sys/kern_syscall.h>
   38 #include <sys/socket.h>
   39 #include <sys/socketvar.h>
   40 #include <sys/uio.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/un.h>
   44 
   45 #include <sys/mplock2.h>
   46 
   47 #include <netinet/in.h>
   48 #include <netinet/in_systm.h>
   49 #include <netinet/ip.h>
   50 
   51 #include <arch_linux/linux.h>
   52 #include <arch_linux/linux_proto.h>
   53 #include "linux_socket.h"
   54 #include "linux_util.h"
   55 
   56 /*
   57  * Copyin a sockaddr structure provided by a Linux binary.  Linux uses
   58  * the 4.3BSD sockaddr structure which has no sa_len field.  We must
   59  * pass 4.4BSD sockaddr structures when we call native functions in the
   60  * BSD kernel.  This function does the conversion for us.
   61  *
   62  * Also, our socket calls require the sockaddr structure length to agree
   63  * with the address family.  Linux does not, so we must force it.
   64  *
   65  * This function should only need to be called from linux_connect()
   66  * and linux_bind().
   67  */
   68 static int
   69 linux_getsockaddr(struct sockaddr **namp, struct sockaddr *uaddr, size_t len)
   70 {
   71         struct sockaddr *sa;
   72         uint16_t family;        /* XXX: must match Linux sockaddr */
   73         int error;
   74         int sa_len;
   75 
   76         *namp = NULL;
   77 
   78         if (len > SOCK_MAXADDRLEN)
   79                 return ENAMETOOLONG;
   80         error = copyin(uaddr, &family, sizeof(family));
   81         if (error)
   82                 return (error);
   83 
   84         /*
   85          * Force the sa_len field to match the address family.
   86          */
   87         switch (family) {
   88         case AF_INET:
   89                 sa_len = sizeof(struct sockaddr_in);
   90                 break;
   91         case AF_INET6:
   92                 sa_len = sizeof(struct sockaddr_in6);
   93                 break;
   94         default:
   95                 /*
   96                  * This is the default behavior of the old
   97                  * linux_to_bsd_namelen() function.  NOTE!  The
   98                  * minimum length we allocate must cover sa->sa_len and
   99                  * sa->sa_family.
  100                  */
  101                 sa_len = offsetof(struct sockaddr, sa_data[0]);
  102                 if (sa_len < len)
  103                         sa_len = len;
  104                 break;
  105         }
  106 
  107         sa = kmalloc(sa_len, M_SONAME, M_WAITOK);
  108         error = copyin(uaddr, sa, sa_len);
  109         if (error) {
  110                 kfree(sa, M_SONAME);
  111         } else {
  112                 /*
  113                  * Convert to the 4.4BSD sockaddr structure.
  114                  */
  115                 sa->sa_family = *(sa_family_t *)sa;
  116                 sa->sa_len = sa_len;
  117                 *namp = sa;
  118         }
  119 
  120         return (error);
  121 }
  122 
  123 /*
  124  * Transform a 4.4BSD sockaddr structure into a Linux sockaddr structure
  125  * and copy it out to a user address.
  126  */
  127 static int
  128 linux_copyout_sockaddr(struct sockaddr *sa, struct sockaddr *uaddr, int sa_len)
  129 {
  130         int error;
  131 
  132         if (sa_len < (int)sizeof(u_short))
  133                 return (EINVAL);
  134 
  135         *(u_short *)sa = sa->sa_family;
  136         error = copyout(sa, uaddr, sa_len);
  137 
  138         return (error);
  139 }
  140  
  141 static int
  142 linux_to_bsd_domain(int domain)
  143 {
  144 
  145         switch (domain) {
  146         case LINUX_AF_UNSPEC:
  147                 return (AF_UNSPEC);
  148         case LINUX_AF_UNIX:
  149                 return (AF_LOCAL);
  150         case LINUX_AF_INET:
  151                 return (AF_INET);
  152         case LINUX_AF_AX25:
  153                 return (AF_CCITT);
  154         case LINUX_AF_IPX:
  155                 return (AF_IPX);
  156         }
  157         return (-1);
  158 }
  159 
  160 static int
  161 linux_to_bsd_sockopt_level(int level)
  162 {
  163 
  164         switch (level) {
  165         case LINUX_SOL_SOCKET:
  166                 return (SOL_SOCKET);
  167         }
  168         return (level);
  169 }
  170 
  171 static int
  172 linux_to_bsd_ip_sockopt(int opt)
  173 {
  174 
  175         switch (opt) {
  176         case LINUX_IP_TOS:
  177                 return (IP_TOS);
  178         case LINUX_IP_TTL:
  179                 return (IP_TTL);
  180         case LINUX_IP_OPTIONS:
  181                 return (IP_OPTIONS);
  182         case LINUX_IP_MULTICAST_IF:
  183                 return (IP_MULTICAST_IF);
  184         case LINUX_IP_MULTICAST_TTL:
  185                 return (IP_MULTICAST_TTL);
  186         case LINUX_IP_MULTICAST_LOOP:
  187                 return (IP_MULTICAST_LOOP);
  188         case LINUX_IP_ADD_MEMBERSHIP:
  189                 return (IP_ADD_MEMBERSHIP);
  190         case LINUX_IP_DROP_MEMBERSHIP:
  191                 return (IP_DROP_MEMBERSHIP);
  192         case LINUX_IP_HDRINCL:
  193                 return (IP_HDRINCL);
  194         }
  195         return (-1);
  196 }
  197 
  198 static int
  199 linux_to_bsd_so_sockopt(int opt)
  200 {
  201 
  202         switch (opt) {
  203         case LINUX_SO_DEBUG:
  204                 return (SO_DEBUG);
  205         case LINUX_SO_REUSEADDR:
  206                 return (SO_REUSEADDR);
  207         case LINUX_SO_TYPE:
  208                 return (SO_TYPE);
  209         case LINUX_SO_ERROR:
  210                 return (SO_ERROR);
  211         case LINUX_SO_DONTROUTE:
  212                 return (SO_DONTROUTE);
  213         case LINUX_SO_BROADCAST:
  214                 return (SO_BROADCAST);
  215         case LINUX_SO_SNDBUF:
  216                 return (SO_SNDBUF);
  217         case LINUX_SO_RCVBUF:
  218                 return (SO_RCVBUF);
  219         case LINUX_SO_KEEPALIVE:
  220                 return (SO_KEEPALIVE);
  221         case LINUX_SO_OOBINLINE:
  222                 return (SO_OOBINLINE);
  223         case LINUX_SO_LINGER:
  224                 return (SO_LINGER);
  225         case LINUX_SO_PEERCRED:
  226                 return (LOCAL_PEERCRED);
  227         }
  228         return (-1);
  229 }
  230 
  231 static int
  232 linux_to_bsd_msg_flags(int flags)
  233 {
  234         int ret_flags = 0;
  235 
  236         if (flags & LINUX_MSG_OOB)
  237                 ret_flags |= MSG_OOB;
  238         if (flags & LINUX_MSG_PEEK)
  239                 ret_flags |= MSG_PEEK;
  240         if (flags & LINUX_MSG_DONTROUTE)
  241                 ret_flags |= MSG_DONTROUTE;
  242         if (flags & LINUX_MSG_CTRUNC)
  243                 ret_flags |= MSG_CTRUNC;
  244         if (flags & LINUX_MSG_TRUNC)
  245                 ret_flags |= MSG_TRUNC;
  246         if (flags & LINUX_MSG_DONTWAIT)
  247                 ret_flags |= MSG_DONTWAIT;
  248         if (flags & LINUX_MSG_EOR)
  249                 ret_flags |= MSG_EOR;
  250         if (flags & LINUX_MSG_WAITALL)
  251                 ret_flags |= MSG_WAITALL;
  252 #if 0 /* not handled */
  253         if (flags & LINUX_MSG_PROXY)
  254                 ;
  255         if (flags & LINUX_MSG_FIN)
  256                 ;
  257         if (flags & LINUX_MSG_SYN)
  258                 ;
  259         if (flags & LINUX_MSG_CONFIRM)
  260                 ;
  261         if (flags & LINUX_MSG_RST)
  262                 ;
  263         if (flags & LINUX_MSG_ERRQUEUE)
  264                 ;
  265         if (flags & LINUX_MSG_NOSIGNAL)
  266                 ;
  267 #endif
  268         return ret_flags;
  269 }
  270 
  271 struct linux_socket_args {
  272         int domain;
  273         int type;
  274         int protocol;
  275 };
  276 
  277 static int
  278 linux_socket(struct linux_socket_args *args, int *res)
  279 {
  280         struct linux_socket_args linux_args;
  281         struct sockopt sopt;
  282         int error, domain, optval;
  283 
  284         error = copyin(args, &linux_args, sizeof(linux_args));
  285         if (error)
  286                 return (error);
  287 
  288         domain = linux_to_bsd_domain(linux_args.domain);
  289         if (domain == -1)
  290                 return (EINVAL);
  291 
  292         error = kern_socket(domain, linux_args.type, linux_args.protocol, res);
  293 
  294         /* Copy back the return value from socket() */
  295         if (error == 0 && linux_args.type == SOCK_RAW &&
  296             (linux_args.protocol == IPPROTO_RAW || linux_args.protocol == 0) &&
  297             linux_args.domain == AF_INET) {
  298                 /* It's a raw IP socket: set the IP_HDRINCL option. */
  299                 optval = 1;
  300                 sopt.sopt_dir = SOPT_SET;
  301                 sopt.sopt_level = IPPROTO_IP;
  302                 sopt.sopt_name = IP_HDRINCL;
  303                 sopt.sopt_val = &optval;
  304                 sopt.sopt_valsize = sizeof(optval);
  305                 sopt.sopt_td = NULL;
  306 
  307                 /* We ignore any error returned by setsockopt() */
  308                 kern_setsockopt(*res, &sopt);
  309         }
  310 
  311         return (error);
  312 }
  313 
  314 struct linux_bind_args {
  315         int s;
  316         struct sockaddr *name;
  317         int namelen;
  318 };
  319 
  320 static int
  321 linux_bind(struct linux_bind_args *args, int *res)
  322 {
  323         struct linux_bind_args linux_args;
  324         struct sockaddr *sa;
  325         int error;
  326 
  327         error = copyin(args, &linux_args, sizeof(linux_args));
  328         if (error)
  329                 return (error);
  330         error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
  331         if (error)
  332                 return (error);
  333 
  334         error = kern_bind(linux_args.s, sa);
  335         kfree(sa, M_SONAME);
  336 
  337         return (error);
  338 }
  339 
  340 struct linux_connect_args {
  341         int s;
  342         struct sockaddr * name;
  343         int namelen;
  344 };
  345 
  346 static int
  347 linux_connect(struct linux_connect_args *args, int *res)
  348 {
  349         struct thread *td = curthread;  /* XXX */
  350         struct proc *p = td->td_proc;
  351         struct linux_connect_args linux_args;
  352         struct sockaddr *sa;
  353         struct socket *so;
  354         struct file *fp;
  355         int error;
  356 
  357         KKASSERT(p);
  358 
  359         error = copyin(args, &linux_args, sizeof(linux_args));
  360         if (error)
  361                 return (error);
  362         error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
  363         if (error)
  364                 return (error);
  365 
  366         error = kern_connect(linux_args.s, 0, sa);
  367         kfree(sa, M_SONAME);
  368 
  369         if (error != EISCONN)
  370                 return (error);
  371 
  372         /*
  373          * Linux doesn't return EISCONN the first time it occurs,
  374          * when on a non-blocking socket. Instead it returns the
  375          * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
  376          */
  377         error = holdsock(p->p_fd, linux_args.s, &fp);
  378         if (error)
  379                 return (error);
  380         error = EISCONN;
  381         if (fp->f_flag & FNONBLOCK) {
  382                 so = (struct socket *)fp->f_data;
  383                 if (so->so_emuldata == 0)
  384                         error = so->so_error;
  385                 so->so_emuldata = (void *)1;
  386         }
  387         fdrop(fp);
  388         return (error);
  389 }
  390 
  391 struct linux_listen_args {
  392         int s;
  393         int backlog;
  394 };
  395 
  396 static int
  397 linux_listen(struct linux_listen_args *args, int *res)
  398 {
  399         struct linux_listen_args linux_args;
  400         int error;
  401 
  402         error = copyin(args, &linux_args, sizeof(linux_args));
  403         if (error)
  404                 return (error);
  405 
  406         error = kern_listen(linux_args.s, linux_args.backlog);
  407 
  408         return(error);
  409 }
  410 
  411 struct linux_accept_args {
  412         int s;
  413         struct sockaddr *addr;
  414         int *namelen;
  415 };
  416 
  417 static int
  418 linux_accept(struct linux_accept_args *args, int *res)
  419 {
  420         struct thread *td = curthread;
  421         struct linux_accept_args linux_args;
  422         struct sockaddr *sa = NULL;
  423         union fcntl_dat dat = { 0 };
  424         int error, sa_len;
  425 
  426         error = copyin(args, &linux_args, sizeof(linux_args));
  427         if (error)
  428                 return (error);
  429 
  430         if (linux_args.addr) {
  431                 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
  432                 if (error)
  433                         return (error);
  434 
  435                 error = kern_accept(linux_args.s, 0, &sa, &sa_len, res);
  436 
  437                 if (error) {
  438                         /*
  439                          * Return a namelen of zero for older code which
  440                          * might ignore the return value from accept().
  441                          */
  442                         sa_len = 0;
  443                         copyout(&sa_len, linux_args.namelen,
  444                             sizeof(*linux_args.namelen));
  445                 } else {
  446                         error = linux_copyout_sockaddr(sa, linux_args.addr,
  447                             sa_len);
  448                         if (error == 0) {
  449                                 error = copyout(&sa_len, linux_args.namelen,
  450                                     sizeof(*linux_args.namelen));
  451                         }
  452                 }
  453                 if (sa)
  454                         kfree(sa, M_SONAME);
  455         } else {
  456                 error = kern_accept(linux_args.s, 0, NULL, 0, res);
  457         }
  458 
  459         if (error)
  460                 return (error);
  461 
  462         /*
  463          * linux appears not to copy flags from the parent socket to the
  464          * accepted one, so we must clear the flags in the new descriptor.
  465          * Ignore any errors, because we already have an open fd.
  466          */
  467         kern_fcntl(*res, F_SETFL, &dat, td->td_ucred);
  468         return (0);
  469 }
  470 
  471 struct linux_getsockname_args {
  472         int s;
  473         struct sockaddr *addr;
  474         int *namelen;
  475 };
  476 
  477 static int
  478 linux_getsockname(struct linux_getsockname_args *args, int *res)
  479 {
  480         struct linux_getsockname_args linux_args;
  481         struct sockaddr *sa = NULL;
  482         int error, sa_len;
  483          
  484 
  485         error = copyin(args, &linux_args, sizeof(linux_args));
  486         if (error)
  487                 return (error);
  488         error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
  489         if (error)
  490                 return (error);
  491 
  492         error = kern_getsockname(linux_args.s, &sa, &sa_len);
  493 
  494         if (error == 0)
  495                 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
  496         if (error == 0)
  497                 error = copyout(&sa_len, linux_args.namelen,
  498                     sizeof(*linux_args.namelen));
  499         if (sa)
  500                 kfree(sa, M_SONAME);
  501         return(error);
  502 }
  503 
  504 struct linux_getpeername_args {
  505         int s;
  506         struct sockaddr *addr;
  507         int *namelen;
  508 };
  509 
  510 static int
  511 linux_getpeername(struct linux_getpeername_args *args, int *res)
  512 {
  513         struct linux_getpeername_args linux_args;
  514         struct sockaddr *sa = NULL;
  515         int error, sa_len;
  516 
  517         error = copyin(args, &linux_args, sizeof(linux_args));
  518         if (error)
  519                 return (error);
  520         error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
  521         if (error)
  522                 return (error);
  523 
  524         error = kern_getpeername(linux_args.s, &sa, &sa_len);
  525 
  526         if (error == 0)
  527                 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
  528         if (error == 0)
  529                 error = copyout(&sa_len, linux_args.namelen,
  530                     sizeof(*linux_args.namelen));
  531         if (sa)
  532                 kfree(sa, M_SONAME);
  533         return(error);
  534 }
  535 
  536 struct linux_socketpair_args {
  537         int domain;
  538         int type;
  539         int protocol;
  540         int *rsv;
  541 };
  542 
  543 static int
  544 linux_socketpair(struct linux_socketpair_args *args, int *res)
  545 {
  546         struct linux_socketpair_args linux_args;
  547         int error, domain, sockv[2];
  548 
  549         error = copyin(args, &linux_args, sizeof(linux_args));
  550         if (error)
  551                 return (error);
  552 
  553         domain = linux_to_bsd_domain(linux_args.domain);
  554         if (domain == -1)
  555                 return (EINVAL);
  556         error = kern_socketpair(domain, linux_args.type, linux_args.protocol,
  557             sockv);
  558 
  559         if (error == 0)
  560                 error = copyout(sockv, linux_args.rsv, sizeof(sockv));
  561         return(error);
  562 }
  563 
  564 struct linux_send_args {
  565         int s;
  566         void *msg;
  567         int len;
  568         int flags;
  569 };
  570 
  571 static int
  572 linux_send(struct linux_send_args *args, size_t *res)
  573 {
  574         struct linux_send_args linux_args;
  575         struct thread *td = curthread;
  576         struct uio auio;
  577         struct iovec aiov;
  578         int error;
  579 
  580         error = copyin(args, &linux_args, sizeof(linux_args));
  581         if (error)
  582                 return (error);
  583 
  584         aiov.iov_base = linux_args.msg;
  585         aiov.iov_len = linux_args.len;
  586         auio.uio_iov = &aiov;
  587         auio.uio_iovcnt = 1;
  588         auio.uio_offset = 0;
  589         auio.uio_resid = linux_args.len;
  590         auio.uio_segflg = UIO_USERSPACE;
  591         auio.uio_rw = UIO_WRITE;
  592         auio.uio_td = td;
  593 
  594         error = kern_sendmsg(linux_args.s, NULL, &auio, NULL,
  595                              linux_args.flags, res);
  596 
  597         return(error);
  598 }
  599 
  600 struct linux_recv_args {
  601         int s;
  602         void *msg;
  603         int len;
  604         int flags;
  605 };
  606 
  607 static int
  608 linux_recv(struct linux_recv_args *args, size_t *res)
  609 {
  610         struct linux_recv_args linux_args;
  611         struct thread *td = curthread;
  612         struct uio auio;
  613         struct iovec aiov;
  614         int error;
  615 
  616         error = copyin(args, &linux_args, sizeof(linux_args));
  617         if (error)
  618                 return (error);
  619 
  620         aiov.iov_base = linux_args.msg;
  621         aiov.iov_len = linux_args.len;
  622         auio.uio_iov = &aiov;
  623         auio.uio_iovcnt = 1;
  624         auio.uio_offset = 0;
  625         auio.uio_resid = linux_args.len;
  626         auio.uio_segflg = UIO_USERSPACE;
  627         auio.uio_rw = UIO_READ;
  628         auio.uio_td = td;
  629 
  630         error = kern_recvmsg(linux_args.s, NULL, &auio, NULL,
  631                              &linux_args.flags, res);
  632 
  633         return(error);
  634 }
  635 
  636 struct linux_sendto_args {
  637         int s;
  638         void *msg;
  639         int len;
  640         int flags;
  641         struct sockaddr *to;
  642         int tolen;
  643 };
  644 
  645 static int
  646 linux_sendto(struct linux_sendto_args *args, size_t *res)
  647 {
  648         struct linux_sendto_args linux_args;
  649         struct thread *td = curthread;
  650         struct uio auio;
  651         struct iovec aiov;
  652         struct sockopt sopt;
  653         struct sockaddr *sa = NULL;
  654         caddr_t msg = NULL;
  655         int error, optval;
  656 
  657         error = copyin(args, &linux_args, sizeof(linux_args));
  658         if (error)
  659                 return (error);
  660 
  661         if (linux_args.to) {
  662                 error = linux_getsockaddr(&sa, linux_args.to,
  663                     linux_args.tolen);
  664                 if (error)
  665                         return (error);
  666         }
  667 
  668         /*
  669          * Check to see if the IP_HDRINCL option is set.
  670          */
  671         sopt.sopt_dir = SOPT_GET;
  672         sopt.sopt_level = IPPROTO_IP;
  673         sopt.sopt_name = IP_HDRINCL;
  674         sopt.sopt_val = &optval;
  675         sopt.sopt_valsize = sizeof(optval);
  676         sopt.sopt_td = NULL;
  677 
  678         if (kern_getsockopt(linux_args.s, &sopt) != 0)
  679                 optval = 0;
  680 
  681         if (optval == 0) {
  682                 /*
  683                  * IP_HDRINCL is not set.  Package the message as usual.
  684                  */
  685                 aiov.iov_base = linux_args.msg;
  686                 aiov.iov_len = linux_args.len;
  687                 auio.uio_iov = &aiov;
  688                 auio.uio_iovcnt = 1;
  689                 auio.uio_offset = 0;
  690                 auio.uio_resid = linux_args.len;
  691                 auio.uio_segflg = UIO_USERSPACE;
  692                 auio.uio_rw = UIO_WRITE;
  693                 auio.uio_td = td;
  694         } else {
  695                 /*
  696                  * IP_HDRINCL is set.  We must convert the beginning of
  697                  * the packet header so we can feed it to the BSD kernel.
  698                  */
  699 
  700                 /*
  701                  * Check that the packet header is long enough to contain
  702                  * the fields of interest.  This relies on the fact that
  703                  * the fragment offset field comes after the length field.
  704                  */
  705                 if (linux_args.len < offsetof(struct ip, ip_off))
  706                         return (EINVAL);
  707 
  708                 msg = kmalloc(linux_args.len, M_LINUX, M_WAITOK);
  709                 error = copyin(linux_args.msg, msg, linux_args.len);
  710                 if (error)
  711                         goto cleanup;
  712 
  713                 /* Fix the ip_len and ip_off fields.  */
  714                 ((struct ip *)msg)->ip_len = linux_args.len;
  715                 ((struct ip *)msg)->ip_off = ntohs(((struct ip *)msg)->ip_off);
  716 
  717                 aiov.iov_base = msg;
  718                 aiov.iov_len = linux_args.len;
  719                 auio.uio_iov = &aiov;
  720                 auio.uio_iovcnt = 1;
  721                 auio.uio_offset = 0;
  722                 auio.uio_resid = linux_args.len;
  723                 auio.uio_segflg = UIO_SYSSPACE;
  724                 auio.uio_rw = UIO_WRITE;
  725                 auio.uio_td = td;
  726         }
  727 
  728         error = kern_sendmsg(linux_args.s, sa, &auio, NULL,
  729                              linux_args.flags, res);
  730 
  731 cleanup:
  732         if (sa)
  733                 kfree(sa, M_SONAME);
  734         if (msg)
  735                 kfree(msg, M_LINUX);
  736         return(error);
  737 }
  738 
  739 struct linux_recvfrom_args {
  740         int s;
  741         void *buf;
  742         int len;
  743         int flags;
  744         struct sockaddr *from;
  745         int *fromlen;
  746 };
  747 
  748 static int
  749 linux_recvfrom(struct linux_recvfrom_args *args, size_t *res)
  750 {
  751         struct linux_recvfrom_args linux_args;
  752         struct thread *td = curthread;
  753         struct uio auio;
  754         struct iovec aiov;
  755         struct sockaddr *sa = NULL;
  756         int error, fromlen, flags;
  757 
  758         error = copyin(args, &linux_args, sizeof(linux_args));
  759         if (error)
  760                 return (error);
  761 
  762         if (linux_args.from && linux_args.fromlen) {
  763                 error = copyin(linux_args.fromlen, &fromlen, sizeof(fromlen));
  764                 if (error)
  765                         return (error);
  766                 if (fromlen < 0)
  767                         return (EINVAL);
  768         } else {
  769                 fromlen = 0;
  770         }
  771         aiov.iov_base = linux_args.buf;
  772         aiov.iov_len = linux_args.len;
  773         auio.uio_iov = &aiov;
  774         auio.uio_iovcnt = 1;
  775         auio.uio_offset = 0;
  776         auio.uio_resid = linux_args.len;
  777         auio.uio_segflg = UIO_USERSPACE;
  778         auio.uio_rw = UIO_READ;
  779         auio.uio_td = td;
  780 
  781         flags = linux_to_bsd_msg_flags(linux_args.flags);
  782 
  783         error = kern_recvmsg(linux_args.s, linux_args.from ? &sa : NULL, &auio,
  784                              NULL, &flags, res);
  785 
  786         if (error == 0 && linux_args.from) {
  787                 if (sa != NULL) {
  788                         fromlen = MIN(fromlen, sa->sa_len);
  789                         error = linux_copyout_sockaddr(sa, linux_args.from,
  790                                                         fromlen);
  791                 } else
  792                         fromlen = 0;
  793                 if (error == 0)
  794                         copyout(&fromlen, linux_args.fromlen,
  795                             sizeof(fromlen));
  796         }
  797         if (sa)
  798                 kfree(sa, M_SONAME);
  799 
  800         return(error);
  801 }
  802 
  803 struct linux_sendmsg_args {
  804         int s;
  805         struct msghdr *msg;
  806         int flags;
  807 };
  808 
  809 static int
  810 linux_sendmsg(struct linux_sendmsg_args *args, size_t *res)
  811 {
  812         struct linux_sendmsg_args linux_args;
  813         struct thread *td = curthread;
  814         struct msghdr msg;
  815         struct uio auio;
  816         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
  817         struct sockaddr *sa = NULL;
  818         struct mbuf *control = NULL;
  819         int error;
  820 
  821         error = copyin(args, &linux_args, sizeof(linux_args));
  822         if (error)
  823                 return (error);
  824 
  825         error = copyin(linux_args.msg, &msg, sizeof(msg));
  826         if (error)
  827                 return (error);
  828 
  829         /* 
  830          * XXX: I'm not sure atm how this relates to dragonfly, but 
  831          *      just in case, I put it in.
  832          * Ping on linux does pass 0 in controllen which is forbidden
  833          * by FreeBSD but seems to be ok on Linux. This needs some
  834          * checking but now it lets ping work.
  835          */
  836         if (msg.msg_control && msg.msg_controllen == 0)
  837                 msg.msg_control = NULL;
  838 
  839         /*
  840          * Conditionally copyin msg.msg_name.
  841          */
  842         if (msg.msg_name) {
  843                 error = linux_getsockaddr(&sa, msg.msg_name, msg.msg_namelen);
  844                 if (error)
  845                         return (error);
  846         }
  847 
  848         /*
  849          * Populate auio.
  850          */
  851         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
  852                              &auio.uio_resid);
  853         if (error)
  854                 goto cleanup2;
  855         auio.uio_iov = iov;
  856         auio.uio_iovcnt = msg.msg_iovlen;
  857         auio.uio_offset = 0;
  858         auio.uio_segflg = UIO_USERSPACE;
  859         auio.uio_rw = UIO_WRITE;
  860         auio.uio_td = td;
  861 
  862         /*
  863          * Conditionally copyin msg.msg_control.
  864          */
  865         if (msg.msg_control) {
  866                 if (msg.msg_controllen < sizeof(struct cmsghdr) ||
  867                     msg.msg_controllen > MLEN) {
  868                         error = EINVAL;
  869                         goto cleanup;
  870                 }
  871                 control = m_get(MB_WAIT, MT_CONTROL);
  872                 if (control == NULL) {
  873                         error = ENOBUFS;
  874                         goto cleanup;
  875                 }
  876                 control->m_len = msg.msg_controllen;
  877                 error = copyin(msg.msg_control, mtod(control, caddr_t),
  878                     msg.msg_controllen);
  879                 if (error) {
  880                         m_free(control);
  881                         goto cleanup;
  882                 }
  883                 /*
  884                  * Linux and BSD both support SCM_RIGHTS.  If a linux binary
  885                  * wants anything else with an option level of SOL_SOCKET,
  886                  * we don't support it.
  887                  */
  888                 if (mtod(control, struct cmsghdr *)->cmsg_level ==
  889                     SOL_SOCKET &&
  890                     mtod(control, struct cmsghdr *)->cmsg_type !=
  891                     SCM_RIGHTS) {
  892                         m_free(control);
  893                         error = EINVAL;
  894                         goto cleanup;
  895                 }
  896         }
  897 
  898         error = kern_sendmsg(linux_args.s, sa, &auio, control,
  899                              linux_args.flags, res);
  900 
  901 cleanup:
  902         iovec_free(&iov, aiov);
  903 cleanup2:
  904         if (sa)
  905                 kfree(sa, M_SONAME);
  906         return (error);
  907 }
  908 
  909 struct linux_recvmsg_args {
  910         int s;
  911         struct msghdr *msg;
  912         int flags;
  913 };
  914 
  915 static int
  916 linux_recvmsg(struct linux_recvmsg_args *args, size_t *res)
  917 {
  918         struct linux_recvmsg_args linux_args;
  919         struct thread *td = curthread;
  920         struct msghdr msg;
  921         struct uio auio;
  922         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
  923         struct mbuf *m, *control = NULL;
  924         struct sockaddr *sa = NULL;
  925         caddr_t ctlbuf;
  926         socklen_t *ufromlenp, *ucontrollenp;
  927         int error, fromlen, controllen, len, flags, *uflagsp;
  928 
  929         error = copyin(args, &linux_args, sizeof(linux_args));
  930         if (error)
  931                 return (error);
  932 
  933         error = copyin(linux_args.msg, &msg, sizeof(struct msghdr));
  934         if (error)
  935                 return (error);
  936 
  937         if (msg.msg_name && msg.msg_namelen < 0)
  938                 return (EINVAL);
  939         if (msg.msg_control && msg.msg_controllen < 0)
  940                 return (EINVAL);
  941 
  942         ufromlenp = (socklen_t *)((caddr_t)linux_args.msg +
  943             offsetof(struct msghdr, msg_namelen));
  944         ucontrollenp = (socklen_t *)((caddr_t)linux_args.msg +
  945             offsetof(struct msghdr, msg_controllen));
  946         uflagsp = (int *)((caddr_t)linux_args.msg +
  947             offsetof(struct msghdr, msg_flags));
  948 
  949         /*
  950          * Populate auio.
  951          */
  952         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
  953                              &auio.uio_resid);
  954         if (error)
  955                 return (error);
  956         auio.uio_iov = iov;
  957         auio.uio_iovcnt = msg.msg_iovlen;
  958         auio.uio_offset = 0;
  959         auio.uio_segflg = UIO_USERSPACE;
  960         auio.uio_rw = UIO_READ;
  961         auio.uio_td = td;
  962 
  963         flags = linux_to_bsd_msg_flags(linux_args.flags);
  964 
  965         error = kern_recvmsg(linux_args.s, msg.msg_name ? &sa : NULL, &auio,
  966                              msg.msg_control ? &control : NULL, &flags, res);
  967 
  968         /*
  969          * Copyout msg.msg_name and msg.msg_namelen.
  970          */
  971         if (error == 0 && msg.msg_name) {
  972                 if (sa != NULL) {
  973                         fromlen = MIN(msg.msg_namelen, sa->sa_len);
  974                         error = linux_copyout_sockaddr(sa, msg.msg_name,
  975                                                         fromlen);
  976                 } else
  977                         fromlen = 0;
  978                 if (error == 0)
  979                         error = copyout(&fromlen, ufromlenp,
  980                             sizeof(*ufromlenp));
  981         }
  982 
  983         /*
  984          * Copyout msg.msg_control and msg.msg_controllen.
  985          */
  986         if (error == 0 && msg.msg_control) {
  987                 /*
  988                  * Linux and BSD both support SCM_RIGHTS.  If a linux binary
  989                  * wants anything else with an option level of SOL_SOCKET,
  990                  * we don't support it.
  991                  */
  992                 if (mtod((struct mbuf *)msg.msg_control,
  993                     struct cmsghdr *)->cmsg_level == SOL_SOCKET &&
  994                     mtod((struct mbuf *)msg.msg_control,
  995                     struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
  996                         error = EINVAL;
  997                         goto cleanup;
  998                 }
  999 
 1000                 len = msg.msg_controllen;
 1001                 m = control;
 1002                 ctlbuf = (caddr_t)msg.msg_control;
 1003 
 1004                 while (m && len > 0) {
 1005                         unsigned int tocopy;
 1006 
 1007                         if (len >= m->m_len) {
 1008                                 tocopy = m->m_len;
 1009                         } else {
 1010                                 msg.msg_flags |= MSG_CTRUNC;
 1011                                 tocopy = len;
 1012                         }
 1013 
 1014                         error = copyout(mtod(m, caddr_t), ctlbuf,
 1015                             tocopy);
 1016                         if (error)
 1017                                 goto cleanup;
 1018 
 1019                         ctlbuf += tocopy;
 1020                         len -= tocopy;
 1021                         m = m->m_next;
 1022                 }
 1023                 controllen = ctlbuf - (caddr_t)msg.msg_control;
 1024                 error = copyout(&controllen, ucontrollenp,
 1025                     sizeof(*ucontrollenp));
 1026         }
 1027 
 1028         if (error == 0)
 1029                 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
 1030 
 1031 cleanup:
 1032         if (sa)
 1033                 kfree(sa, M_SONAME);
 1034         iovec_free(&iov, aiov);
 1035         if (control)
 1036                 m_freem(control);
 1037         return (error);
 1038 }
 1039 
 1040 struct linux_shutdown_args {
 1041         int s;
 1042         int how;
 1043 };
 1044 
 1045 static int
 1046 linux_shutdown(struct linux_shutdown_args *args, int *res)
 1047 {
 1048         struct linux_shutdown_args linux_args;
 1049         int error;
 1050 
 1051         error = copyin(args, &linux_args, sizeof(linux_args));
 1052         if (error)
 1053                 return (error);
 1054 
 1055         error = kern_shutdown(linux_args.s, linux_args.how);
 1056 
 1057         return (error);
 1058 }
 1059 
 1060 struct linux_setsockopt_args {
 1061         int s;
 1062         int level;
 1063         int optname;
 1064         void *optval;
 1065         int optlen;
 1066 };
 1067 
 1068 static int
 1069 linux_setsockopt(struct linux_setsockopt_args *args, int *res)
 1070 {
 1071         struct linux_setsockopt_args linux_args;
 1072         struct thread *td = curthread;
 1073         struct sockopt sopt;
 1074         l_timeval linux_tv;
 1075         struct timeval tv;
 1076         int error, name, level;
 1077 
 1078         error = copyin(args, &linux_args, sizeof(linux_args));
 1079         if (error)
 1080                 return (error);
 1081 
 1082         level = linux_to_bsd_sockopt_level(linux_args.level);
 1083         switch (level) {
 1084         case SOL_SOCKET:
 1085                 name = linux_to_bsd_so_sockopt(linux_args.optname);
 1086                 switch (name) {
 1087                 case SO_RCVTIMEO:
 1088                         /* FALLTHROUGH */
 1089                 case SO_SNDTIMEO:
 1090                         error = copyin(linux_args.optval, &linux_tv,
 1091                             sizeof(linux_tv));
 1092                         if (error)
 1093                                 return (error);
 1094                         tv.tv_sec = linux_tv.tv_sec;
 1095                         tv.tv_usec = linux_tv.tv_usec;
 1096                         sopt.sopt_dir = SOPT_SET;
 1097                         sopt.sopt_level = level;
 1098                         sopt.sopt_name = name;
 1099                         sopt.sopt_valsize = sizeof(tv);
 1100                         sopt.sopt_val = &tv;
 1101                         sopt.sopt_td = td;
 1102                         return (kern_setsockopt(linux_args.s, &sopt));
 1103                         /* NOTREACHED */
 1104                         break;
 1105                 default:
 1106                         break;
 1107                 }
 1108                 break;
 1109         case IPPROTO_IP:
 1110                 name = linux_to_bsd_ip_sockopt(linux_args.optname);
 1111                 break;
 1112         case IPPROTO_TCP:
 1113                 /* Linux TCP option values match BSD's */
 1114                 name = linux_args.optname;
 1115                 break;
 1116         default:
 1117                 name = -1;
 1118                 break;
 1119         }
 1120         if (name == -1)
 1121                 return (ENOPROTOOPT);
 1122 
 1123         if (linux_args.optlen < 0 || linux_args.optlen > SOMAXOPT_SIZE)
 1124                 return (EINVAL);
 1125         if (linux_args.optval != NULL && linux_args.optlen == 0)
 1126                 return (EINVAL);
 1127         if (linux_args.optval == NULL && linux_args.optlen != 0)
 1128                 return (EFAULT);
 1129 
 1130         sopt.sopt_dir = SOPT_SET;
 1131         sopt.sopt_level = level;
 1132         sopt.sopt_name = name;
 1133         sopt.sopt_valsize = linux_args.optlen;
 1134         sopt.sopt_td = td;
 1135 
 1136         if (linux_args.optval) {
 1137                 sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK);
 1138                 error = copyin(linux_args.optval, sopt.sopt_val, sopt.sopt_valsize);
 1139                 if (error)
 1140                         goto out;
 1141         } else {
 1142                 sopt.sopt_val = NULL;
 1143         }
 1144         error = kern_setsockopt(linux_args.s, &sopt);
 1145         if (error)
 1146                 goto out;
 1147         if (linux_args.optval)
 1148                 error = copyout(sopt.sopt_val, linux_args.optval,
 1149                                 sopt.sopt_valsize);
 1150 out:
 1151         if (linux_args.optval)
 1152                 kfree(sopt.sopt_val, M_TEMP);
 1153         return(error);
 1154 }
 1155 
 1156 struct linux_getsockopt_args {
 1157         int s;
 1158         int level;
 1159         int optname;
 1160         void *optval;
 1161         int *optlen;
 1162 };
 1163 
 1164 static int
 1165 linux_getsockopt(struct linux_getsockopt_args *args, int *res)
 1166 {
 1167         struct linux_getsockopt_args linux_args;
 1168         struct thread *td = curthread;
 1169         struct sockopt sopt;
 1170         l_timeval linux_tv;
 1171         struct timeval tv;
 1172         struct xucred xu;
 1173         struct l_ucred lxu;
 1174         int error, name, valsize, level;
 1175 
 1176         error = copyin(args, &linux_args, sizeof(linux_args));
 1177         if (error)
 1178                 return (error);
 1179 
 1180         if (linux_args.optlen) {
 1181                 error = copyin(linux_args.optlen, &valsize, sizeof(valsize));
 1182                 if (error)
 1183                         return (error);
 1184         } else {
 1185                 valsize = 0;
 1186         }
 1187 
 1188         if (valsize < 0 || valsize > SOMAXOPT_SIZE)
 1189                 return (EINVAL);
 1190         if (linux_args.optval != NULL && valsize == 0)
 1191                 return (EFAULT);
 1192         if (linux_args.optval == NULL && valsize != 0)
 1193                 return (EFAULT);
 1194                 
 1195         level = linux_to_bsd_sockopt_level(linux_args.level);
 1196         switch (level) {
 1197         case SOL_SOCKET:
 1198                 name = linux_to_bsd_so_sockopt(linux_args.optname);
 1199                 switch (name) {
 1200                 case SO_RCVTIMEO:
 1201                         /* FALLTHROUGH */
 1202                 case SO_SNDTIMEO:
 1203                         sopt.sopt_dir = SOPT_GET;
 1204                         sopt.sopt_level = level;
 1205                         sopt.sopt_name = name;
 1206                         sopt.sopt_valsize = sizeof(tv);
 1207                         sopt.sopt_td = td;
 1208                         sopt.sopt_val = &tv;
 1209                         error = kern_getsockopt(linux_args.s, &sopt);
 1210                         if (error)
 1211                                 return (error);
 1212                         linux_tv.tv_sec = tv.tv_sec;
 1213                         linux_tv.tv_usec = tv.tv_usec;
 1214                         return (copyout(&linux_tv, linux_args.optval,
 1215                             sizeof(linux_tv)));
 1216                         /* NOTREACHED */
 1217                         break;
 1218                 case LOCAL_PEERCRED:
 1219                         if (valsize != sizeof(lxu))
 1220                                 return (EINVAL);
 1221                         sopt.sopt_dir = SOPT_GET;
 1222                         sopt.sopt_level = level;
 1223                         sopt.sopt_name = name;
 1224                         sopt.sopt_valsize = sizeof(xu);
 1225                         sopt.sopt_td = td;
 1226                         sopt.sopt_val = &xu;
 1227                         error = kern_getsockopt(linux_args.s, &sopt);
 1228                         if (error)
 1229                                 return (error);
 1230                         /*
 1231                          * XXX Use 0 for pid as the FreeBSD does not cache peer pid.
 1232                          */
 1233                         lxu.pid = 0;
 1234                         lxu.uid = xu.cr_uid;
 1235                         lxu.gid = xu.cr_gid;
 1236                         return (copyout(&lxu, linux_args.optval, sizeof(lxu)));
 1237                         /* NOTREACHED */
 1238                         break;
 1239                 default:
 1240                         break;
 1241                 }
 1242                 break;
 1243         case IPPROTO_IP:
 1244                 name = linux_to_bsd_ip_sockopt(linux_args.optname);
 1245                 break;
 1246         case IPPROTO_TCP:
 1247                 /* Linux TCP option values match BSD's */
 1248                 name = linux_args.optname;
 1249                 break;
 1250         default:
 1251                 name = -1;
 1252                 break;
 1253         }
 1254         if (name == -1)
 1255                 return (EOPNOTSUPP);
 1256 
 1257 
 1258 
 1259         sopt.sopt_dir = SOPT_GET;
 1260         sopt.sopt_level = level;
 1261         sopt.sopt_name = name;
 1262         sopt.sopt_valsize = valsize;
 1263         sopt.sopt_td = td;
 1264 
 1265         if (linux_args.optval) {
 1266                 sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK);
 1267                 error = copyin(linux_args.optval, sopt.sopt_val, sopt.sopt_valsize);
 1268                 if (error)
 1269                         goto out;
 1270         } else {
 1271                 sopt.sopt_val = NULL;
 1272         }
 1273         error = kern_getsockopt(linux_args.s, &sopt);
 1274         if (error) {
 1275                 if (error == EINVAL)
 1276                         error = ENOPROTOOPT;
 1277                 goto out;
 1278         }
 1279         valsize = sopt.sopt_valsize;
 1280         error = copyout(&valsize, linux_args.optlen, sizeof(valsize));
 1281         if (error)
 1282                 goto out;
 1283         if (linux_args.optval)
 1284                 error = copyout(sopt.sopt_val, linux_args.optval, sopt.sopt_valsize);
 1285 out:
 1286         if (linux_args.optval)
 1287                 kfree(sopt.sopt_val, M_TEMP);
 1288         return(error);
 1289 }
 1290 
 1291 /*
 1292  * MPALMOSTSAFE
 1293  */
 1294 int
 1295 sys_linux_socketcall(struct linux_socketcall_args *args)
 1296 {
 1297         void *arg = (void *)args->args;
 1298         int error;
 1299 
 1300         get_mplock();
 1301 
 1302         switch (args->what) {
 1303         case LINUX_SOCKET:
 1304                 error = linux_socket(arg, &args->sysmsg_result);
 1305                 break;
 1306         case LINUX_BIND:
 1307                 error = linux_bind(arg, &args->sysmsg_result);
 1308                 break;
 1309         case LINUX_CONNECT:
 1310                 error = linux_connect(arg, &args->sysmsg_result);
 1311                 break;
 1312         case LINUX_LISTEN:
 1313                 error = linux_listen(arg, &args->sysmsg_result);
 1314                 break;
 1315         case LINUX_ACCEPT:
 1316                 error = linux_accept(arg, &args->sysmsg_result);
 1317                 break;
 1318         case LINUX_GETSOCKNAME:
 1319                 error = linux_getsockname(arg, &args->sysmsg_result);
 1320                 break;
 1321         case LINUX_GETPEERNAME:
 1322                 error = linux_getpeername(arg, &args->sysmsg_result);
 1323                 break;
 1324         case LINUX_SOCKETPAIR:
 1325                 error = linux_socketpair(arg, &args->sysmsg_result);
 1326                 break;
 1327         case LINUX_SEND:
 1328                 error = linux_send(arg, &args->sysmsg_szresult);
 1329                 break;
 1330         case LINUX_RECV:
 1331                 error = linux_recv(arg, &args->sysmsg_szresult);
 1332                 break;
 1333         case LINUX_SENDTO:
 1334                 error = linux_sendto(arg, &args->sysmsg_szresult);
 1335                 break;
 1336         case LINUX_RECVFROM:
 1337                 error = linux_recvfrom(arg, &args->sysmsg_szresult);
 1338                 break;
 1339         case LINUX_SHUTDOWN:
 1340                 error = linux_shutdown(arg, &args->sysmsg_result);
 1341                 break;
 1342         case LINUX_SETSOCKOPT:
 1343                 error = linux_setsockopt(arg, &args->sysmsg_result);
 1344                 break;
 1345         case LINUX_GETSOCKOPT:
 1346                 error = linux_getsockopt(arg, &args->sysmsg_result);
 1347                 break;
 1348         case LINUX_SENDMSG:
 1349                 error = linux_sendmsg(arg, &args->sysmsg_szresult);
 1350                 break;
 1351         case LINUX_RECVMSG:
 1352                 error = linux_recvmsg(arg, &args->sysmsg_szresult);
 1353                 break;
 1354         default:
 1355                 uprintf("LINUX: 'socket' typ=%d not implemented\n",
 1356                         args->what);
 1357                 error = ENOSYS;
 1358                 break;
 1359         }
 1360         rel_mplock();
 1361 
 1362         return (error);
 1363 }

Cache object: 6961c93411ad5dc49b1ee27b1198faac


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