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/i386/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 withough 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$
   29  */
   30 
   31 /* XXX we use functions that might not exist. */
   32 #include "opt_compat.h"
   33 
   34 #ifndef COMPAT_43
   35 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
   36 #endif
   37 
   38 #include <sys/param.h>
   39 #include <sys/proc.h>
   40 #include <sys/systm.h>
   41 #include <sys/sysproto.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/socket.h>
   44 #include <sys/uio.h>
   45 
   46 #include <netinet/in.h>
   47 #include <netinet/in_systm.h>
   48 #include <netinet/ip.h>
   49 
   50 #include <i386/linux/linux.h>
   51 #include <i386/linux/linux_proto.h>
   52 #include <i386/linux/linux_util.h>
   53 
   54 static int
   55 linux_to_bsd_domain(int domain)
   56 {
   57     switch (domain) {
   58     case LINUX_AF_UNSPEC:
   59         return AF_UNSPEC;
   60     case LINUX_AF_UNIX:
   61         return AF_LOCAL;
   62     case LINUX_AF_INET:
   63         return AF_INET;
   64     case LINUX_AF_AX25:
   65         return AF_CCITT;
   66     case LINUX_AF_IPX:
   67         return AF_IPX;
   68     case LINUX_AF_APPLETALK:
   69         return AF_APPLETALK;
   70     default:
   71         return -1;
   72     }
   73 }
   74 
   75 static int
   76 linux_to_bsd_sockopt_level(int level)
   77 {
   78     switch (level) {
   79     case LINUX_SOL_SOCKET:
   80         return SOL_SOCKET;
   81     default:
   82         return level;
   83     }
   84 }
   85 
   86 static int linux_to_bsd_ip_sockopt(int opt)
   87 {
   88     switch (opt) {
   89     case LINUX_IP_TOS:
   90         return IP_TOS;
   91     case LINUX_IP_TTL:
   92         return IP_TTL;
   93     case LINUX_IP_OPTIONS:
   94         return IP_OPTIONS;
   95     case LINUX_IP_MULTICAST_IF:
   96         return IP_MULTICAST_IF;
   97     case LINUX_IP_MULTICAST_TTL:
   98         return IP_MULTICAST_TTL;
   99     case LINUX_IP_MULTICAST_LOOP:
  100         return IP_MULTICAST_LOOP;
  101     case LINUX_IP_ADD_MEMBERSHIP:
  102         return IP_ADD_MEMBERSHIP;
  103     case LINUX_IP_DROP_MEMBERSHIP:
  104         return IP_DROP_MEMBERSHIP;
  105     case LINUX_IP_HDRINCL:
  106         return IP_HDRINCL;
  107     default:
  108         return -1;
  109     }
  110 }
  111 
  112 static int
  113 linux_to_bsd_so_sockopt(int opt)
  114 {
  115     switch (opt) {
  116     case LINUX_SO_DEBUG:
  117         return SO_DEBUG;
  118     case LINUX_SO_REUSEADDR:
  119         return SO_REUSEADDR;
  120     case LINUX_SO_TYPE:
  121         return SO_TYPE;
  122     case LINUX_SO_ERROR:
  123         return SO_ERROR;
  124     case LINUX_SO_DONTROUTE:
  125         return SO_DONTROUTE;
  126     case LINUX_SO_BROADCAST:
  127         return SO_BROADCAST;
  128     case LINUX_SO_SNDBUF:
  129         return SO_SNDBUF;
  130     case LINUX_SO_RCVBUF:
  131         return SO_RCVBUF;
  132     case LINUX_SO_KEEPALIVE:
  133         return SO_KEEPALIVE;
  134     case LINUX_SO_OOBINLINE:
  135         return SO_OOBINLINE;
  136     case LINUX_SO_LINGER:
  137         return SO_LINGER;
  138     case LINUX_SO_PRIORITY:
  139     case LINUX_SO_NO_CHECK:
  140     default:
  141         return -1;
  142     }
  143 }
  144 
  145 /* Return 0 if IP_HDRINCL is set of the given socket, not 0 otherwise */
  146 static int
  147 linux_check_hdrincl(struct proc *p, int s)
  148 {
  149     struct getsockopt_args /* {
  150         int s;
  151         int level;
  152         int name;
  153         caddr_t val;
  154         int *avalsize;
  155     } */ bsd_args;
  156     int error;
  157     caddr_t sg, val, valsize;
  158     int size_val = sizeof val;
  159     int optval;
  160 
  161     sg = stackgap_init();
  162     val = stackgap_alloc(&sg, sizeof(int));
  163     valsize = stackgap_alloc(&sg, sizeof(int));
  164 
  165     if ((error=copyout(&size_val, valsize, sizeof(size_val))))
  166         return error;
  167     bsd_args.s = s;
  168     bsd_args.level = IPPROTO_IP;
  169     bsd_args.name = IP_HDRINCL;
  170     bsd_args.val = val;
  171     bsd_args.avalsize = (int *)valsize;
  172     if ((error=getsockopt(p, &bsd_args)))
  173         return error;
  174     if ((error=copyin(val, &optval, sizeof(optval))))
  175         return error;
  176     return optval == 0;
  177 }
  178 
  179 /*
  180  * Updated sendto() when IP_HDRINCL is set:
  181  * tweak endian-dependent fields in the IP packet.
  182  */
  183 static int
  184 linux_sendto_hdrincl(struct proc *p, struct sendto_args *bsd_args)
  185 {
  186 /*
  187  * linux_ip_copysize defines how many bytes we should copy
  188  * from the beginning of the IP packet before we customize it for BSD.
  189  * It should include all the fields we modify (ip_len and ip_off)
  190  * and be as small as possible to minimize copying overhead.
  191  */
  192 #define linux_ip_copysize       8
  193 
  194     caddr_t sg;
  195     struct ip *packet;
  196     struct msghdr *msg;
  197     struct iovec *iov;
  198 
  199     int error;
  200     struct  sendmsg_args /* {
  201         int s;
  202         caddr_t msg;
  203         int flags;
  204     } */ sendmsg_args;
  205 
  206     /* Check the packet isn't too small before we mess with it */
  207     if (bsd_args->len < linux_ip_copysize)
  208         return EINVAL;
  209 
  210     /*
  211      * Tweaking the user buffer in place would be bad manners.
  212      * We create a corrected IP header with just the needed length,
  213      * then use an iovec to glue it to the rest of the user packet
  214      * when calling sendmsg().
  215      */
  216     sg = stackgap_init();
  217     packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
  218     msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg));
  219     iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2);
  220 
  221     /* Make a copy of the beginning of the packet to be sent */
  222     if ((error = copyin(bsd_args->buf, (caddr_t)packet, linux_ip_copysize)))
  223         return error;
  224 
  225     /* Convert fields from Linux to BSD raw IP socket format */
  226     packet->ip_len = bsd_args->len;
  227     packet->ip_off = ntohs(packet->ip_off);
  228 
  229     /* Prepare the msghdr and iovec structures describing the new packet */
  230     msg->msg_name = bsd_args->to;
  231     msg->msg_namelen = bsd_args->tolen;
  232     msg->msg_iov = iov;
  233     msg->msg_iovlen = 2;
  234     msg->msg_control = NULL;
  235     msg->msg_controllen = 0;
  236     msg->msg_flags = 0;
  237     iov[0].iov_base = (char *)packet;
  238     iov[0].iov_len = linux_ip_copysize;
  239     iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize;
  240     iov[1].iov_len = bsd_args->len - linux_ip_copysize;
  241 
  242     sendmsg_args.s = bsd_args->s;
  243     sendmsg_args.msg = (caddr_t)msg;
  244     sendmsg_args.flags = bsd_args->flags;
  245     return sendmsg(p, &sendmsg_args);
  246 }
  247 
  248 struct linux_socket_args {
  249     int domain;
  250     int type;
  251     int protocol;
  252 };
  253 
  254 static int
  255 linux_socket(struct proc *p, struct linux_socket_args *args)
  256 {
  257     struct linux_socket_args linux_args;
  258     struct socket_args /* {
  259         int domain;
  260         int type;
  261         int protocol;
  262     } */ bsd_args;
  263     int error;
  264     int retval_socket;
  265 
  266     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  267         return error;
  268     bsd_args.protocol = linux_args.protocol;
  269     bsd_args.type = linux_args.type;
  270     bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
  271     if (bsd_args.domain == -1)
  272         return EINVAL;
  273 
  274     retval_socket = socket(p, &bsd_args);
  275     if (bsd_args.type == SOCK_RAW
  276         && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
  277         && bsd_args.domain == AF_INET
  278         && retval_socket >= 0) {
  279         /* It's a raw IP socket: set the IP_HDRINCL option. */
  280         struct setsockopt_args /* {
  281             int s;
  282             int level;
  283             int name;
  284             caddr_t val;
  285             int valsize;
  286         } */ bsd_setsockopt_args;
  287         caddr_t sg;
  288         int *hdrincl;
  289 
  290         sg = stackgap_init();
  291         hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
  292         *hdrincl = 1;
  293         bsd_setsockopt_args.s = p->p_retval[0];
  294         bsd_setsockopt_args.level = IPPROTO_IP;
  295         bsd_setsockopt_args.name = IP_HDRINCL;
  296         bsd_setsockopt_args.val = (caddr_t)hdrincl;
  297         bsd_setsockopt_args.valsize = sizeof(*hdrincl);
  298         /* We ignore any error returned by setsockopt() */
  299         setsockopt(p, &bsd_setsockopt_args);
  300         /* Copy back the return value from socket() */
  301         p->p_retval[0] = bsd_setsockopt_args.s;
  302     }
  303     return retval_socket;
  304 }
  305 
  306 struct linux_bind_args {
  307     int s;
  308     struct sockaddr *name;
  309     int namelen;
  310 };
  311 
  312 static int
  313 linux_bind(struct proc *p, struct linux_bind_args *args)
  314 {
  315     struct linux_bind_args linux_args;
  316     struct bind_args /* {
  317         int s;
  318         caddr_t name;
  319         int namelen;
  320     } */ bsd_args;
  321     int error;
  322 
  323     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  324         return error;
  325     bsd_args.s = linux_args.s;
  326     bsd_args.name = (caddr_t)linux_args.name;
  327     bsd_args.namelen = linux_args.namelen;
  328     return bind(p, &bsd_args);
  329 }
  330 
  331 struct linux_connect_args {
  332     int s;
  333     struct sockaddr * name;
  334     int namelen;
  335 };
  336 
  337 static int
  338 linux_connect(struct proc *p, struct linux_connect_args *args)
  339 {
  340     struct linux_connect_args linux_args;
  341     struct connect_args /* {
  342         int s;
  343         caddr_t name;
  344         int namelen;
  345     } */ bsd_args;
  346     int error;
  347 
  348     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  349         return error;
  350     bsd_args.s = linux_args.s;
  351     bsd_args.name = (caddr_t)linux_args.name;
  352     bsd_args.namelen = linux_args.namelen;
  353     error = connect(p, &bsd_args);
  354     if (error == EISCONN) {
  355         /*
  356          * Linux doesn't return EISCONN the first time it occurs,
  357          * when on a non-blocking socket. Instead it returns the
  358          * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
  359          */
  360         struct fcntl_args /* {
  361             int fd;
  362             int cmd;
  363             int arg;
  364         } */ bsd_fcntl_args;
  365         struct getsockopt_args /* {
  366             int s;
  367             int level;
  368             int name;
  369             caddr_t val;
  370             int *avalsize;
  371         } */ bsd_getsockopt_args;
  372         void *status, *statusl;
  373         int stat, statl = sizeof stat;
  374         caddr_t sg;
  375 
  376         /* Check for non-blocking */
  377         bsd_fcntl_args.fd = linux_args.s;
  378         bsd_fcntl_args.cmd = F_GETFL;
  379         bsd_fcntl_args.arg = 0;
  380         error = fcntl(p, &bsd_fcntl_args);
  381         if (error == 0 && (p->p_retval[0] & O_NONBLOCK)) {
  382             sg = stackgap_init();
  383             status = stackgap_alloc(&sg, sizeof stat);
  384             statusl = stackgap_alloc(&sg, sizeof statusl);
  385 
  386             if ((error = copyout(&statl, statusl, sizeof statl)))
  387                 return error;
  388 
  389             bsd_getsockopt_args.s = linux_args.s;
  390             bsd_getsockopt_args.level = SOL_SOCKET;
  391             bsd_getsockopt_args.name = SO_ERROR;
  392             bsd_getsockopt_args.val = status;
  393             bsd_getsockopt_args.avalsize = statusl;
  394 
  395             error = getsockopt(p, &bsd_getsockopt_args);
  396             if (error)
  397                 return error;
  398             if ((error = copyin(status, &stat, sizeof stat)))
  399                 return error;  
  400             p->p_retval[0] = stat;
  401             return 0;
  402         }
  403     }
  404     return error;
  405 }
  406 
  407 struct linux_listen_args {
  408     int s;
  409     int backlog;
  410 };
  411 
  412 static int
  413 linux_listen(struct proc *p, struct linux_listen_args *args)
  414 {
  415     struct linux_listen_args linux_args;
  416     struct listen_args /* {
  417         int s;
  418         int backlog;
  419     } */ bsd_args;
  420     int error;
  421 
  422     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  423         return error;
  424     bsd_args.s = linux_args.s;
  425     bsd_args.backlog = linux_args.backlog;
  426     return listen(p, &bsd_args);
  427 }
  428 
  429 struct linux_accept_args {
  430     int s;
  431     struct sockaddr *addr;
  432     int *namelen;
  433 };
  434 
  435 static int
  436 linux_accept(struct proc *p, struct linux_accept_args *args)
  437 {
  438     struct linux_accept_args linux_args;
  439     struct accept_args /* {
  440         int s;
  441         caddr_t name;
  442         int *anamelen;
  443     } */ bsd_args;
  444     int error;
  445 
  446     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  447         return error;
  448     bsd_args.s = linux_args.s;
  449     bsd_args.name = (caddr_t)linux_args.addr;
  450     bsd_args.anamelen = linux_args.namelen;
  451     return oaccept(p, &bsd_args);
  452 }
  453 
  454 struct linux_getsockname_args {
  455     int s;
  456     struct sockaddr *addr;
  457     int *namelen;
  458 };
  459 
  460 static int
  461 linux_getsockname(struct proc *p, struct linux_getsockname_args *args)
  462 {
  463     struct linux_getsockname_args linux_args;
  464     struct getsockname_args /* {
  465         int fdes;
  466         caddr_t asa;
  467         int *alen;
  468     } */ bsd_args;
  469     int error;
  470 
  471     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  472         return error;
  473     bsd_args.fdes = linux_args.s;
  474     bsd_args.asa = (caddr_t) linux_args.addr;
  475     bsd_args.alen = linux_args.namelen;
  476     return ogetsockname(p, &bsd_args);
  477 }
  478 
  479 struct linux_getpeername_args {
  480     int s;
  481     struct sockaddr *addr;
  482     int *namelen;
  483 };
  484 
  485 static int
  486 linux_getpeername(struct proc *p, struct linux_getpeername_args *args)
  487 {
  488     struct linux_getpeername_args linux_args;
  489     struct ogetpeername_args /* {
  490         int fdes;
  491         caddr_t asa;
  492         int *alen;
  493     } */ bsd_args;
  494     int error;
  495 
  496     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  497         return error;
  498     bsd_args.fdes = linux_args.s;
  499     bsd_args.asa = (caddr_t) linux_args.addr;
  500     bsd_args.alen = linux_args.namelen;
  501     return ogetpeername(p, &bsd_args);
  502 }
  503 
  504 struct linux_socketpair_args {
  505     int domain;
  506     int type;
  507     int protocol;
  508     int *rsv;
  509 };
  510 
  511 static int
  512 linux_socketpair(struct proc *p, struct linux_socketpair_args *args)
  513 {
  514     struct linux_socketpair_args linux_args;
  515     struct socketpair_args /* {
  516         int domain;
  517         int type;
  518         int protocol;
  519         int *rsv;
  520     } */ bsd_args;
  521     int error;
  522 
  523     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  524         return error;
  525     bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
  526     if (bsd_args.domain == -1)
  527         return EINVAL;
  528     bsd_args.type = linux_args.type;
  529     bsd_args.protocol = linux_args.protocol;
  530     bsd_args.rsv = linux_args.rsv;
  531     return socketpair(p, &bsd_args);
  532 }
  533 
  534 struct linux_send_args {
  535     int s;
  536     void *msg;
  537     int len;
  538     int flags;
  539 };
  540 
  541 static int
  542 linux_send(struct proc *p, struct linux_send_args *args)
  543 {
  544     struct linux_send_args linux_args;
  545     struct osend_args /* {
  546         int s;
  547         caddr_t buf;
  548         int len;
  549         int flags;
  550     } */ bsd_args;
  551     int error;
  552 
  553     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  554         return error;
  555     bsd_args.s = linux_args.s;
  556     bsd_args.buf = linux_args.msg;
  557     bsd_args.len = linux_args.len;
  558     bsd_args.flags = linux_args.flags;
  559     return osend(p, &bsd_args);
  560 }
  561 
  562 struct linux_recv_args {
  563     int s;
  564     void *msg;
  565     int len;
  566     int flags;
  567 };
  568 
  569 static int
  570 linux_recv(struct proc *p, struct linux_recv_args *args)
  571 {
  572     struct linux_recv_args linux_args;
  573     struct orecv_args /* {
  574         int s;
  575         caddr_t buf;
  576         int len;
  577         int flags;
  578     } */ bsd_args;
  579     int error;
  580 
  581     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  582         return error;
  583     bsd_args.s = linux_args.s;
  584     bsd_args.buf = linux_args.msg;
  585     bsd_args.len = linux_args.len;
  586     bsd_args.flags = linux_args.flags;
  587     return orecv(p, &bsd_args);
  588 }
  589 
  590 struct linux_sendto_args {
  591     int s;
  592     void *msg;
  593     int len;
  594     int flags;
  595     caddr_t to;
  596     int tolen;
  597 };
  598 
  599 static int
  600 linux_sendto(struct proc *p, struct linux_sendto_args *args)
  601 {
  602     struct linux_sendto_args linux_args;
  603     struct sendto_args /* {
  604         int s;
  605         caddr_t buf;
  606         size_t len;
  607         int flags;
  608         caddr_t to;
  609         int tolen;
  610     } */ bsd_args;
  611     int error;
  612 
  613     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  614         return error;
  615     bsd_args.s = linux_args.s;
  616     bsd_args.buf = linux_args.msg;
  617     bsd_args.len = linux_args.len;
  618     bsd_args.flags = linux_args.flags;
  619     bsd_args.to = linux_args.to;
  620     bsd_args.tolen = linux_args.tolen;
  621 
  622     if (linux_check_hdrincl(p, linux_args.s) == 0)
  623         /* IP_HDRINCL set, tweak the packet before sending */
  624         return linux_sendto_hdrincl(p, &bsd_args);
  625 
  626     return sendto(p, &bsd_args);
  627 }
  628 
  629 struct linux_recvfrom_args {
  630     int s;
  631     void *buf;
  632     int len;
  633     int flags;
  634     caddr_t from;
  635     int *fromlen;
  636 };
  637 
  638 static int
  639 linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args)
  640 {
  641     struct linux_recvfrom_args linux_args;
  642     struct recvfrom_args /* {
  643         int s;
  644         caddr_t buf;
  645         size_t len;
  646         int flags;
  647         caddr_t from;
  648         int *fromlenaddr;
  649     } */ bsd_args;
  650     int error;
  651 
  652     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  653         return error;
  654     bsd_args.s = linux_args.s;
  655     bsd_args.buf = linux_args.buf;
  656     bsd_args.len = linux_args.len;
  657     bsd_args.flags = linux_args.flags;
  658     bsd_args.from = linux_args.from;
  659     bsd_args.fromlenaddr = linux_args.fromlen;
  660     return orecvfrom(p, &bsd_args);
  661 }
  662 
  663 struct linux_shutdown_args {
  664     int s;
  665     int how;
  666 };
  667 
  668 static int
  669 linux_shutdown(struct proc *p, struct linux_shutdown_args *args)
  670 {
  671     struct linux_shutdown_args linux_args;
  672     struct shutdown_args /* {
  673         int s;
  674         int how;
  675     } */ bsd_args;
  676     int error;
  677 
  678     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  679         return error;
  680     bsd_args.s = linux_args.s;
  681     bsd_args.how = linux_args.how;
  682     return shutdown(p, &bsd_args);
  683 }
  684 
  685 struct linux_setsockopt_args {
  686     int s;
  687     int level;
  688     int optname;
  689     void *optval;
  690     int optlen;
  691 };
  692 
  693 static int
  694 linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args)
  695 {
  696     struct linux_setsockopt_args linux_args;
  697     struct setsockopt_args /* {
  698         int s;
  699         int level;
  700         int name;
  701         caddr_t val;
  702         int valsize;
  703     } */ bsd_args;
  704     int error, name;
  705 
  706     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  707         return error;
  708     bsd_args.s = linux_args.s;
  709     bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
  710     switch (bsd_args.level) {
  711     case SOL_SOCKET:
  712         name = linux_to_bsd_so_sockopt(linux_args.optname);
  713         break;
  714     case IPPROTO_IP:
  715         name = linux_to_bsd_ip_sockopt(linux_args.optname);
  716         break;
  717     case IPPROTO_TCP:
  718         /* Linux TCP option values match BSD's */
  719         name = linux_args.optname;
  720         break;
  721     default:
  722         return EINVAL;
  723     }
  724     if (name == -1)
  725         return EINVAL;
  726     bsd_args.name = name;
  727     bsd_args.val = linux_args.optval;
  728     bsd_args.valsize = linux_args.optlen;
  729     return setsockopt(p, &bsd_args);
  730 }
  731 
  732 struct linux_getsockopt_args {
  733     int s;
  734     int level;
  735     int optname;
  736     void *optval;
  737     int *optlen;
  738 };
  739 
  740 static int
  741 linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args)
  742 {
  743     struct linux_getsockopt_args linux_args;
  744     struct getsockopt_args /* {
  745         int s;
  746         int level;
  747         int name;
  748         caddr_t val;
  749         int *avalsize;
  750     } */ bsd_args;
  751     int error, name;
  752 
  753     if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
  754         return error;
  755     bsd_args.s = linux_args.s;
  756     bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
  757     switch (bsd_args.level) {
  758     case SOL_SOCKET:
  759         name = linux_to_bsd_so_sockopt(linux_args.optname);
  760         break;
  761     case IPPROTO_IP:
  762         name = linux_to_bsd_ip_sockopt(linux_args.optname);
  763         break;
  764     case IPPROTO_TCP:
  765         /* Linux TCP option values match BSD's */
  766         name = linux_args.optname;
  767         break;
  768     default:
  769         return EINVAL;
  770     }
  771     if (name == -1)
  772         return EINVAL;
  773     bsd_args.name = name;
  774     bsd_args.val = linux_args.optval;
  775     bsd_args.avalsize = linux_args.optlen;
  776     return getsockopt(p, &bsd_args);
  777 }
  778 
  779 int
  780 linux_socketcall(struct proc *p, struct linux_socketcall_args *args)
  781 {
  782     switch (args->what) {
  783     case LINUX_SOCKET:
  784         return linux_socket(p, args->args);
  785     case LINUX_BIND:
  786         return linux_bind(p, args->args);
  787     case LINUX_CONNECT:
  788         return linux_connect(p, args->args);
  789     case LINUX_LISTEN:
  790         return linux_listen(p, args->args);
  791     case LINUX_ACCEPT:
  792         return linux_accept(p, args->args);
  793     case LINUX_GETSOCKNAME:
  794         return linux_getsockname(p, args->args);
  795     case LINUX_GETPEERNAME:
  796         return linux_getpeername(p, args->args);
  797     case LINUX_SOCKETPAIR:
  798         return linux_socketpair(p, args->args);
  799     case LINUX_SEND:
  800         return linux_send(p, args->args);
  801     case LINUX_RECV:
  802         return linux_recv(p, args->args);
  803     case LINUX_SENDTO:
  804         return linux_sendto(p, args->args);
  805     case LINUX_RECVFROM:
  806         return linux_recvfrom(p, args->args);
  807     case LINUX_SHUTDOWN:
  808         return linux_shutdown(p, args->args);
  809     case LINUX_SETSOCKOPT:
  810         return linux_setsockopt(p, args->args);
  811     case LINUX_GETSOCKOPT:
  812         return linux_getsockopt(p, args->args);
  813     case LINUX_SENDMSG:
  814         do {
  815                 int error;
  816                 int level;
  817                 caddr_t control;
  818                 struct {
  819                         int s;
  820                         const struct msghdr *msg;
  821                         int flags;
  822                 } *uap = args->args;
  823 
  824                 error = copyin(&uap->msg->msg_control,
  825                                 &control, sizeof(caddr_t));
  826                 if (error)
  827                         return error;
  828                 if (control == NULL)
  829                         goto done;
  830                 error = copyin(&((struct cmsghdr *)control)->cmsg_level,
  831                                 &level, sizeof(int));
  832                 if (error)
  833                         return error;
  834                 if (level == 1) {
  835                 /*
  836                  * Linux thinks that SOL_SOCKET is 1; we know that it's really
  837                  * 0xffff, of course.
  838                  */
  839                         level = SOL_SOCKET;
  840                         error = copyout(&level, &((struct cmsghdr *)control)->
  841                                         cmsg_level, sizeof(int));
  842                         if (error)
  843                                 return error;
  844                 }
  845         done:
  846                 return sendmsg(p, args->args);
  847         } while (0);
  848     case LINUX_RECVMSG:
  849         return recvmsg(p, args->args);
  850 
  851     default:
  852         uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
  853         return ENOSYS;
  854     }
  855 }

Cache object: 016bab88673058eef69ba7c482243fe7


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