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/linux32/common/linux32_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: linux32_socket.c,v 1.9.4.1 2009/11/28 15:45:02 bouyer Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   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. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Emmanuel Dreyfus
   17  * 4. The name of the author may not be used to endorse or promote 
   18  *    products derived from this software without specific prior written 
   19  *    permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 
   22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
   23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 
   25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 
   36 __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.9.4.1 2009/11/28 15:45:02 bouyer Exp $");
   37 
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/fstypes.h>
   41 #include <sys/signal.h>
   42 #include <sys/dirent.h>
   43 #include <sys/kernel.h>
   44 #include <sys/fcntl.h>
   45 #include <sys/select.h>
   46 #include <sys/proc.h>
   47 #include <sys/ucred.h>
   48 #include <sys/swap.h>
   49 #include <sys/file.h>
   50 #include <sys/vnode.h>
   51 #include <sys/filedesc.h>
   52 
   53 #include <machine/types.h>
   54 
   55 #include <net/if.h>
   56 #include <net/if_dl.h>
   57 #include <net/if_types.h>
   58 #include <net/route.h>
   59 
   60 #include <netinet/in.h>
   61 #include <netinet/ip_mroute.h>
   62 
   63 #include <sys/syscallargs.h>
   64 
   65 #include <compat/netbsd32/netbsd32.h>
   66 #include <compat/netbsd32/netbsd32_ioctl.h>
   67 #include <compat/netbsd32/netbsd32_conv.h>
   68 #include <compat/netbsd32/netbsd32_syscallargs.h>
   69 
   70 #include <compat/sys/socket.h>
   71 #include <compat/sys/sockio.h>
   72 
   73 #include <compat/linux/common/linux_types.h>
   74 #include <compat/linux/common/linux_types.h>
   75 #include <compat/linux/common/linux_signal.h>
   76 #include <compat/linux/common/linux_machdep.h>
   77 #include <compat/linux/common/linux_misc.h>
   78 #include <compat/linux/common/linux_oldolduname.h>
   79 #include <compat/linux/common/linux_ioctl.h>
   80 #include <compat/linux/common/linux_sockio.h>
   81 #include <compat/linux/linux_syscallargs.h>
   82 
   83 #include <compat/linux32/common/linux32_types.h>
   84 #include <compat/linux32/common/linux32_signal.h>
   85 #include <compat/linux32/common/linux32_machdep.h>
   86 #include <compat/linux32/common/linux32_sysctl.h>
   87 #include <compat/linux32/common/linux32_socketcall.h>
   88 #include <compat/linux32/common/linux32_sockio.h>
   89 #include <compat/linux32/common/linux32_ioctl.h>
   90 #include <compat/linux32/linux32_syscallargs.h>
   91 
   92 int linux32_getifname(struct lwp *, register_t *, void *);
   93 int linux32_getifconf(struct lwp *, register_t *, void *);
   94 int linux32_getifhwaddr(struct lwp *, register_t *, u_int, void *);
   95 
   96 int
   97 linux32_sys_socketpair(struct lwp *l, const struct linux32_sys_socketpair_args *uap, register_t *retval)
   98 {
   99         /* {
  100                 syscallarg(int) domain;
  101                 syscallarg(int) type;
  102                 syscallarg(int) protocol;
  103                 syscallarg(netbsd32_intp) rsv;
  104         } */
  105         struct linux_sys_socketpair_args ua;
  106 
  107         NETBSD32TO64_UAP(domain);
  108         NETBSD32TO64_UAP(type);
  109         NETBSD32TO64_UAP(protocol);
  110         NETBSD32TOP_UAP(rsv, int)
  111 
  112         return linux_sys_socketpair(l, &ua, retval);
  113 }
  114 
  115 int
  116 linux32_sys_sendto(struct lwp *l, const struct linux32_sys_sendto_args *uap, register_t *retval)
  117 {
  118         /* {
  119                 syscallarg(int) s;
  120                 syscallarg(netbsd32_voidp) msg;
  121                 syscallarg(int) len;
  122                 syscallarg(int) flags;
  123                 syscallarg(netbsd32_osockaddrp_t) to;
  124                 syscallarg(int) tolen;
  125         } */
  126         struct linux_sys_sendto_args ua;
  127 
  128         NETBSD32TO64_UAP(s);
  129         NETBSD32TOP_UAP(msg, void);
  130         NETBSD32TO64_UAP(len);
  131         NETBSD32TO64_UAP(flags);
  132         NETBSD32TOP_UAP(to, struct osockaddr);
  133         NETBSD32TO64_UAP(tolen);
  134 
  135         return linux_sys_sendto(l, &ua, retval);
  136 }
  137 
  138 
  139 int
  140 linux32_sys_recvfrom(struct lwp *l, const struct linux32_sys_recvfrom_args *uap, register_t *retval)
  141 {
  142         /* {
  143                 syscallarg(int) s;
  144                 syscallarg(netbsd32_voidp) buf;
  145                 syscallarg(netbsd32_size_t) len;
  146                 syscallarg(int) flags;
  147                 syscallarg(netbsd32_osockaddrp_t) from;
  148                 syscallarg(netbsd32_intp) fromlenaddr;
  149         } */
  150         struct linux_sys_recvfrom_args ua;
  151 
  152         NETBSD32TO64_UAP(s);
  153         NETBSD32TOP_UAP(buf, void);
  154         NETBSD32TO64_UAP(len);
  155         NETBSD32TO64_UAP(flags);
  156         NETBSD32TOP_UAP(from, struct osockaddr);
  157         NETBSD32TOP_UAP(fromlenaddr, unsigned int);
  158 
  159         return linux_sys_recvfrom(l, &ua, retval);
  160 }
  161 
  162 int
  163 linux32_sys_setsockopt(struct lwp *l, const struct linux32_sys_setsockopt_args *uap, register_t *retval)
  164 {
  165         /* {
  166                 syscallarg(int) s;
  167                 syscallarg(int) level;
  168                 syscallarg(int) optname;
  169                 syscallarg(netbsd32_voidp) optval;
  170                 syscallarg(int) optlen;
  171         } */
  172         struct linux_sys_setsockopt_args ua;
  173 
  174         NETBSD32TO64_UAP(s);
  175         NETBSD32TO64_UAP(level);
  176         NETBSD32TO64_UAP(optname);
  177         NETBSD32TOP_UAP(optval, void);
  178         NETBSD32TO64_UAP(optlen);
  179 
  180         return linux_sys_setsockopt(l, &ua, retval);
  181 }
  182 
  183 
  184 int
  185 linux32_sys_getsockopt(struct lwp *l, const struct linux32_sys_getsockopt_args *uap, register_t *retval)
  186 {
  187         /* {
  188                 syscallarg(int) s;
  189                 syscallarg(int) level;
  190                 syscallarg(int) optname;
  191                 syscallarg(netbsd32_voidp) optval;
  192                 syscallarg(netbsd32_intp) optlen;
  193         } */
  194         struct linux_sys_getsockopt_args ua;
  195 
  196         NETBSD32TO64_UAP(s);
  197         NETBSD32TO64_UAP(level);
  198         NETBSD32TO64_UAP(optname);
  199         NETBSD32TOP_UAP(optval, void);
  200         NETBSD32TOP_UAP(optlen, int);
  201 
  202         return linux_sys_getsockopt(l, &ua, retval);
  203 }
  204 
  205 int
  206 linux32_sys_socket(struct lwp *l, const struct linux32_sys_socket_args *uap, register_t *retval)
  207 {
  208         /* {
  209                 syscallarg(int) domain;
  210                 syscallarg(int) type;
  211                 syscallarg(int) protocol;
  212         } */
  213         struct linux_sys_socket_args ua;
  214 
  215         NETBSD32TO64_UAP(domain);
  216         NETBSD32TO64_UAP(type);
  217         NETBSD32TO64_UAP(protocol);
  218 
  219         return linux_sys_socket(l, &ua, retval);
  220 }
  221 
  222 int
  223 linux32_sys_bind(struct lwp *l, const struct linux32_sys_bind_args *uap, register_t *retval)
  224 {
  225         /* {
  226                 syscallarg(int) s;
  227                 syscallarg(netbsd32_osockaddrp_t) name;
  228                 syscallarg(int) namelen;
  229         } */
  230         struct linux_sys_bind_args ua;
  231 
  232         NETBSD32TO64_UAP(s);
  233         NETBSD32TOP_UAP(name, struct osockaddr)
  234         NETBSD32TO64_UAP(namelen);
  235 
  236         return linux_sys_bind(l, &ua, retval);
  237 }
  238 
  239 int
  240 linux32_sys_connect(struct lwp *l, const struct linux32_sys_connect_args *uap, register_t *retval)
  241 {
  242         /* {
  243                 syscallarg(int) s;
  244                 syscallarg(netbsd32_osockaddrp_t) name;
  245                 syscallarg(int) namelen;
  246         } */
  247         struct linux_sys_connect_args ua;
  248 
  249         NETBSD32TO64_UAP(s);
  250         NETBSD32TOP_UAP(name, struct osockaddr)
  251         NETBSD32TO64_UAP(namelen);
  252 
  253 #ifdef DEBUG_LINUX
  254         printf("linux32_sys_connect: s = %d, name = %p, namelen = %d\n",
  255                 SCARG(&ua, s), SCARG(&ua, name), SCARG(&ua, namelen));
  256 #endif
  257 
  258         return linux_sys_connect(l, &ua, retval);
  259 }
  260 
  261 int
  262 linux32_sys_accept(struct lwp *l, const struct linux32_sys_accept_args *uap, register_t *retval)
  263 {
  264         /* {
  265                 syscallarg(int) s;
  266                 syscallarg(netbsd32_osockaddrp_t) name;
  267                 syscallarg(netbsd32_intp) anamelen;
  268         } */
  269         struct linux_sys_accept_args ua;
  270 
  271         NETBSD32TO64_UAP(s);
  272         NETBSD32TOP_UAP(name, struct osockaddr)
  273         NETBSD32TOP_UAP(anamelen, int);
  274 
  275         return linux_sys_accept(l, &ua, retval);
  276 }
  277 
  278 int
  279 linux32_sys_getpeername(struct lwp *l, const struct linux32_sys_getpeername_args *uap, register_t *retval)
  280 {
  281         /* {
  282                 syscallarg(int) fdes;
  283                 syscallarg(netbsd32_sockaddrp_t) asa;
  284                 syscallarg(netbsd32_intp) alen;
  285         } */
  286         struct linux_sys_getpeername_args ua;
  287 
  288         NETBSD32TO64_UAP(fdes);
  289         NETBSD32TOP_UAP(asa, struct sockaddr)
  290         NETBSD32TOP_UAP(alen, int);
  291 
  292         return linux_sys_getpeername(l, &ua, retval);
  293 }
  294 
  295 int
  296 linux32_sys_getsockname(struct lwp *l, const struct linux32_sys_getsockname_args *uap, register_t *retval)
  297 {
  298         /* {
  299                 syscallarg(int) fdec;
  300                 syscallarg(netbsd32_charp) asa;
  301                 syscallarg(netbsd32_intp) alen;
  302         } */
  303         struct linux_sys_getsockname_args ua;
  304 
  305         NETBSD32TO64_UAP(fdec);
  306         NETBSD32TOP_UAP(asa, char)
  307         NETBSD32TOP_UAP(alen, int);
  308 
  309         return linux_sys_getsockname(l, &ua, retval);
  310 }
  311 
  312 int
  313 linux32_sys_sendmsg(struct lwp *l, const struct linux32_sys_sendmsg_args *uap, register_t *retval)
  314 {
  315         /* {
  316                 syscallarg(int) s;
  317                 syscallarg(netbsd32_msghdrp_t) msg;
  318                 syscallarg(int) flags;
  319         } */
  320         struct linux_sys_sendmsg_args ua;
  321 
  322         NETBSD32TO64_UAP(s);
  323         NETBSD32TOP_UAP(msg, struct msghdr);
  324         NETBSD32TO64_UAP(flags);
  325 
  326         return linux_sys_sendmsg(l, &ua, retval);
  327 }
  328 
  329 int
  330 linux32_sys_recvmsg(struct lwp *l, const struct linux32_sys_recvmsg_args *uap, register_t *retval)
  331 {
  332         /* {
  333                 syscallarg(int) s;
  334                 syscallarg(netbsd32_msghdrp_t) msg;
  335                 syscallarg(int) flags;
  336         } */
  337         struct linux_sys_recvmsg_args ua;
  338 
  339         NETBSD32TO64_UAP(s);
  340         NETBSD32TOP_UAP(msg, struct msghdr);
  341         NETBSD32TO64_UAP(flags);
  342 
  343         return linux_sys_recvmsg(l, &ua, retval);
  344 }
  345 
  346 int
  347 linux32_sys_send(struct lwp *l, const struct linux32_sys_send_args *uap, register_t *retval)
  348 {
  349         /* {
  350                 syscallarg(int) s;
  351                 syscallarg(netbsd32_voidp) buf;
  352                 syscallarg(int) len;
  353                 syscallarg(int) flags;
  354         } */
  355         struct sys_sendto_args ua;
  356 
  357         NETBSD32TO64_UAP(s);
  358         NETBSD32TOP_UAP(buf, void);
  359         NETBSD32TO64_UAP(len);
  360         NETBSD32TO64_UAP(flags);
  361         SCARG(&ua, to) = NULL;
  362         SCARG(&ua, tolen) = 0;
  363 
  364         return sys_sendto(l, &ua, retval);
  365 }
  366 
  367 int
  368 linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, register_t *retval)
  369 {
  370         /* {
  371                 syscallarg(int) s;
  372                 syscallarg(netbsd32_voidp) buf;
  373                 syscallarg(int) len;
  374                 syscallarg(int) flags;
  375         } */
  376         struct sys_recvfrom_args ua;
  377 
  378         NETBSD32TO64_UAP(s);
  379         NETBSD32TOP_UAP(buf, void);
  380         NETBSD32TO64_UAP(len);
  381         NETBSD32TO64_UAP(flags);
  382         SCARG(&ua, from) = NULL;
  383         SCARG(&ua, fromlenaddr) = NULL;
  384 
  385         return sys_recvfrom(l, &ua, retval);
  386 }
  387 
  388 int
  389 linux32_getifname(struct lwp *l, register_t *retval, void *data)
  390 {
  391         struct ifnet *ifp;
  392         struct linux32_ifreq ifr;
  393         int error;
  394 
  395         error = copyin(data, &ifr, sizeof(ifr));
  396         if (error)
  397                 return error;
  398 
  399         if (ifr.ifr_ifru.ifru_ifindex >= if_indexlim)
  400                 return ENODEV;
  401         
  402         ifp = ifindex2ifnet[ifr.ifr_ifru.ifru_ifindex];
  403         if (ifp == NULL)
  404                 return ENODEV;
  405 
  406         strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name));
  407 
  408         return copyout(&ifr, data, sizeof(ifr));
  409 }
  410 
  411 int
  412 linux32_getifconf(struct lwp *l, register_t *retval, void *data)
  413 {
  414         struct linux32_ifreq ifr, *ifrp;
  415         struct netbsd32_ifconf *ifc = data;
  416         struct ifnet *ifp;
  417         struct ifaddr *ifa;
  418         struct sockaddr *sa;
  419         struct osockaddr *osa;
  420         int space, error = 0;
  421         const int sz = (int)sizeof(ifr);
  422 
  423         ifrp = (struct linux32_ifreq *)NETBSD32PTR64(ifc->ifc_req);
  424         if (ifrp == NULL)
  425                 space = 0;
  426         else
  427                 space = ifc->ifc_len;
  428 
  429         IFNET_FOREACH(ifp) {
  430                 (void)strncpy(ifr.ifr_name, ifp->if_xname,
  431                     sizeof(ifr.ifr_name));
  432                 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0')
  433                         return ENAMETOOLONG;
  434                 if (IFADDR_EMPTY(ifp))
  435                         continue;
  436                 IFADDR_FOREACH(ifa, ifp) {
  437                         sa = ifa->ifa_addr;
  438                         if (sa->sa_family != AF_INET ||
  439                             sa->sa_len > sizeof(*osa))
  440                                 continue;
  441                         memcpy(&ifr.ifr_addr, sa, sa->sa_len);
  442                         osa = (struct osockaddr *)&ifr.ifr_addr;
  443                         osa->sa_family = sa->sa_family;
  444                         if (space >= sz) {
  445                                 error = copyout(&ifr, ifrp, sz);
  446                                 if (error != 0)
  447                                         return error;
  448                                 ifrp++;
  449                         }
  450                         space -= sz;
  451                 }
  452         }
  453 
  454         if (ifrp != NULL)
  455                 ifc->ifc_len -= space;
  456         else
  457                 ifc->ifc_len = -space;
  458 
  459         return 0;
  460 }
  461 
  462 int
  463 linux32_getifhwaddr(struct lwp *l, register_t *retval, u_int fd,
  464     void *data)
  465 {
  466         struct linux32_ifreq lreq;
  467         file_t *fp;
  468         struct ifaddr *ifa;
  469         struct ifnet *ifp;
  470         struct sockaddr_dl *sadl;
  471         int error, found;
  472         int index, ifnum;
  473 
  474         /*
  475          * We can't emulate this ioctl by calling sys_ioctl() to run
  476          * SIOCGIFCONF, because the user buffer is not of the right
  477          * type to take those results.  We can't use kernel buffers to
  478          * receive the results, as the implementation of sys_ioctl()
  479          * and ifconf() [which implements SIOCGIFCONF] use
  480          * copyin()/copyout() which will fail on kernel addresses.
  481          *
  482          * So, we must duplicate code from sys_ioctl() and ifconf().  Ugh.
  483          */
  484 
  485         if ((fp = fd_getfile(fd)) == NULL)
  486                 return (EBADF);
  487 
  488         KERNEL_LOCK(1, NULL);
  489 
  490         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
  491                 error = EBADF;
  492                 goto out;
  493         }
  494 
  495         error = copyin(data, &lreq, sizeof(lreq));
  496         if (error)
  497                 goto out;
  498         lreq.ifr_name[LINUX32_IFNAMSIZ-1] = '\0';               /* just in case */
  499 
  500         /*
  501          * Try real interface name first, then fake "ethX"
  502          */
  503         found = 0;
  504         IFNET_FOREACH(ifp) {
  505                 if (found)
  506                         break;
  507                 if (strcmp(lreq.ifr_name, ifp->if_xname))
  508                         /* not this interface */
  509                         continue;
  510                 found=1;
  511                 if (IFADDR_EMPTY(ifp)) {
  512                         error = ENODEV;
  513                         goto out;
  514                 }
  515                 IFADDR_FOREACH(ifa, ifp) {
  516                         sadl = satosdl(ifa->ifa_addr);
  517                         /* only return ethernet addresses */
  518                         /* XXX what about FDDI, etc. ? */
  519                         if (sadl->sdl_family != AF_LINK ||
  520                             sadl->sdl_type != IFT_ETHER)
  521                                 continue;
  522                         memcpy(&lreq.ifr_hwaddr.sa_data, CLLADDR(sadl),
  523                                MIN(sadl->sdl_alen,
  524                                    sizeof(lreq.ifr_hwaddr.sa_data)));
  525                         lreq.ifr_hwaddr.sa_family =
  526                                 sadl->sdl_family;
  527                         error = copyout(&lreq, data, sizeof(lreq));
  528                         goto out;
  529                 }
  530         }
  531 
  532         if (strncmp(lreq.ifr_name, "eth", 3) == 0) {
  533                 for (ifnum = 0, index = 3;
  534                      lreq.ifr_name[index] != '\0' && index < LINUX32_IFNAMSIZ;
  535                      index++) {
  536                         ifnum *= 10;
  537                         ifnum += lreq.ifr_name[index] - '';
  538                 }
  539 
  540                 error = EINVAL;                 /* in case we don't find one */
  541                 found = 0;
  542                 IFNET_FOREACH(ifp) {
  543                         if (found)
  544                                 break;
  545                         memcpy(lreq.ifr_name, ifp->if_xname,
  546                                MIN(LINUX32_IFNAMSIZ, IFNAMSIZ));
  547                         IFADDR_FOREACH(ifa, ifp) {
  548                                 sadl = satosdl(ifa->ifa_addr);
  549                                 /* only return ethernet addresses */
  550                                 /* XXX what about FDDI, etc. ? */
  551                                 if (sadl->sdl_family != AF_LINK ||
  552                                     sadl->sdl_type != IFT_ETHER)
  553                                         continue;
  554                                 if (ifnum--)
  555                                         /* not the reqested iface */
  556                                         continue;
  557                                 memcpy(&lreq.ifr_hwaddr.sa_data,
  558                                        CLLADDR(sadl),
  559                                        MIN(sadl->sdl_alen,
  560                                            sizeof(lreq.ifr_hwaddr.sa_data)));
  561                                 lreq.ifr_hwaddr.sa_family =
  562                                         sadl->sdl_family;
  563                                 error = copyout(&lreq, data, sizeof(lreq));
  564                                 found = 1;
  565                                 break;
  566                         }
  567                 }
  568         } else {
  569                 /* unknown interface, not even an "eth*" name */
  570                 error = ENODEV;
  571         }
  572 
  573 out:
  574         KERNEL_UNLOCK_ONE(NULL);
  575         fd_putfile(fd);
  576         return error;
  577 }
  578 
  579 int
  580 linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval)
  581 {
  582         /* {
  583                 syscallarg(int) fd;
  584                 syscallarg(u_long) com;
  585                 syscallarg(void *) data;
  586         } */
  587         u_long com;
  588         int error = 0, isdev = 0, dosys = 1;
  589         struct netbsd32_ioctl_args ia;
  590         file_t *fp;
  591         struct vnode *vp;
  592         int (*ioctlf)(file_t *, u_long, void *);
  593         struct ioctl_pt pt;
  594 
  595         if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
  596                 return (EBADF);
  597 
  598         if (fp->f_type == DTYPE_VNODE) {
  599                 vp = (struct vnode *)fp->f_data;
  600                 isdev = vp->v_type == VCHR;
  601         }
  602 
  603         /*
  604          * Don't try to interpret socket ioctl calls that are done
  605          * on a device filedescriptor, just pass them through, to
  606          * emulate Linux behaviour. Use PTIOCLINUX so that the
  607          * device will only handle these if it's prepared to do
  608          * so, to avoid unexpected things from happening.
  609          */
  610         if (isdev) {
  611                 dosys = 0;
  612                 ioctlf = fp->f_ops->fo_ioctl;
  613                 pt.com = SCARG(uap, com);
  614                 pt.data = (void *)NETBSD32PTR64(SCARG(uap, data));
  615                 error = ioctlf(fp, PTIOCLINUX, &pt);
  616                 /*
  617                  * XXX hack: if the function returns EJUSTRETURN,
  618                  * it has stuffed a sysctl return value in pt.data.
  619                  */
  620                 if (error == EJUSTRETURN) {
  621                         retval[0] = (register_t)pt.data;
  622                         error = 0;
  623                 }
  624                 goto out;
  625         }
  626 
  627         com = SCARG(uap, com);
  628         retval[0] = 0;
  629 
  630         switch (com) {
  631         case LINUX_SIOCGIFNAME:
  632                 error = linux32_getifname(l, retval, SCARG_P32(uap, data));
  633                 dosys = 0;
  634                 break;
  635         case LINUX_SIOCGIFCONF:
  636                 error = linux32_getifconf(l, retval, SCARG_P32(uap, data));
  637                 dosys = 0;
  638                 break;
  639         case LINUX_SIOCGIFFLAGS:
  640                 SCARG(&ia, com) = OSIOCGIFFLAGS;
  641                 break;
  642         case LINUX_SIOCSIFFLAGS:
  643                 SCARG(&ia, com) = OSIOCSIFFLAGS;
  644                 break;
  645         case LINUX_SIOCGIFADDR:
  646                 SCARG(&ia, com) = OOSIOCGIFADDR;
  647                 break;
  648         case LINUX_SIOCGIFDSTADDR:
  649                 SCARG(&ia, com) = OOSIOCGIFDSTADDR;
  650                 break;
  651         case LINUX_SIOCGIFBRDADDR:
  652                 SCARG(&ia, com) = OOSIOCGIFBRDADDR;
  653                 break;
  654         case LINUX_SIOCGIFNETMASK:
  655                 SCARG(&ia, com) = OOSIOCGIFNETMASK;
  656                 break;
  657         case LINUX_SIOCADDMULTI:
  658                 SCARG(&ia, com) = OSIOCADDMULTI;
  659                 break;
  660         case LINUX_SIOCDELMULTI:
  661                 SCARG(&ia, com) = OSIOCDELMULTI;
  662                 break;
  663         case LINUX_SIOCGIFHWADDR:
  664                 error = linux32_getifhwaddr(l, retval, SCARG(uap, fd),
  665                     SCARG_P32(uap, data));
  666                 dosys = 0;
  667                 break;
  668         default:
  669                 error = EINVAL;
  670         }
  671 
  672  out:
  673         fd_putfile(SCARG(uap, fd));
  674 
  675         if (error == 0 && dosys) {
  676                 SCARG(&ia, fd) = SCARG(uap, fd);
  677                 SCARG(&ia, data) = SCARG(uap, data);
  678                 error = netbsd32_ioctl(curlwp, &ia, retval);
  679         }
  680 
  681         return error;
  682 }

Cache object: fcad7d1594f92bee7eb05bc14bcc0b23


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