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