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


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

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/common/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 /*      $NetBSD: linux_socket.c,v 1.50.2.1 2004/09/20 05:59:47 tron Exp $       */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Functions in multiarch:
   41  *      linux_sys_socketcall            : linux_socketcall.c
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.50.2.1 2004/09/20 05:59:47 tron Exp $");
   46 
   47 #if defined(_KERNEL_OPT)
   48 #include "opt_inet.h"
   49 #endif
   50 
   51 #include <sys/param.h>
   52 #include <sys/kernel.h>
   53 #include <sys/systm.h>
   54 #include <sys/buf.h>
   55 #include <sys/malloc.h>
   56 #include <sys/ioctl.h>
   57 #include <sys/tty.h>
   58 #include <sys/file.h>
   59 #include <sys/filedesc.h>
   60 #include <sys/select.h>
   61 #include <sys/socket.h>
   62 #include <sys/socketvar.h>
   63 #include <sys/domain.h>
   64 #include <net/if.h>
   65 #include <net/if_dl.h>
   66 #include <net/if_types.h>
   67 #include <netinet/in.h>
   68 #include <netinet/tcp.h>
   69 #include <sys/mount.h>
   70 #include <sys/proc.h>
   71 #include <sys/vnode.h>
   72 #include <sys/device.h>
   73 #include <sys/protosw.h> 
   74 #include <sys/mbuf.h>
   75 #include <sys/syslog.h>
   76 #include <sys/exec.h>
   77 
   78 #include <sys/sa.h>
   79 #include <sys/syscallargs.h>
   80 
   81 #ifdef INET6
   82 #include <netinet/ip6.h>
   83 #include <netinet6/ip6_var.h>
   84 #endif
   85 
   86 #include <compat/linux/common/linux_types.h>
   87 #include <compat/linux/common/linux_util.h>
   88 #include <compat/linux/common/linux_signal.h>
   89 #include <compat/linux/common/linux_ioctl.h>
   90 #include <compat/linux/common/linux_socket.h>
   91 #include <compat/linux/common/linux_socketcall.h>
   92 #include <compat/linux/common/linux_sockio.h>
   93 
   94 #include <compat/linux/linux_syscallargs.h>
   95 
   96 #ifdef DEBUG_LINUX
   97 #define DPRINTF(a) uprintf a
   98 #else
   99 #define DPRINTF(a)
  100 #endif
  101 
  102 /*
  103  * The calls in this file are entered either via the linux_socketcall()
  104  * interface or, on the Alpha, as individual syscalls.  The
  105  * linux_socketcall function does any massaging of arguments so that all
  106  * the calls in here need not think that they are anything other
  107  * than a normal syscall.
  108  */
  109 
  110 static int linux_to_bsd_domain __P((int));
  111 static int bsd_to_linux_domain __P((int));
  112 int linux_to_bsd_sopt_level __P((int));
  113 int linux_to_bsd_so_sockopt __P((int));
  114 int linux_to_bsd_ip_sockopt __P((int));
  115 int linux_to_bsd_tcp_sockopt __P((int));
  116 int linux_to_bsd_udp_sockopt __P((int));
  117 int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
  118 static int linux_sa_get __P((struct proc *, int, caddr_t *, struct sockaddr **,
  119                 const struct osockaddr *, int *));
  120 static int linux_sa_put __P((struct osockaddr *osa));
  121 static int linux_to_bsd_msg_flags __P((int));
  122 static int bsd_to_linux_msg_flags __P((int));
  123 
  124 static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
  125         AF_UNSPEC,
  126         AF_UNIX,
  127         AF_INET,
  128         AF_CCITT,       /* LINUX_AF_AX25 */
  129         AF_IPX,
  130         AF_APPLETALK,
  131         -1,             /* LINUX_AF_NETROM */
  132         -1,             /* LINUX_AF_BRIDGE */
  133         -1,             /* LINUX_AF_ATMPVC */
  134         AF_CCITT,       /* LINUX_AF_X25 */
  135         AF_INET6,
  136         -1,             /* LINUX_AF_ROSE */
  137         AF_DECnet,
  138         -1,             /* LINUX_AF_NETBEUI */
  139         -1,             /* LINUX_AF_SECURITY */
  140         pseudo_AF_KEY,
  141         AF_ROUTE,       /* LINUX_AF_NETLINK */
  142         -1,             /* LINUX_AF_PACKET */
  143         -1,             /* LINUX_AF_ASH */
  144         -1,             /* LINUX_AF_ECONET */
  145         -1,             /* LINUX_AF_ATMSVC */
  146         AF_SNA,
  147         /* rest up to LINUX_AF_MAX-1 is not allocated */
  148         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  149 };
  150         
  151 static const int bsd_to_linux_domain_[AF_MAX] = {
  152         LINUX_AF_UNSPEC,
  153         LINUX_AF_UNIX,
  154         LINUX_AF_INET,
  155         -1,             /* AF_IMPLINK */
  156         -1,             /* AF_PUP */
  157         -1,             /* AF_CHAOS */
  158         -1,             /* AF_NS */
  159         -1,             /* AF_ISO */
  160         -1,             /* AF_ECMA */
  161         -1,             /* AF_DATAKIT */
  162         LINUX_AF_AX25,  /* AF_CCITT */
  163         LINUX_AF_SNA,
  164         LINUX_AF_DECnet,
  165         -1,             /* AF_DLI */
  166         -1,             /* AF_LAT */
  167         -1,             /* AF_HYLINK */
  168         LINUX_AF_APPLETALK,
  169         LINUX_AF_NETLINK,
  170         -1,             /* AF_LINK */
  171         -1,             /* AF_XTP */
  172         -1,             /* AF_COIP */
  173         -1,             /* AF_CNT */
  174         -1,             /* pseudo_AF_RTIP */
  175         LINUX_AF_IPX,
  176         LINUX_AF_INET6,
  177         -1,             /* pseudo_AF_PIP */
  178         -1,             /* AF_ISDN */
  179         -1,             /* AF_NATM */
  180         -1,             /* AF_ARP */
  181         LINUX_pseudo_AF_KEY,
  182         -1,             /* pseudo_AF_HDRCMPLT */
  183 };
  184 
  185 static const int bsd_to_linux_msg_flags_[] = {
  186         MSG_OOB,                LINUX_MSG_OOB,
  187         MSG_PEEK,               LINUX_MSG_PEEK,
  188         MSG_DONTROUTE,          LINUX_MSG_DONTROUTE,
  189         MSG_EOR,                LINUX_MSG_EOR,
  190         MSG_TRUNC,              LINUX_MSG_TRUNC,
  191         MSG_CTRUNC,             LINUX_MSG_CTRUNC,
  192         MSG_WAITALL,            LINUX_MSG_WAITALL,
  193         MSG_DONTWAIT,           LINUX_MSG_DONTWAIT,
  194         MSG_BCAST,              0,              /* not supported, clear */
  195         MSG_MCAST,              0,              /* not supported, clear */
  196         -1, /* not supp */      LINUX_MSG_PROBE,
  197         -1, /* not supp */      LINUX_MSG_FIN,
  198         -1, /* not supp */      LINUX_MSG_SYN,
  199         -1, /* not supp */      LINUX_MSG_CONFIRM,
  200         -1, /* not supp */      LINUX_MSG_RST,
  201         -1, /* not supp */      LINUX_MSG_ERRQUEUE,
  202         -1, /* not supp */      LINUX_MSG_NOSIGNAL,
  203         -1, /* not supp */      LINUX_MSG_MORE,
  204 };
  205 
  206 /*
  207  * Convert between Linux and BSD socket domain values
  208  */
  209 static int
  210 linux_to_bsd_domain(ldom)
  211         int ldom;
  212 {
  213         if (ldom < 0 || ldom >= LINUX_AF_MAX)
  214                 return (-1);
  215 
  216         return linux_to_bsd_domain_[ldom];
  217 }
  218 
  219 /*
  220  * Convert between BSD and Linux socket domain values
  221  */
  222 static int
  223 bsd_to_linux_domain(bdom)
  224         int bdom;
  225 {
  226         if (bdom < 0 || bdom >= AF_MAX)
  227                 return (-1);
  228 
  229         return bsd_to_linux_domain_[bdom];
  230 }
  231 
  232 static int
  233 linux_to_bsd_msg_flags(lflag)
  234         int lflag;
  235 {
  236         int i, lfl, bfl;
  237         int bflag = 0;
  238 
  239         if (lflag == 0)
  240                 return (0);
  241 
  242         for(i=0; i < sizeof(bsd_to_linux_msg_flags_)/2; i += 2) {
  243                 bfl = bsd_to_linux_msg_flags_[i];
  244                 lfl = bsd_to_linux_msg_flags_[i+1];
  245 
  246                 if (lfl == 0)
  247                         continue;
  248 
  249                 if (lflag & lfl) {
  250                         if (bfl < 0)
  251                                 return (-1);
  252 
  253                         bflag |= bfl;
  254                 }
  255         }
  256 
  257         return (bflag);
  258 }
  259 
  260 static int
  261 bsd_to_linux_msg_flags(bflag)
  262         int bflag;
  263 {
  264         int i, lfl, bfl;
  265         int lflag = 0;
  266 
  267         if (bflag == 0)
  268                 return (0);
  269 
  270         for(i=0; i < sizeof(bsd_to_linux_msg_flags_)/2; i += 2) {
  271                 bfl = bsd_to_linux_msg_flags_[i];
  272                 lfl = bsd_to_linux_msg_flags_[i+1];
  273 
  274                 if (bfl <= 0)
  275                         continue;
  276 
  277                 if (bflag & bfl) {
  278                         if (lfl < 0)
  279                                 return (-1);
  280 
  281                         lflag |= lfl;
  282                 }
  283         }
  284 
  285         return (lflag);
  286 }
  287 
  288 int
  289 linux_sys_socket(l, v, retval)
  290         struct lwp *l;
  291         void *v;
  292         register_t *retval;
  293 {
  294         struct linux_sys_socket_args /* {
  295                 syscallarg(int) domain;
  296                 syscallarg(int) type;
  297                 syscallarg(int) protocol;
  298         } */ *uap = v;
  299         struct sys_socket_args bsa;
  300         int error;
  301 
  302         SCARG(&bsa, protocol) = SCARG(uap, protocol);
  303         SCARG(&bsa, type) = SCARG(uap, type);
  304         SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
  305         if (SCARG(&bsa, domain) == -1)
  306                 return EINVAL;
  307         error = sys_socket(l, &bsa, retval);
  308 
  309 #ifdef INET6
  310         /*
  311          * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
  312          * default and some apps depend on this. So, set V6ONLY to 0
  313          * for Linux apps if the sysctl value is set to 1.
  314          */
  315         if (!error && ip6_v6only && SCARG(&bsa, domain) == PF_INET6) {
  316                 struct proc *p = l->l_proc;
  317                 struct file *fp;
  318 
  319                 if (getsock(p->p_fd, *retval, &fp) == 0) {
  320                         struct mbuf *m;
  321 
  322                         m = m_get(M_WAIT, MT_SOOPTS);
  323                         m->m_len = sizeof(int);
  324                         *mtod(m, int *) = 0;
  325 
  326                         /* ignore error */
  327                         (void) sosetopt((struct socket *)fp->f_data,
  328                                 IPPROTO_IPV6, IPV6_V6ONLY, m);
  329 
  330                         FILE_UNUSE(fp, p);
  331                 }
  332         }
  333 #endif
  334 
  335         return (error);
  336 }
  337 
  338 int
  339 linux_sys_socketpair(l, v, retval)
  340         struct lwp *l;
  341         void *v;
  342         register_t *retval;
  343 {
  344         struct linux_sys_socketpair_args /* {
  345                 syscallarg(int) domain;
  346                 syscallarg(int) type;
  347                 syscallarg(int) protocol;
  348                 syscallarg(int *) rsv;
  349         } */ *uap = v;
  350         struct sys_socketpair_args bsa;
  351 
  352         SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
  353         if (SCARG(&bsa, domain) == -1)
  354                 return EINVAL;
  355         SCARG(&bsa, type) = SCARG(uap, type);
  356         SCARG(&bsa, protocol) = SCARG(uap, protocol);
  357         SCARG(&bsa, rsv) = SCARG(uap, rsv);
  358 
  359         return sys_socketpair(l, &bsa, retval);
  360 }
  361 
  362 int
  363 linux_sys_sendto(l, v, retval)
  364         struct lwp *l;
  365         void *v;
  366         register_t *retval;
  367 {
  368         struct linux_sys_sendto_args /* {
  369                 syscallarg(int)                         s;
  370                 syscallarg(void *)                      msg;
  371                 syscallarg(int)                         len;
  372                 syscallarg(int)                         flags;
  373                 syscallarg(struct osockaddr *)          to;
  374                 syscallarg(int)                         tolen;
  375         } */ *uap = v;
  376         struct proc *p = l->l_proc;
  377         struct sys_sendto_args bsa;
  378         int tolen;
  379 
  380         SCARG(&bsa, s) = SCARG(uap, s);
  381         SCARG(&bsa, buf) = SCARG(uap, msg);
  382         SCARG(&bsa, len) = (size_t) SCARG(uap, len);
  383         SCARG(&bsa, flags) = SCARG(uap, flags);
  384         tolen = SCARG(uap, tolen);
  385         if (SCARG(uap, to)) {
  386                 struct sockaddr *sa;
  387                 int error;
  388                 caddr_t sg = stackgap_init(p, 0);
  389 
  390                 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
  391                     SCARG(uap, to), &tolen);
  392                 if (error)
  393                         return (error);
  394 
  395                 SCARG(&bsa, to) = sa;
  396         } else
  397                 SCARG(&bsa, to) = NULL;
  398         SCARG(&bsa, tolen) = tolen;
  399 
  400         return (sys_sendto(l, &bsa, retval));
  401 }
  402 
  403 int
  404 linux_sys_sendmsg(l, v, retval)
  405         struct lwp *l;
  406         void *v;
  407         register_t *retval;
  408 {
  409         struct linux_sys_sendmsg_args /* {
  410                 syscallarg(int) s;
  411                 syscallarg(struct msghdr *) msg;
  412                 syscallarg(u_int) flags;
  413         } */ *uap = v;
  414         struct proc *p = l->l_proc;
  415         struct msghdr   msg;
  416         int             error;
  417         struct iovec    aiov[UIO_SMALLIOV], *iov;
  418         caddr_t sg = 0;
  419         int             bflags;
  420         u_int8_t        *control=NULL;
  421 
  422         error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
  423         if (error)
  424                 return (error);
  425         if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
  426                 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
  427                         return (EMSGSIZE);
  428                 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
  429                     M_IOV, M_WAITOK);
  430         } else
  431                 iov = aiov;
  432         if ((unsigned int)msg.msg_iovlen > 0) {
  433                 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
  434                     (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
  435                 if (error)
  436                         goto done;
  437         }
  438         msg.msg_iov = iov;
  439         msg.msg_flags = 0;
  440 
  441         /* Convert the sockaddr if necessary */
  442         if (msg.msg_name) {
  443                 struct sockaddr *sa;
  444                 sg = stackgap_init(p, 0);
  445 
  446                 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
  447                     (struct osockaddr *) msg.msg_name, &msg.msg_namelen);
  448                 if (error)
  449                         goto done;
  450                 msg.msg_name = sa;
  451         }
  452 
  453         /*
  454          * Translate message flags.
  455          */
  456         bflags = linux_to_bsd_msg_flags(SCARG(uap, flags));
  457         if (bflags < 0) {
  458                 /* Some supported flag */
  459                 error = EINVAL;
  460                 goto done;
  461         }
  462 
  463         /*
  464          * Handle cmsg if there is any.
  465          */
  466         if (CMSG_FIRSTHDR(&msg)) {
  467                 struct cmsghdr cmsg, *cc;
  468                 int changed = 0;
  469                 ssize_t resid = msg.msg_controllen;
  470                 size_t clen, cidx = 0, cspace;
  471 
  472                 /*
  473                  * Limit the size even more than what sockargs() would do,
  474                  * We need to fit into stackgap space.
  475                  */
  476                 if (msg.msg_controllen > (STACKGAPLEN / 2)) {
  477                         /* Sorry guys! */
  478                         error = EMSGSIZE;
  479                         goto done;
  480                 }
  481 
  482                 control = malloc((clen = msg.msg_controllen), M_TEMP, M_WAITOK);
  483                 if (!control) {
  484                         error = ENOMEM;
  485                         goto done;
  486                 }
  487 
  488                 cc = CMSG_FIRSTHDR(&msg);
  489                 do {
  490                         error = copyin(cc, &cmsg, sizeof(cmsg));
  491                         if (error)
  492                                 goto done;
  493 
  494                         /*
  495                          * Sanity check the control message length.
  496                          */
  497                         if (cmsg.cmsg_len > resid
  498                             || cmsg.cmsg_len < sizeof(struct cmsghdr)) {
  499                                 error = EINVAL;
  500                                 goto done;
  501                         }
  502 
  503                         /*
  504                          * Refuse unsupported control messages, and
  505                          * translate fields as appropriate.
  506                          */
  507                         switch (cmsg.cmsg_level) {
  508                         case LINUX_SOL_SOCKET:
  509                                 /* It only differs on some archs */
  510                                 if (LINUX_SOL_SOCKET != SOL_SOCKET) {
  511                                         cmsg.cmsg_level = SOL_SOCKET;
  512                                         changed = 1;
  513                                 }
  514 
  515                                 switch(cmsg.cmsg_type) {
  516                                 case LINUX_SCM_RIGHTS:
  517                                         /* Linux SCM_RIGHTS is same as NetBSD */
  518                                         break;
  519 
  520                                 default:
  521                                         /* other types not supported */
  522                                         error = EINVAL;
  523                                         goto done;
  524                                 }
  525                                 break;
  526                         default:
  527                                 /* pray and leave intact */
  528                                 break;
  529                         }
  530 
  531                         cspace = CMSG_SPACE(cmsg.cmsg_len - sizeof(cmsg));
  532 
  533                         /* Check the buffer is big enough */
  534                         if (__predict_false(cidx + cspace > clen)) {
  535                                 u_int8_t *nc;
  536 
  537                                 clen = cidx + cspace;
  538                                 nc = realloc(control, clen, M_TEMP, M_WAITOK);
  539                                 if (!nc) {
  540                                         error = ENOMEM;
  541                                         goto done;
  542                                 }
  543                                 control = nc;
  544                         }
  545 
  546                         /* Copy header */
  547                         memcpy(&control[cidx], &cmsg, sizeof(cmsg));
  548 
  549                         /* Zero are between header and data */
  550                         memset(&control[cidx+sizeof(cmsg)], 0,
  551                                 CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg));
  552 
  553                         /* Copyin the data */
  554                         error = copyin(LINUX_CMSG_DATA(cc),
  555                                 CMSG_DATA(control),
  556                                 cmsg.cmsg_len - sizeof(cmsg));
  557                         if (error)
  558                                 goto done;
  559 
  560                         /*
  561                          * If there is alignment difference, we changed
  562                          * layout of cmsg.
  563                          */
  564                         if (LINUX_CMSG_ALIGNDIFF)
  565                                 changed = 1;
  566 
  567                         resid -= cspace;
  568                         cidx += cspace;
  569                 } while ((cc = LINUX_CMSG_NXTHDR(&msg, cc)) && resid > 0);
  570 
  571                 /*
  572                  * If any of the passed control message needed
  573                  * a change, put the changed data into stackgap
  574                  * and adjust msg appropriately.
  575                  */
  576                 if (changed) {
  577                         char *newc;
  578 
  579                         /*
  580                          * Check again the total len is maximum half of
  581                          * stackgap. The length might change if the
  582                          * alignment is different.
  583                          */
  584                         if (clen > STACKGAPLEN/2) {
  585                                 error = EMSGSIZE;
  586                                 goto done;
  587                         }
  588 
  589                         /*
  590                          * Allocate space on stack within stackgap, and
  591                          * copy changed data there.
  592                          */
  593                         if (!sg)
  594                                 sg = stackgap_init(p, STACKGAPLEN/3);
  595                         newc = stackgap_alloc(p, &sg, clen);
  596                         if (!newc) {
  597                                 error = ENOMEM;
  598                                 goto done;
  599                         }
  600 
  601                         error = copyout(control, newc, clen);
  602                         if (error)
  603                                 goto done;
  604 
  605                         msg.msg_control = newc;
  606                         msg.msg_controllen = clen;
  607                 }
  608 
  609                 free(control, M_TEMP);
  610                 control = NULL;
  611         }
  612 
  613         error = sendit(p, SCARG(uap, s), &msg, bflags, retval);
  614 
  615 done:
  616         if (control)
  617                 free(control, M_TEMP);
  618         if (iov != aiov)
  619                 free(iov, M_IOV);
  620         return (error);
  621 }
  622 
  623 int
  624 linux_sys_recvfrom(l, v, retval)
  625         struct lwp *l;
  626         void *v;
  627         register_t *retval;
  628 {
  629         struct linux_sys_recvfrom_args /* {
  630                 syscallarg(int) s;
  631                 syscallarg(void *) buf;
  632                 syscallarg(int) len;
  633                 syscallarg(int) flags;
  634                 syscallarg(struct osockaddr *) from;
  635                 syscallarg(int *) fromlenaddr;
  636         } */ *uap = v;
  637         int             error;
  638         struct sys_recvfrom_args bra;
  639 
  640         SCARG(&bra, s) = SCARG(uap, s);
  641         SCARG(&bra, buf) = SCARG(uap, buf);
  642         SCARG(&bra, len) = SCARG(uap, len);
  643         SCARG(&bra, flags) = SCARG(uap, flags);
  644         SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
  645         SCARG(&bra, fromlenaddr) = SCARG(uap, fromlenaddr);
  646 
  647         if ((error = sys_recvfrom(l, &bra, retval)))
  648                 return (error);
  649 
  650         if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
  651                 return (error);
  652 
  653         return (0);
  654 }
  655 
  656 int
  657 linux_sys_recvmsg(l, v, retval)
  658         struct lwp *l;
  659         void *v;
  660         register_t *retval;
  661 {
  662         struct linux_sys_recvmsg_args /* {
  663                 syscallarg(int) s;
  664                 syscallarg(struct msghdr *) msg;
  665                 syscallarg(u_int) flags;
  666         } */ *uap = v;
  667         struct msghdr   msg;
  668         int             error;
  669         struct sys_recvmsg_args bsa;
  670         int lflags;
  671         u_int8_t *ocontrol = NULL; /* XXX: gcc */
  672         socklen_t ocontrollen = 0;
  673 
  674         /*
  675          * Data alignment is different on some architectures. If control
  676          * message is expected, we must arrange for the control message
  677          * to be initially put elsewhere, and copy to target place
  678          * with Linux alignment.
  679          */
  680         if (LINUX_CMSG_ALIGNDIFF) {
  681                 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
  682                 if (error)
  683                         return (error);
  684 
  685                 if (CMSG_FIRSTHDR(&msg)) {
  686                         caddr_t sg;
  687 
  688                         /* Need to fit within stackgap */
  689                         if (msg.msg_controllen > STACKGAPLEN/2) {
  690                                 /* Sorry guys! */
  691                                 return (EINVAL);
  692                         }
  693 
  694                         sg = stackgap_init(l->l_proc, STACKGAPLEN/3);
  695 
  696                         ocontrol = msg.msg_control;
  697                         ocontrollen = msg.msg_controllen;
  698 
  699                         /* space for at least one message's worth align */
  700                         msg.msg_controllen += CMSG_ALIGN(1);
  701 
  702                         msg.msg_control = stackgap_alloc(l->l_proc, &sg,
  703                                 msg.msg_controllen);
  704                         if (!msg.msg_control)
  705                                 return (ENOMEM);
  706 
  707                         /*
  708                          * Okay to overwrite the original structure, it's
  709                          * supposed to be writable.
  710                          */
  711                         error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
  712                         if (error)
  713                                 return (error);
  714                 }
  715         }
  716 
  717         SCARG(&bsa, s) = SCARG(uap, s);
  718         SCARG(&bsa, msg) = SCARG(uap, msg);
  719         SCARG(&bsa, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
  720 
  721         if (SCARG(&bsa, flags) < 0) {
  722                 /* Some unsupported flag */
  723                 return (EINVAL);
  724         }
  725 
  726         if ((error = sys_recvmsg(l, &bsa, retval)))
  727                 goto done;
  728 
  729         /* Fixup sockaddr */
  730         error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
  731                        sizeof(msg));
  732         if (error)
  733                 goto done;
  734 
  735         if (msg.msg_name && msg.msg_namelen > 2) {
  736                 if ((error = linux_sa_put(msg.msg_name)))
  737                         goto done;
  738         }
  739 
  740         /* Fixup msg flags */
  741         lflags = bsd_to_linux_msg_flags(msg.msg_flags);
  742         if (lflags < 0) {
  743                 /* Some flag unsupported by Linux */
  744                 error = EINVAL;
  745                 goto done;
  746         }
  747         error = copyout(&lflags, (u_int8_t *) SCARG(uap, msg) +
  748                         offsetof(struct msghdr, msg_flags), sizeof(lflags));
  749         if (error)
  750                 goto done;
  751 
  752         /*
  753          * Fixup cmsg. We handle two things:
  754          * 1. different values for level/type on some archs
  755          * 2. different alignment of CMSG_DATA on some archs
  756          */
  757         if (CMSG_FIRSTHDR(&msg)) {
  758                 struct cmsghdr cmsg, *cc;
  759                 int changed = 0;
  760                 size_t resid = ocontrollen;
  761 
  762                 cc = CMSG_FIRSTHDR(&msg);
  763                 do {
  764                         error = copyin(cc, &cmsg, sizeof(cmsg));
  765                         if (error)
  766                                 goto done;
  767 
  768                         switch (cmsg.cmsg_level) {
  769                         case SOL_SOCKET:
  770                                 if (SOL_SOCKET != LINUX_SOL_SOCKET) {
  771                                         cmsg.cmsg_level = LINUX_SOL_SOCKET;
  772                                         changed = 1;
  773                                 }
  774 
  775                                 switch (cmsg.cmsg_type) {
  776                                 case SCM_RIGHTS:
  777                                         /* Linux SCM_RIGHTS is same as NetBSD */
  778                                         break;
  779                                         
  780                                 default:
  781                                         /* other types not supported */
  782                                         error = EINVAL;
  783                                         goto done;
  784                                 }
  785                         default:
  786                                 /* pray and leave intact */
  787                                 break;
  788                         }
  789 
  790                         if (LINUX_CMSG_ALIGNDIFF) {
  791                                 int i;
  792                                 u_int8_t d, *sd, *td;
  793 
  794                                 /*
  795                                  * Sanity check.
  796                                  */
  797                                 if (cmsg.cmsg_len > resid
  798                                     || cmsg.cmsg_len < sizeof(cmsg)) {
  799                                         error = EINVAL;
  800                                         goto done;
  801                                 }
  802 
  803                                 /*
  804                                  * Need to copy the cmsg from scratch area
  805                                  * to the original place, converting data
  806                                  * alignment from NetBSD to Linux one.
  807                                  */
  808                                 error = copyout(&cmsg, ocontrol, sizeof(cmsg));
  809                                 if (error)
  810                                         goto done;
  811                                 /* zero pad */
  812                                 for(i=0; i < LINUX_CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg); i++) {
  813                                         copyout("",&ocontrol[sizeof(cmsg)+i],1);
  814                                 }
  815 
  816                                 sd = CMSG_DATA(cc);
  817                                 td = LINUX_CMSG_DATA(ocontrol);
  818 
  819                                 /* This is not particularily effective, but ..*/
  820                                 d = '\0';
  821                                 for(i=0; i < cmsg.cmsg_len - sizeof(cmsg); i++){
  822                                         copyin(sd++, &d, 1);
  823                                         copyout(&d, td++, 1);
  824                                 }
  825 
  826                                 resid -= (td - ocontrol);
  827                                 ocontrol = td;
  828                         } else if (changed) {
  829                                 /* Update cmsghdr in-place */
  830                                 error = copyout(&cmsg, cc, sizeof(cmsg));
  831                                 if (error)
  832                                         goto done;
  833                                 changed = 0;
  834                         }
  835                 } while((cc = CMSG_NXTHDR(&msg, cc)));
  836         }
  837 
  838 done:
  839         return (error);
  840 }
  841 
  842 /*
  843  * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
  844  * is different, the rest matches IPPROTO_* on both systems.
  845  */
  846 int
  847 linux_to_bsd_sopt_level(llevel)
  848         int llevel;
  849 {
  850 
  851         switch (llevel) {
  852         case LINUX_SOL_SOCKET:
  853                 return SOL_SOCKET;
  854         case LINUX_SOL_IP:
  855                 return IPPROTO_IP;
  856         case LINUX_SOL_TCP:
  857                 return IPPROTO_TCP;
  858         case LINUX_SOL_UDP:
  859                 return IPPROTO_UDP;
  860         default:
  861                 return -1;
  862         }
  863 }
  864 
  865 /*
  866  * Convert Linux socket level socket option numbers to NetBSD values.
  867  */
  868 int
  869 linux_to_bsd_so_sockopt(lopt)
  870         int lopt;
  871 {
  872 
  873         switch (lopt) {
  874         case LINUX_SO_DEBUG:
  875                 return SO_DEBUG;
  876         case LINUX_SO_REUSEADDR:
  877                 /* 
  878                  * Linux does not implement SO_REUSEPORT, but allows reuse of a
  879                  * host:port pair through SO_REUSEADDR even if the address is not a
  880                  * multicast-address.  Effectively, this means that we should use
  881                  * SO_REUSEPORT to allow Linux applications to not exit with
  882                  * EADDRINUSE
  883                  */
  884                 return SO_REUSEPORT;
  885         case LINUX_SO_TYPE:
  886                 return SO_TYPE;
  887         case LINUX_SO_ERROR:
  888                 return SO_ERROR;
  889         case LINUX_SO_DONTROUTE:
  890                 return SO_DONTROUTE;
  891         case LINUX_SO_BROADCAST:
  892                 return SO_BROADCAST;
  893         case LINUX_SO_SNDBUF:
  894                 return SO_SNDBUF;
  895         case LINUX_SO_RCVBUF:
  896                 return SO_RCVBUF;
  897         case LINUX_SO_KEEPALIVE:
  898                 return SO_KEEPALIVE;
  899         case LINUX_SO_OOBINLINE:
  900                 return SO_OOBINLINE;
  901         case LINUX_SO_LINGER:
  902                 return SO_LINGER;
  903         case LINUX_SO_PRIORITY:
  904         case LINUX_SO_NO_CHECK:
  905         default:
  906                 return -1;
  907         }
  908 }
  909 
  910 /*
  911  * Convert Linux IP level socket option number to NetBSD values.
  912  */
  913 int
  914 linux_to_bsd_ip_sockopt(lopt)
  915         int lopt;
  916 {
  917 
  918         switch (lopt) {
  919         case LINUX_IP_TOS:
  920                 return IP_TOS;
  921         case LINUX_IP_TTL:
  922                 return IP_TTL;
  923         case LINUX_IP_MULTICAST_TTL:
  924                 return IP_MULTICAST_TTL;
  925         case LINUX_IP_MULTICAST_LOOP:
  926                 return IP_MULTICAST_LOOP;
  927         case LINUX_IP_MULTICAST_IF:
  928                 return IP_MULTICAST_IF;
  929         case LINUX_IP_ADD_MEMBERSHIP:
  930                 return IP_ADD_MEMBERSHIP;
  931         case LINUX_IP_DROP_MEMBERSHIP:
  932                 return IP_DROP_MEMBERSHIP;
  933         default:
  934                 return -1;
  935         }
  936 }
  937 
  938 /*
  939  * Convert Linux TCP level socket option number to NetBSD values.
  940  */
  941 int
  942 linux_to_bsd_tcp_sockopt(lopt)
  943         int lopt;
  944 {
  945 
  946         switch (lopt) {
  947         case LINUX_TCP_NODELAY:
  948                 return TCP_NODELAY;
  949         case LINUX_TCP_MAXSEG:
  950                 return TCP_MAXSEG;
  951         default:
  952                 return -1;
  953         }
  954 }
  955 
  956 /*
  957  * Convert Linux UDP level socket option number to NetBSD values.
  958  */
  959 int
  960 linux_to_bsd_udp_sockopt(lopt)
  961         int lopt;
  962 {
  963 
  964         switch (lopt) {
  965         default:
  966                 return -1;
  967         }
  968 }
  969 
  970 /*
  971  * Another reasonably straightforward function: setsockopt(2).
  972  * The level and option numbers are converted; the values passed
  973  * are not (yet) converted, the ones currently implemented don't
  974  * need conversion, as they are the same on both systems.
  975  */
  976 int
  977 linux_sys_setsockopt(l, v, retval)
  978         struct lwp *l;
  979         void *v;
  980         register_t *retval;
  981 {
  982         struct linux_sys_setsockopt_args /* {
  983                 syscallarg(int) s;
  984                 syscallarg(int) level;
  985                 syscallarg(int) optname;
  986                 syscallarg(void *) optval;
  987                 syscallarg(int) optlen;
  988         } */ *uap = v;
  989         struct sys_setsockopt_args bsa;
  990         int name;
  991 
  992         SCARG(&bsa, s) = SCARG(uap, s);
  993         SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
  994         SCARG(&bsa, val) = SCARG(uap, optval);
  995         SCARG(&bsa, valsize) = SCARG(uap, optlen);
  996 
  997         switch (SCARG(&bsa, level)) {
  998         case SOL_SOCKET:
  999                 name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
 1000                 break;
 1001         case IPPROTO_IP:
 1002                 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
 1003                 break;
 1004         case IPPROTO_TCP:
 1005                 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
 1006                 break;
 1007         case IPPROTO_UDP:
 1008                 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
 1009                 break;
 1010         default:
 1011                 return EINVAL;
 1012         }
 1013 
 1014         if (name == -1)
 1015                 return EINVAL;
 1016         SCARG(&bsa, name) = name;
 1017 
 1018         return sys_setsockopt(l, &bsa, retval);
 1019 }
 1020 
 1021 /*
 1022  * getsockopt(2) is very much the same as setsockopt(2) (see above)
 1023  */
 1024 int
 1025 linux_sys_getsockopt(l, v, retval)
 1026         struct lwp *l;
 1027         void *v;
 1028         register_t *retval;
 1029 {
 1030         struct linux_sys_getsockopt_args /* {
 1031                 syscallarg(int) s;
 1032                 syscallarg(int) level;
 1033                 syscallarg(int) optname;
 1034                 syscallarg(void *) optval;
 1035                 syscallarg(int *) optlen;
 1036         } */ *uap = v;
 1037         struct sys_getsockopt_args bga;
 1038         int name;
 1039 
 1040         SCARG(&bga, s) = SCARG(uap, s);
 1041         SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
 1042         SCARG(&bga, val) = SCARG(uap, optval);
 1043         SCARG(&bga, avalsize) = SCARG(uap, optlen);
 1044 
 1045         switch (SCARG(&bga, level)) {
 1046         case SOL_SOCKET:
 1047                 name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
 1048                 break;
 1049         case IPPROTO_IP:
 1050                 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
 1051                 break;
 1052         case IPPROTO_TCP:
 1053                 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
 1054                 break;
 1055         case IPPROTO_UDP:
 1056                 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
 1057                 break;
 1058         default:
 1059                 return EINVAL;
 1060         }
 1061 
 1062         if (name == -1)
 1063                 return EINVAL;
 1064         SCARG(&bga, name) = name;
 1065 
 1066         return sys_getsockopt(l, &bga, retval);
 1067 }
 1068 
 1069 #define IF_NAME_LEN 16
 1070 
 1071 int
 1072 linux_getifhwaddr(p, retval, fd, data)
 1073         struct proc *p;
 1074         register_t *retval;
 1075         u_int fd;
 1076         void *data;
 1077 {
 1078         /* Not the full structure, just enough to map what we do here */
 1079         struct linux_ifreq {
 1080                 char if_name[IF_NAME_LEN];
 1081                 struct osockaddr hwaddr;
 1082         } lreq;
 1083         struct filedesc *fdp;
 1084         struct file *fp;
 1085         struct ifaddr *ifa;
 1086         struct ifnet *ifp;
 1087         struct sockaddr_dl *sadl;
 1088         int error, found;
 1089         int index, ifnum;
 1090 
 1091         /*
 1092          * We can't emulate this ioctl by calling sys_ioctl() to run
 1093          * SIOCGIFCONF, because the user buffer is not of the right
 1094          * type to take those results.  We can't use kernel buffers to
 1095          * receive the results, as the implementation of sys_ioctl()
 1096          * and ifconf() [which implements SIOCGIFCONF] use
 1097          * copyin()/copyout() which will fail on kernel addresses.
 1098          *
 1099          * So, we must duplicate code from sys_ioctl() and ifconf().  Ugh.
 1100          */
 1101 
 1102         fdp = p->p_fd;
 1103         if ((fp = fd_getfile(fdp, fd)) == NULL)
 1104                 return (EBADF);
 1105 
 1106         FILE_USE(fp);
 1107         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
 1108                 error = EBADF;
 1109                 goto out;
 1110         }
 1111 
 1112         error = copyin(data, (caddr_t)&lreq, sizeof(lreq));
 1113         if (error)
 1114                 goto out;
 1115         lreq.if_name[IF_NAME_LEN-1] = '\0';             /* just in case */
 1116 
 1117         /*
 1118          * Try real interface name first, then fake "ethX"
 1119          */
 1120         for (ifp = ifnet.tqh_first, found = 0;
 1121              ifp != 0 && !found;
 1122              ifp = ifp->if_list.tqe_next) {
 1123                 if (strcmp(lreq.if_name, ifp->if_xname))
 1124                         /* not this interface */
 1125                         continue;
 1126                 found=1;           
 1127                 if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
 1128                         for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
 1129                                 sadl = (struct sockaddr_dl *)ifa->ifa_addr;
 1130                                 /* only return ethernet addresses */
 1131                                 /* XXX what about FDDI, etc. ? */
 1132                                 if (sadl->sdl_family != AF_LINK ||
 1133                                     sadl->sdl_type != IFT_ETHER)
 1134                                         continue;
 1135                                 memcpy((caddr_t)&lreq.hwaddr.sa_data,
 1136                                        LLADDR(sadl),
 1137                                        MIN(sadl->sdl_alen,
 1138                                            sizeof(lreq.hwaddr.sa_data)));
 1139                                 lreq.hwaddr.sa_family =
 1140                                         sadl->sdl_family;
 1141                                 error = copyout((caddr_t)&lreq, data,
 1142                                                 sizeof(lreq));
 1143                                 goto out; 
 1144                         }
 1145                 } else {
 1146                         error = ENODEV;
 1147                         goto out;
 1148                 }
 1149         }
 1150 
 1151         if (strncmp(lreq.if_name, "eth", 3) == 0) {
 1152                 for (ifnum = 0, index = 3;
 1153                      lreq.if_name[index] != '\0' && index < IF_NAME_LEN;
 1154                      index++) {
 1155                         ifnum *= 10;
 1156                         ifnum += lreq.if_name[index] - '';
 1157                 }
 1158 
 1159                 error = EINVAL;                 /* in case we don't find one */
 1160                 for (ifp = ifnet.tqh_first, found = 0;
 1161                      ifp != 0 && !found;
 1162                      ifp = ifp->if_list.tqe_next) {
 1163                         memcpy(lreq.if_name, ifp->if_xname,
 1164                                MIN(IF_NAME_LEN, IFNAMSIZ));
 1165                         if ((ifa = ifp->if_addrlist.tqh_first) == 0)
 1166                                 /* no addresses on this interface */
 1167                                 continue;
 1168                         else 
 1169                                 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
 1170                                         sadl = (struct sockaddr_dl *)ifa->ifa_addr;
 1171                                         /* only return ethernet addresses */
 1172                                         /* XXX what about FDDI, etc. ? */
 1173                                         if (sadl->sdl_family != AF_LINK ||
 1174                                             sadl->sdl_type != IFT_ETHER)
 1175                                                 continue;
 1176                                         if (ifnum--)
 1177                                                 /* not the reqested iface */
 1178                                                 continue;
 1179                                         memcpy((caddr_t)&lreq.hwaddr.sa_data,
 1180                                                LLADDR(sadl),
 1181                                                MIN(sadl->sdl_alen,
 1182                                                    sizeof(lreq.hwaddr.sa_data)));
 1183                                         lreq.hwaddr.sa_family =
 1184                                                 sadl->sdl_family;
 1185                                         error = copyout((caddr_t)&lreq, data,
 1186                                                         sizeof(lreq));
 1187                                         found = 1;
 1188                                         break;
 1189                                 }
 1190                 }
 1191         } else {
 1192                 /* unknown interface, not even an "eth*" name */
 1193                 error = ENODEV;
 1194         }
 1195     
 1196 out:
 1197         FILE_UNUSE(fp, p);
 1198         return error;
 1199 }
 1200 #undef IF_NAME_LEN
 1201 
 1202 int
 1203 linux_ioctl_socket(p, uap, retval)
 1204         struct proc *p;
 1205         struct linux_sys_ioctl_args /* {
 1206                 syscallarg(int) fd;
 1207                 syscallarg(u_long) com;
 1208                 syscallarg(caddr_t) data;
 1209         } */ *uap;
 1210         register_t *retval;
 1211 {
 1212         u_long com;
 1213         int error = 0, isdev = 0, dosys = 1;
 1214         struct sys_ioctl_args ia;
 1215         struct file *fp;
 1216         struct filedesc *fdp;
 1217         struct vnode *vp;
 1218         int (*ioctlf)(struct file *, u_long, void *, struct proc *);
 1219         struct ioctl_pt pt;
 1220 
 1221         fdp = p->p_fd;
 1222         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
 1223                 return (EBADF);
 1224 
 1225         FILE_USE(fp);
 1226 
 1227         if (fp->f_type == DTYPE_VNODE) {
 1228                 vp = (struct vnode *)fp->f_data;
 1229                 isdev = vp->v_type == VCHR;
 1230         }
 1231 
 1232         /*
 1233          * Don't try to interpret socket ioctl calls that are done
 1234          * on a device filedescriptor, just pass them through, to
 1235          * emulate Linux behaviour. Use PTIOCLINUX so that the
 1236          * device will only handle these if it's prepared to do
 1237          * so, to avoid unexpected things from happening.
 1238          */
 1239         if (isdev) {
 1240                 dosys = 0;
 1241                 ioctlf = fp->f_ops->fo_ioctl;
 1242                 pt.com = SCARG(uap, com);
 1243                 pt.data = SCARG(uap, data);
 1244                 error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
 1245                 /*
 1246                  * XXX hack: if the function returns EJUSTRETURN,       
 1247                  * it has stuffed a sysctl return value in pt.data.
 1248                  */
 1249                 if (error == EJUSTRETURN) {
 1250                         retval[0] = (register_t)pt.data;
 1251                         error = 0;
 1252                 }
 1253                 goto out;
 1254         }
 1255 
 1256         com = SCARG(uap, com);
 1257         retval[0] = 0;
 1258 
 1259         switch (com) {
 1260         case LINUX_SIOCGIFCONF:
 1261                 SCARG(&ia, com) = OSIOCGIFCONF;
 1262                 break;
 1263         case LINUX_SIOCGIFFLAGS:
 1264                 SCARG(&ia, com) = SIOCGIFFLAGS;
 1265                 break;
 1266         case LINUX_SIOCSIFFLAGS:
 1267                 SCARG(&ia, com) = SIOCSIFFLAGS;
 1268                 break;
 1269         case LINUX_SIOCGIFADDR:
 1270                 SCARG(&ia, com) = OSIOCGIFADDR;
 1271                 break;
 1272         case LINUX_SIOCGIFDSTADDR:
 1273                 SCARG(&ia, com) = OSIOCGIFDSTADDR;
 1274                 break;
 1275         case LINUX_SIOCGIFBRDADDR:
 1276                 SCARG(&ia, com) = OSIOCGIFBRDADDR;
 1277                 break;
 1278         case LINUX_SIOCGIFNETMASK:
 1279                 SCARG(&ia, com) = OSIOCGIFNETMASK;
 1280                 break;
 1281         case LINUX_SIOCADDMULTI:
 1282                 SCARG(&ia, com) = SIOCADDMULTI;
 1283                 break;
 1284         case LINUX_SIOCDELMULTI:
 1285                 SCARG(&ia, com) = SIOCDELMULTI;
 1286                 break;
 1287         case LINUX_SIOCGIFHWADDR:
 1288                 error = linux_getifhwaddr(p, retval, SCARG(uap, fd),
 1289                                          SCARG(uap, data));
 1290                 dosys = 0;
 1291                 break;
 1292         default:
 1293                 error = EINVAL;
 1294         }
 1295 
 1296 out:
 1297         FILE_UNUSE(fp, p);
 1298 
 1299         if (error ==0 && dosys) {
 1300                 SCARG(&ia, fd) = SCARG(uap, fd);
 1301                 SCARG(&ia, data) = SCARG(uap, data);
 1302                 /* XXX NJWLWP */
 1303                 error = sys_ioctl(curlwp, &ia, retval);
 1304         }
 1305 
 1306         return error;
 1307 }
 1308 
 1309 int
 1310 linux_sys_connect(l, v, retval)
 1311         struct lwp *l;
 1312         void *v;
 1313         register_t *retval;
 1314 {
 1315         struct linux_sys_connect_args /* {
 1316                 syscallarg(int) s;
 1317                 syscallarg(const struct sockaddr *) name;
 1318                 syscallarg(int) namelen;
 1319         } */ *uap = v;
 1320         struct proc *p = l->l_proc;
 1321         int             error;
 1322         struct sockaddr *sa;
 1323         struct sys_connect_args bca;
 1324         caddr_t sg = stackgap_init(p, 0);
 1325         int namlen;
 1326 
 1327         namlen = SCARG(uap, namelen);
 1328         error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
 1329             SCARG(uap, name), &namlen);
 1330         if (error)
 1331                 return (error);
 1332         
 1333         SCARG(&bca, s) = SCARG(uap, s);
 1334         SCARG(&bca, name) = sa;
 1335         SCARG(&bca, namelen) = (unsigned int) namlen;
 1336 
 1337         error = sys_connect(l, &bca, retval);
 1338 
 1339         if (error == EISCONN) {
 1340                 struct file *fp;
 1341                 struct socket *so;
 1342                 int s, state, prflags;
 1343                 
 1344                 /* getsock() will use the descriptor for us */
 1345                 if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0)
 1346                         return EISCONN;
 1347 
 1348                 s = splsoftnet();
 1349                 so = (struct socket *)fp->f_data;
 1350                 state = so->so_state;
 1351                 prflags = so->so_proto->pr_flags;
 1352                 splx(s);
 1353                 FILE_UNUSE(fp, p);
 1354                 /*
 1355                  * We should only let this call succeed once per
 1356                  * non-blocking connect; however we don't have
 1357                  * a convenient place to keep that state..
 1358                  */
 1359                 if ((state & SS_NBIO) && (state & SS_ISCONNECTED) &&
 1360                     (prflags & PR_CONNREQUIRED))
 1361                         return 0;
 1362         }
 1363 
 1364         return (error);
 1365 }
 1366 
 1367 int
 1368 linux_sys_bind(l, v, retval)
 1369         struct lwp *l;
 1370         void *v;
 1371         register_t *retval;
 1372 {
 1373         struct linux_sys_bind_args /* {
 1374                 syscallarg(int) s;
 1375                 syscallarg(const struct osockaddr *) name;
 1376                 syscallarg(int) namelen;
 1377         } */ *uap = v;
 1378         struct proc *p = l->l_proc;
 1379         int             error, namlen;
 1380         struct sys_bind_args bsa;
 1381 
 1382         namlen = SCARG(uap, namelen);
 1383         SCARG(&bsa, s) = SCARG(uap, s);
 1384         if (SCARG(uap, name)) {
 1385                 struct sockaddr *sa;
 1386                 caddr_t sg = stackgap_init(p, 0);
 1387 
 1388                 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
 1389                     SCARG(uap, name), &namlen);
 1390                 if (error)
 1391                         return (error);
 1392 
 1393                 SCARG(&bsa, name) = sa;
 1394         } else
 1395                 SCARG(&bsa, name) = NULL;
 1396         SCARG(&bsa, namelen) = namlen;
 1397 
 1398         return (sys_bind(l, &bsa, retval));
 1399 }
 1400 
 1401 int
 1402 linux_sys_getsockname(l, v, retval)
 1403         struct lwp *l;
 1404         void *v;
 1405         register_t *retval;
 1406 {
 1407         struct linux_sys_getsockname_args /* {
 1408                 syscallarg(int) fdes;
 1409                 syscallarg(caddr_t) asa;
 1410                 syscallarg(int *) alen;
 1411         } */ *uap = v;
 1412         int error;
 1413 
 1414         if ((error = sys_getsockname(l, uap, retval)) != 0)
 1415                 return (error);
 1416 
 1417         if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
 1418                 return (error);
 1419 
 1420         return (0);
 1421 }
 1422 
 1423 int
 1424 linux_sys_getpeername(l, v, retval)
 1425         struct lwp *l;
 1426         void *v;
 1427         register_t *retval;
 1428 {
 1429         struct sys_getpeername_args /* {
 1430                 syscallarg(int) fdes;
 1431                 syscallarg(caddr_t) asa;
 1432                 syscallarg(int *) alen;
 1433         } */ *uap = v;
 1434         int error;
 1435 
 1436         if ((error = sys_getpeername(l, uap, retval)) != 0)
 1437                 return (error);
 1438 
 1439         if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
 1440                 return (error);
 1441 
 1442         return (0);
 1443 }
 1444 
 1445 /*
 1446  * Copy the osockaddr structure pointed to by osa to kernel, adjust
 1447  * family and convert to sockaddr, allocate stackgap and put the
 1448  * the converted structure there, address on stackgap returned in sap.
 1449  */
 1450 static int
 1451 linux_sa_get(p, s, sgp, sap, osa, osalen)
 1452         struct proc *p;
 1453         int s;
 1454         caddr_t *sgp;
 1455         struct sockaddr **sap;
 1456         const struct osockaddr *osa;
 1457         int *osalen;
 1458 {
 1459         int error=0, bdom;
 1460         struct sockaddr *sa, *usa;
 1461         struct osockaddr *kosa = (struct osockaddr *) &sa;
 1462         int alloclen;
 1463 #ifdef INET6
 1464         int oldv6size;
 1465         struct sockaddr_in6 *sin6;
 1466 #endif
 1467 
 1468         if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
 1469                 DPRINTF(("bad osa=%p osalen=%d\n", osa, *osalen));
 1470                 return (EINVAL);
 1471         }
 1472 
 1473         alloclen = *osalen;
 1474 #ifdef INET6
 1475         oldv6size = 0;
 1476         /*
 1477          * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
 1478          * if it's a v4-mapped address, so reserve the proper space
 1479          * for it.
 1480          */
 1481         if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
 1482                 alloclen = sizeof (struct sockaddr_in6);
 1483                 oldv6size = 1;
 1484         }
 1485 #endif
 1486 
 1487         kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
 1488 
 1489         if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
 1490                 DPRINTF(("error copying osa %d\n", error));
 1491                 goto out;
 1492         }
 1493 
 1494         bdom = linux_to_bsd_domain(kosa->sa_family);
 1495         if (bdom == -1) {
 1496                 DPRINTF(("bad linux family=%d\n", kosa->sa_family));
 1497                 error = EINVAL;
 1498                 goto out;
 1499         }
 1500 
 1501 #ifdef INET6
 1502         /*
 1503          * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
 1504          * which lacks the scope id compared with RFC2553 one. If we detect
 1505          * the situation, reject the address and write a message to system log.
 1506          *
 1507          * Still accept addresses for which the scope id is not used.
 1508          */
 1509         if (oldv6size && bdom == AF_INET6) {
 1510                 sin6 = (struct sockaddr_in6 *)kosa;
 1511                 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
 1512                     (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
 1513                      !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
 1514                      !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
 1515                      !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
 1516                      !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
 1517                         sin6->sin6_scope_id = 0;
 1518                 } else {
 1519                         struct proc *p = curproc;       /* XXX */
 1520                         int uid = p->p_cred && p->p_ucred ? 
 1521                                         p->p_ucred->cr_uid : -1;
 1522 
 1523                         log(LOG_DEBUG,
 1524                             "pid %d (%s), uid %d: obsolete pre-RFC2553 "
 1525                             "sockaddr_in6 rejected",
 1526                             p->p_pid, p->p_comm, uid);
 1527                         error = EINVAL;
 1528                         goto out;
 1529                 }
 1530         }
 1531 #endif
 1532 
 1533         /*
 1534          * If the family is unspecified, use address family of the
 1535          * socket. This avoid triggering COMPAT_43 struct socket family check
 1536          * in sockargs() on little-endian machines, and strict family checks
 1537          * in netinet/in_pcb.c et.al.
 1538          */
 1539         if (bdom == AF_UNSPEC) {
 1540                 struct file *fp;
 1541                 struct socket *so;
 1542 
 1543                 /* getsock() will use the descriptor for us */
 1544                 if ((error = getsock(p->p_fd, s, &fp)) != 0)
 1545                         goto out;
 1546 
 1547                 so = (struct socket *)fp->f_data;
 1548                 bdom = so->so_proto->pr_domain->dom_family;
 1549 
 1550                 FILE_UNUSE(fp, p);
 1551 
 1552                 DPRINTF(("AF_UNSPEC family adjusted to %d\n", bdom));
 1553         }
 1554 
 1555         if (bdom == AF_INET) {
 1556                 alloclen = sizeof(struct sockaddr_in);
 1557         }
 1558 
 1559         sa = (struct sockaddr *) kosa;
 1560         sa->sa_family = bdom;
 1561         sa->sa_len = alloclen;
 1562 #ifdef DEBUG_LINUX
 1563         DPRINTF(("family %d, len = %d [ ", sa->sa_family, sa->sa_len));
 1564         for (bdom = 0; bdom < sizeof(sa->sa_data); bdom++)
 1565             DPRINTF(("%02x ", sa->sa_data[bdom]));
 1566         DPRINTF(("\n"));
 1567 #endif
 1568 
 1569         usa = (struct sockaddr *) stackgap_alloc(p, sgp, alloclen);
 1570         if (!usa) {
 1571                 error = ENOMEM;
 1572                 goto out;
 1573         }
 1574 
 1575         if ((error = copyout(sa, usa, alloclen))) {
 1576                 DPRINTF(("error copying out socket %d\n", error));
 1577                 goto out;
 1578         }
 1579 
 1580         *sap = usa;
 1581 
 1582     out:
 1583         *osalen = alloclen;
 1584         free(kosa, M_TEMP);
 1585         return (error);
 1586 }
 1587 
 1588 static int
 1589 linux_sa_put(osa)
 1590         struct osockaddr *osa;
 1591 {
 1592         struct sockaddr sa;
 1593         struct osockaddr *kosa;
 1594         int error, bdom, len;
 1595 
 1596         /*
 1597          * Only read/write the sockaddr family and length part, the rest is
 1598          * not changed.
 1599          */
 1600         len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
 1601 
 1602         error = copyin((caddr_t) osa, (caddr_t) &sa, len);
 1603         if (error)
 1604                 return (error);
 1605 
 1606         bdom = bsd_to_linux_domain(sa.sa_family);
 1607         if (bdom == -1)
 1608                 return (EINVAL);
 1609 
 1610         /* Note: we convert from sockaddr to osockaddr here, too */
 1611         kosa = (struct osockaddr *) &sa;
 1612         kosa->sa_family = bdom;
 1613         error = copyout(kosa, osa, len);
 1614         if (error)
 1615                 return (error);
 1616 
 1617         return (0);
 1618 }
 1619 
 1620 int
 1621 linux_sys_recv(l, v, retval)
 1622         struct lwp *l;
 1623         void *v;
 1624         register_t *retval;
 1625 {
 1626         struct linux_sys_recv_args /* {
 1627                 syscallarg(int) s;
 1628                 syscallarg(void *) buf;
 1629                 syscallarg(int) len;
 1630                 syscallarg(int) flags;
 1631         } */ *uap = v;
 1632         struct sys_recvfrom_args bra;
 1633 
 1634 
 1635         SCARG(&bra, s) = SCARG(uap, s);
 1636         SCARG(&bra, buf) = SCARG(uap, buf);
 1637         SCARG(&bra, len) = (size_t) SCARG(uap, len);
 1638         SCARG(&bra, flags) = SCARG(uap, flags);
 1639         SCARG(&bra, from) = NULL;
 1640         SCARG(&bra, fromlenaddr) = NULL;
 1641 
 1642         return (sys_recvfrom(l, &bra, retval));
 1643 }
 1644 
 1645 int
 1646 linux_sys_send(l, v, retval)
 1647         struct lwp *l;
 1648         void *v;
 1649         register_t *retval;
 1650 {
 1651         struct linux_sys_send_args /* {
 1652                 syscallarg(int) s;
 1653                 syscallarg(caddr_t) buf;
 1654                 syscallarg(int) len;
 1655                 syscallarg(int) flags;
 1656         } */ *uap = v;
 1657         struct sys_sendto_args bsa;
 1658 
 1659         SCARG(&bsa, s)          = SCARG(uap, s);
 1660         SCARG(&bsa, buf)        = SCARG(uap, buf);
 1661         SCARG(&bsa, len)        = SCARG(uap, len);
 1662         SCARG(&bsa, flags)      = SCARG(uap, flags);
 1663         SCARG(&bsa, to)         = NULL;
 1664         SCARG(&bsa, tolen)      = 0;
 1665 
 1666         return (sys_sendto(l, &bsa, retval));
 1667 }
 1668 
 1669 int
 1670 linux_sys_accept(l, v, retval)
 1671         struct lwp *l;
 1672         void *v;
 1673         register_t *retval;
 1674 {
 1675         struct linux_sys_accept_args /* {
 1676                 syscallarg(int) s;
 1677                 syscallarg(struct osockaddr *) name;
 1678                 syscallarg(int *) anamelen;
 1679         } */ *uap = v;
 1680         int error;
 1681         struct sys_accept_args baa;
 1682 
 1683         SCARG(&baa, s)          = SCARG(uap, s);
 1684         SCARG(&baa, name)       = (struct sockaddr *) SCARG(uap, name);
 1685         SCARG(&baa, anamelen)   = (unsigned int *) SCARG(uap, anamelen);
 1686 
 1687         if ((error = sys_accept(l, &baa, retval)))
 1688                 return (error);
 1689 
 1690         if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name))))
 1691                 return (error);
 1692 
 1693         return (0);
 1694 }

Cache object: 2e3edbe087601e3cd55f92a4df680d88


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