Home | History | Annotate | Line # | Download | only in common
linux_socketcall.c revision 1.14
      1  1.14  christos /*	$NetBSD: linux_socketcall.c,v 1.14 1996/04/05 00:01:50 christos Exp $	*/
      2   1.1      fvdl 
      3   1.1      fvdl /*
      4   1.1      fvdl  * Copyright (c) 1995 Frank van der Linden
      5   1.1      fvdl  * All rights reserved.
      6   1.1      fvdl  *
      7   1.1      fvdl  * Redistribution and use in source and binary forms, with or without
      8   1.1      fvdl  * modification, are permitted provided that the following conditions
      9   1.1      fvdl  * are met:
     10   1.1      fvdl  * 1. Redistributions of source code must retain the above copyright
     11   1.1      fvdl  *    notice, this list of conditions and the following disclaimer.
     12   1.1      fvdl  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      fvdl  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      fvdl  *    documentation and/or other materials provided with the distribution.
     15   1.1      fvdl  * 3. All advertising materials mentioning features or use of this software
     16   1.1      fvdl  *    must display the following acknowledgement:
     17   1.1      fvdl  *      This product includes software developed for the NetBSD Project
     18   1.1      fvdl  *      by Frank van der Linden
     19   1.1      fvdl  * 4. The name of the author may not be used to endorse or promote products
     20   1.1      fvdl  *    derived from this software without specific prior written permission
     21   1.1      fvdl  *
     22   1.1      fvdl  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23   1.1      fvdl  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24   1.1      fvdl  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25   1.1      fvdl  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26   1.1      fvdl  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27   1.1      fvdl  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28   1.1      fvdl  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29   1.1      fvdl  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30   1.1      fvdl  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31   1.1      fvdl  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32   1.1      fvdl  */
     33   1.1      fvdl 
     34   1.1      fvdl #include <sys/param.h>
     35   1.1      fvdl #include <sys/kernel.h>
     36   1.1      fvdl #include <sys/systm.h>
     37   1.1      fvdl #include <sys/buf.h>
     38   1.1      fvdl #include <sys/malloc.h>
     39   1.1      fvdl #include <sys/ioctl.h>
     40   1.1      fvdl #include <sys/tty.h>
     41   1.1      fvdl #include <sys/file.h>
     42   1.1      fvdl #include <sys/filedesc.h>
     43   1.1      fvdl #include <sys/select.h>
     44   1.1      fvdl #include <sys/socket.h>
     45   1.1      fvdl #include <sys/socketvar.h>
     46   1.1      fvdl #include <net/if.h>
     47   1.1      fvdl #include <netinet/in.h>
     48   1.7   mycroft #include <netinet/tcp.h>
     49   1.1      fvdl #include <sys/mount.h>
     50   1.1      fvdl #include <sys/proc.h>
     51   1.1      fvdl #include <sys/vnode.h>
     52   1.1      fvdl #include <sys/device.h>
     53   1.1      fvdl 
     54   1.1      fvdl #include <sys/syscallargs.h>
     55   1.1      fvdl 
     56   1.1      fvdl #include <compat/linux/linux_types.h>
     57   1.1      fvdl #include <compat/linux/linux_util.h>
     58  1.10   mycroft #include <compat/linux/linux_signal.h>
     59   1.1      fvdl #include <compat/linux/linux_syscallargs.h>
     60   1.1      fvdl #include <compat/linux/linux_ioctl.h>
     61   1.1      fvdl #include <compat/linux/linux_socket.h>
     62   1.1      fvdl #include <compat/linux/linux_socketcall.h>
     63   1.1      fvdl #include <compat/linux/linux_sockio.h>
     64   1.1      fvdl 
     65   1.1      fvdl /*
     66   1.1      fvdl  * All the calls in this file are entered via one common system
     67   1.1      fvdl  * call in Linux, represented here by linux_socketcall()
     68   1.1      fvdl  * Arguments for the various calls are on the user stack. A pointer
     69   1.1      fvdl  * to them is the only thing that is passed. It is up to the various
     70   1.1      fvdl  * calls to copy them in themselves. To make it look better, they
     71   1.1      fvdl  * are copied to structures.
     72   1.1      fvdl  */
     73  1.14  christos 
     74  1.14  christos int linux_to_bsd_domain __P((int));
     75  1.14  christos int linux_socket __P((struct proc *, struct linux_socket_args *, register_t *));
     76  1.14  christos int linux_bind __P((struct proc *, struct linux_bind_args *, register_t *));
     77  1.14  christos int linux_connect __P((struct proc *, struct linux_connect_args *,
     78  1.14  christos     register_t *));
     79  1.14  christos int linux_listen __P((struct proc *, struct linux_listen_args *, register_t *));
     80  1.14  christos int linux_accept __P((struct proc *, struct linux_accept_args *, register_t *));
     81  1.14  christos int linux_getsockname __P((struct proc *, struct linux_getsockname_args *,
     82  1.14  christos     register_t *));
     83  1.14  christos int linux_getpeername __P((struct proc *, struct linux_getpeername_args *,
     84  1.14  christos     register_t *));
     85  1.14  christos int linux_socketpair __P((struct proc *, struct linux_socketpair_args *,
     86  1.14  christos     register_t *));
     87  1.14  christos int linux_send __P((struct proc *, struct linux_send_args *, register_t *));
     88  1.14  christos int linux_recv __P((struct proc *, struct linux_recv_args *, register_t *));
     89  1.14  christos int linux_sendto __P((struct proc *, struct linux_sendto_args *, register_t *));
     90  1.14  christos int linux_recvfrom __P((struct proc *, struct linux_recvfrom_args *,
     91  1.14  christos     register_t *));
     92  1.14  christos int linux_shutdown __P((struct proc *, struct linux_shutdown_args *,
     93  1.14  christos     register_t *));
     94  1.14  christos int linux_to_bsd_sopt_level __P((int));
     95  1.14  christos int linux_to_bsd_so_sockopt __P((int));
     96  1.14  christos int linux_to_bsd_ip_sockopt __P((int));
     97  1.14  christos int linux_to_bsd_tcp_sockopt __P((int));
     98  1.14  christos int linux_to_bsd_udp_sockopt __P((int));
     99  1.14  christos int linux_setsockopt __P((struct proc *, struct linux_setsockopt_args *,
    100  1.14  christos     register_t *));
    101  1.14  christos int linux_getsockopt __P((struct proc *, struct linux_getsockopt_args *,
    102  1.14  christos     register_t *));
    103   1.1      fvdl 
    104   1.1      fvdl /*
    105   1.1      fvdl  * Convert between Linux and BSD socket domain values
    106   1.1      fvdl  */
    107   1.2   mycroft int
    108   1.1      fvdl linux_to_bsd_domain(ldom)
    109   1.1      fvdl 	int ldom;
    110   1.1      fvdl {
    111  1.12   mycroft 
    112   1.1      fvdl 	switch (ldom) {
    113   1.1      fvdl 	case LINUX_AF_UNSPEC:
    114   1.1      fvdl 		return AF_UNSPEC;
    115   1.1      fvdl 	case LINUX_AF_UNIX:
    116   1.1      fvdl 		return AF_LOCAL;
    117   1.1      fvdl 	case LINUX_AF_INET:
    118   1.1      fvdl 		return AF_INET;
    119   1.1      fvdl 	case LINUX_AF_AX25:
    120   1.1      fvdl 		return AF_CCITT;
    121   1.1      fvdl 	case LINUX_AF_IPX:
    122   1.1      fvdl 		return AF_IPX;
    123   1.1      fvdl 	case LINUX_AF_APPLETALK:
    124   1.1      fvdl 		return AF_APPLETALK;
    125   1.1      fvdl 	default:
    126   1.1      fvdl 		return -1;
    127   1.1      fvdl 	}
    128   1.1      fvdl }
    129   1.1      fvdl 
    130   1.2   mycroft int
    131  1.12   mycroft linux_socket(p, uap, retval)
    132   1.1      fvdl 	struct proc *p;
    133   1.1      fvdl 	struct linux_socket_args /* {
    134   1.1      fvdl 		syscallarg(int)	domain;
    135   1.1      fvdl 		syscallarg(int)	type;
    136   1.1      fvdl 		syscallarg(int) protocol;
    137  1.12   mycroft 	} */ *uap;
    138   1.1      fvdl 	register_t *retval;
    139   1.1      fvdl {
    140   1.1      fvdl 	struct linux_socket_args lsa;
    141  1.12   mycroft 	struct sys_socket_args bsa;
    142   1.1      fvdl 	int error;
    143   1.1      fvdl 
    144  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
    145   1.1      fvdl 		return error;
    146   1.1      fvdl 
    147   1.1      fvdl 	SCARG(&bsa, protocol) = lsa.protocol;
    148   1.1      fvdl 	SCARG(&bsa, type) = lsa.type;
    149   1.1      fvdl 	SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
    150   1.1      fvdl 	if (SCARG(&bsa, domain) == -1)
    151   1.1      fvdl 		return EINVAL;
    152  1.12   mycroft 	return sys_socket(p, &bsa, retval);
    153   1.1      fvdl }
    154   1.1      fvdl 
    155   1.2   mycroft int
    156  1.12   mycroft linux_bind(p, uap, retval)
    157   1.1      fvdl 	struct proc *p;
    158   1.1      fvdl 	struct linux_bind_args /* {
    159   1.1      fvdl 		syscallarg(int)	s;
    160   1.1      fvdl 		syscallarg(struct sockaddr *) name;
    161   1.1      fvdl 		syscallarg(int)	namelen;
    162  1.12   mycroft 	} */ *uap;
    163   1.1      fvdl 	register_t *retval;
    164   1.1      fvdl {
    165   1.1      fvdl 	struct linux_bind_args lba;
    166  1.12   mycroft 	struct sys_bind_args bba;
    167   1.1      fvdl 	int error;
    168   1.1      fvdl 
    169  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba)))
    170   1.1      fvdl 		return error;
    171   1.1      fvdl 
    172   1.1      fvdl 	SCARG(&bba, s) = lba.s;
    173   1.1      fvdl 	SCARG(&bba, name) = (caddr_t) lba.name;
    174   1.1      fvdl 	SCARG(&bba, namelen) = lba.namelen;
    175   1.1      fvdl 
    176  1.12   mycroft 	return sys_bind(p, &bba, retval);
    177   1.1      fvdl }
    178   1.1      fvdl 
    179   1.2   mycroft int
    180  1.12   mycroft linux_connect(p, uap, retval)
    181   1.1      fvdl 	struct proc *p;
    182   1.1      fvdl 	struct linux_connect_args /* {
    183   1.1      fvdl 		syscallarg(int)	s;
    184   1.1      fvdl 		syscallarg(struct sockaddr *) name;
    185   1.1      fvdl 		syscallarg(int)	namelen;
    186  1.12   mycroft 	} */ *uap;
    187   1.1      fvdl 	register_t *retval;
    188   1.1      fvdl {
    189   1.1      fvdl 	struct linux_connect_args lca;
    190  1.12   mycroft 	struct sys_connect_args bca;
    191   1.1      fvdl 	int error;
    192   1.1      fvdl 
    193  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca)))
    194   1.1      fvdl 		return error;
    195   1.1      fvdl 
    196   1.1      fvdl 	SCARG(&bca, s) = lca.s;
    197   1.1      fvdl 	SCARG(&bca, name) = (caddr_t) lca.name;
    198   1.1      fvdl 	SCARG(&bca, namelen) = lca.namelen;
    199   1.1      fvdl 
    200  1.12   mycroft 	return sys_connect(p, &bca, retval);
    201   1.1      fvdl }
    202   1.1      fvdl 
    203   1.2   mycroft int
    204  1.12   mycroft linux_listen(p, uap, retval)
    205   1.1      fvdl 	struct proc *p;
    206   1.1      fvdl 	struct linux_listen_args /* {
    207   1.1      fvdl 		syscallarg(int) s;
    208   1.1      fvdl 		syscallarg(int) backlog;
    209  1.12   mycroft 	} */ *uap;
    210  1.12   mycroft 	register_t *retval;
    211   1.1      fvdl {
    212   1.1      fvdl 	struct linux_listen_args lla;
    213  1.12   mycroft 	struct sys_listen_args bla;
    214   1.1      fvdl 	int error;
    215   1.1      fvdl 
    216  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
    217   1.1      fvdl 		return error;
    218   1.1      fvdl 
    219   1.1      fvdl 	SCARG(&bla, s) = lla.s;
    220   1.1      fvdl 	SCARG(&bla, backlog) = lla.backlog;
    221   1.1      fvdl 
    222  1.12   mycroft 	return sys_listen(p, &bla, retval);
    223   1.1      fvdl }
    224   1.1      fvdl 
    225   1.2   mycroft int
    226  1.12   mycroft linux_accept(p, uap, retval)
    227   1.1      fvdl 	struct proc *p;
    228   1.1      fvdl 	struct linux_accept_args /* {
    229   1.1      fvdl 		syscallarg(int) s;
    230   1.1      fvdl 		syscallarg(struct sockaddr *) addr;
    231   1.1      fvdl 		syscallarg(int *) namelen;
    232  1.12   mycroft 	} */ *uap;
    233   1.1      fvdl 	register_t *retval;
    234   1.1      fvdl {
    235   1.1      fvdl 	struct linux_accept_args laa;
    236  1.12   mycroft 	struct compat_43_sys_accept_args baa;
    237   1.1      fvdl 	int error;
    238   1.1      fvdl 
    239  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa)))
    240   1.1      fvdl 		return error;
    241   1.1      fvdl 
    242   1.1      fvdl 	SCARG(&baa, s) = laa.s;
    243   1.1      fvdl 	SCARG(&baa, name) = (caddr_t) laa.addr;
    244   1.1      fvdl 	SCARG(&baa, anamelen) = laa.namelen;
    245   1.1      fvdl 
    246  1.12   mycroft 	return compat_43_sys_accept(p, &baa, retval);
    247   1.1      fvdl }
    248   1.1      fvdl 
    249   1.2   mycroft int
    250  1.12   mycroft linux_getsockname(p, uap, retval)
    251   1.1      fvdl 	struct proc *p;
    252   1.1      fvdl 	struct linux_getsockname_args /* {
    253   1.1      fvdl 		syscallarg(int) s;
    254   1.1      fvdl 		syscallarg(struct sockaddr *) addr;
    255   1.1      fvdl 		syscallarg(int *) namelen;
    256  1.12   mycroft 	} */ *uap;
    257   1.1      fvdl 	register_t *retval;
    258   1.1      fvdl {
    259   1.1      fvdl 	struct linux_getsockname_args lga;
    260  1.12   mycroft 	struct compat_43_sys_getsockname_args bga;
    261   1.1      fvdl 	int error;
    262   1.1      fvdl 
    263  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
    264   1.1      fvdl 		return error;
    265   1.1      fvdl 
    266   1.1      fvdl 	SCARG(&bga, fdec) = lga.s;
    267   1.1      fvdl 	SCARG(&bga, asa) = (caddr_t) lga.addr;
    268   1.1      fvdl 	SCARG(&bga, alen) = lga.namelen;
    269   1.1      fvdl 
    270  1.12   mycroft 	return compat_43_sys_getsockname(p, &bga, retval);
    271   1.1      fvdl }
    272   1.1      fvdl 
    273   1.2   mycroft int
    274  1.12   mycroft linux_getpeername(p, uap, retval)
    275   1.1      fvdl 	struct proc *p;
    276   1.1      fvdl 	struct linux_getpeername_args /* {
    277   1.1      fvdl 		syscallarg(int) s;
    278   1.1      fvdl 		syscallarg(struct sockaddr *) addr;
    279   1.1      fvdl 		syscallarg(int *) namelen;
    280  1.12   mycroft 	} */ *uap;
    281   1.1      fvdl 	register_t *retval;
    282   1.1      fvdl {
    283   1.1      fvdl 	struct linux_getpeername_args lga;
    284  1.12   mycroft 	struct compat_43_sys_getpeername_args bga;
    285   1.1      fvdl 	int error;
    286   1.1      fvdl 
    287  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
    288   1.1      fvdl 		return error;
    289   1.1      fvdl 
    290   1.1      fvdl 	SCARG(&bga, fdes) = lga.s;
    291   1.1      fvdl 	SCARG(&bga, asa) = (caddr_t) lga.addr;
    292   1.1      fvdl 	SCARG(&bga, alen) = lga.namelen;
    293   1.1      fvdl 
    294  1.12   mycroft 	return compat_43_sys_getpeername(p, &bga, retval);
    295   1.1      fvdl }
    296   1.1      fvdl 
    297   1.2   mycroft int
    298  1.12   mycroft linux_socketpair(p, uap, retval)
    299   1.1      fvdl 	struct proc *p;
    300   1.1      fvdl 	struct linux_socketpair_args /* {
    301   1.1      fvdl 		syscallarg(int) domain;
    302   1.1      fvdl 		syscallarg(int) type;
    303   1.1      fvdl 		syscallarg(int) protocol;
    304   1.1      fvdl 		syscallarg(int *) rsv;
    305  1.12   mycroft 	} */ *uap;
    306   1.1      fvdl 	register_t *retval;
    307   1.1      fvdl {
    308   1.1      fvdl 	struct linux_socketpair_args lsa;
    309  1.12   mycroft 	struct sys_socketpair_args bsa;
    310   1.1      fvdl 	int error;
    311   1.1      fvdl 
    312  1.12   mycroft 	if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa)))
    313   1.1      fvdl 		return error;
    314   1.1      fvdl 
    315   1.1      fvdl 	SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
    316   1.1      fvdl 	if (SCARG(&bsa, domain) == -1)
    317   1.1      fvdl 		return EINVAL;
    318   1.1      fvdl 	SCARG(&bsa, type) = lsa.type;
    319   1.1      fvdl 	SCARG(&bsa, protocol) = lsa.protocol;
    320   1.1      fvdl 	SCARG(&bsa, rsv) = lsa.rsv;
    321   1.1      fvdl 
    322  1.12   mycroft 	return sys_socketpair(p, &bsa, retval);
    323   1.1      fvdl }
    324   1.1      fvdl 
    325   1.2   mycroft int
    326  1.12   mycroft linux_send(p, uap, retval)
    327   1.1      fvdl 	struct proc *p;
    328   1.1      fvdl 	struct linux_send_args /* {
    329   1.1      fvdl 		syscallarg(int) s;
    330   1.1      fvdl 		syscallarg(void *) msg;
    331   1.1      fvdl 		syscallarg(int) len;
    332   1.1      fvdl 		syscallarg(int) flags;
    333  1.12   mycroft 	} */ *uap;
    334   1.1      fvdl 	register_t *retval;
    335   1.1      fvdl {
    336   1.1      fvdl 	struct linux_send_args lsa;
    337  1.12   mycroft 	struct compat_43_sys_send_args bsa;
    338   1.1      fvdl 	int error;
    339   1.1      fvdl 
    340  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
    341   1.1      fvdl 		return error;
    342   1.1      fvdl 
    343   1.1      fvdl 	SCARG(&bsa, s) = lsa.s;
    344   1.1      fvdl 	SCARG(&bsa, buf) = lsa.msg;
    345   1.1      fvdl 	SCARG(&bsa, len) = lsa.len;
    346   1.1      fvdl 	SCARG(&bsa, flags) = lsa.flags;
    347   1.1      fvdl 
    348  1.12   mycroft 	return compat_43_sys_send(p, &bsa, retval);
    349   1.1      fvdl }
    350   1.1      fvdl 
    351   1.2   mycroft int
    352  1.12   mycroft linux_recv(p, uap, retval)
    353   1.1      fvdl 	struct proc *p;
    354  1.12   mycroft 	struct linux_recv_args /* {
    355  1.12   mycroft 		syscallarg(int) s;
    356  1.12   mycroft 		syscallarg(void *) msg;
    357  1.12   mycroft 		syscallarg(int) len;
    358  1.12   mycroft 		syscallarg(int) flags;
    359  1.12   mycroft 	} */ *uap;
    360   1.1      fvdl 	register_t *retval;
    361   1.1      fvdl {
    362   1.1      fvdl 	struct linux_recv_args lra;
    363  1.12   mycroft 	struct compat_43_sys_recv_args bra;
    364   1.1      fvdl 	int error;
    365   1.1      fvdl 
    366  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
    367   1.1      fvdl 		return error;
    368   1.1      fvdl 
    369   1.1      fvdl 	SCARG(&bra, s) = lra.s;
    370   1.1      fvdl 	SCARG(&bra, buf) = lra.msg;
    371   1.1      fvdl 	SCARG(&bra, len) = lra.len;
    372   1.1      fvdl 	SCARG(&bra, flags) = lra.flags;
    373   1.1      fvdl 
    374  1.12   mycroft 	return compat_43_sys_recv(p, &bra, retval);
    375   1.1      fvdl }
    376   1.1      fvdl 
    377   1.2   mycroft int
    378  1.12   mycroft linux_sendto(p, uap, retval)
    379   1.1      fvdl 	struct proc *p;
    380   1.1      fvdl 	struct linux_sendto_args /* {
    381   1.1      fvdl 		syscallarg(int) s;
    382   1.1      fvdl 		syscallarg(void *) msg;
    383   1.1      fvdl 		syscallarg(int) len;
    384   1.1      fvdl 		syscallarg(int) flags;
    385   1.1      fvdl 		syscallarg(sockaddr *) to;
    386   1.1      fvdl 		syscallarg(int) tolen;
    387  1.12   mycroft 	} */ *uap;
    388   1.1      fvdl 	register_t *retval;
    389   1.1      fvdl {
    390   1.1      fvdl 	struct linux_sendto_args lsa;
    391  1.12   mycroft 	struct sys_sendto_args bsa;
    392   1.1      fvdl 	int error;
    393   1.1      fvdl 
    394  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
    395   1.1      fvdl 		return error;
    396   1.1      fvdl 
    397   1.1      fvdl 	SCARG(&bsa, s) = lsa.s;
    398   1.1      fvdl 	SCARG(&bsa, buf) = lsa.msg;
    399   1.1      fvdl 	SCARG(&bsa, len) = lsa.len;
    400   1.1      fvdl 	SCARG(&bsa, flags) = lsa.flags;
    401   1.1      fvdl 	SCARG(&bsa, to) = (caddr_t) lsa.to;
    402   1.1      fvdl 	SCARG(&bsa, tolen) = lsa.tolen;
    403   1.1      fvdl 
    404  1.12   mycroft 	return sys_sendto(p, &bsa, retval);
    405   1.1      fvdl }
    406   1.1      fvdl 
    407   1.2   mycroft int
    408  1.12   mycroft linux_recvfrom(p, uap, retval)
    409   1.1      fvdl 	struct proc *p;
    410   1.1      fvdl 	struct linux_recvfrom_args /* {
    411   1.1      fvdl 		syscallarg(int) s;
    412   1.1      fvdl 		syscallarg(void *) buf;
    413   1.1      fvdl 		syscallarg(int) len;
    414   1.1      fvdl 		syscallarg(int) flags;
    415   1.1      fvdl 		syscallarg(struct sockaddr *) from;
    416   1.1      fvdl 		syscallarg(int *) fromlen;
    417  1.12   mycroft 	} */ *uap;
    418  1.12   mycroft 	register_t *retval;
    419  1.12   mycroft {
    420   1.1      fvdl 	struct linux_recvfrom_args lra;
    421  1.12   mycroft 	struct compat_43_sys_recvfrom_args bra;
    422   1.1      fvdl 	int error;
    423   1.1      fvdl 
    424  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
    425   1.1      fvdl 		return error;
    426   1.1      fvdl 
    427   1.1      fvdl 	SCARG(&bra, s) = lra.s;
    428   1.1      fvdl 	SCARG(&bra, buf) = lra.buf;
    429   1.1      fvdl 	SCARG(&bra, len) = lra.len;
    430   1.1      fvdl 	SCARG(&bra, flags) = lra.flags;
    431   1.1      fvdl 	SCARG(&bra, from) = (caddr_t) lra.from;
    432   1.1      fvdl 	SCARG(&bra, fromlenaddr) = lra.fromlen;
    433   1.1      fvdl 
    434  1.12   mycroft 	return compat_43_sys_recvfrom(p, &bra, retval);
    435   1.1      fvdl }
    436   1.1      fvdl 
    437   1.2   mycroft int
    438  1.12   mycroft linux_shutdown(p, uap, retval)
    439   1.1      fvdl 	struct proc *p;
    440   1.1      fvdl 	struct linux_shutdown_args /* {
    441   1.1      fvdl 		syscallarg(int) s;
    442   1.1      fvdl 		syscallarg(int) how;
    443  1.12   mycroft 	} */ *uap;
    444   1.1      fvdl 	register_t *retval;
    445   1.1      fvdl {
    446   1.1      fvdl 	struct linux_shutdown_args lsa;
    447  1.12   mycroft 	struct sys_shutdown_args bsa;
    448   1.1      fvdl 	int error;
    449   1.1      fvdl 
    450  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
    451   1.1      fvdl 		return error;
    452   1.1      fvdl 
    453   1.1      fvdl 	SCARG(&bsa, s) = lsa.s;
    454   1.1      fvdl 	SCARG(&bsa, how) = lsa.how;
    455   1.1      fvdl 
    456  1.12   mycroft 	return sys_shutdown(p, &bsa, retval);
    457   1.1      fvdl }
    458   1.1      fvdl 
    459   1.1      fvdl /*
    460   1.1      fvdl  * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
    461   1.1      fvdl  * is different, the rest matches IPPROTO_* on both systems.
    462   1.1      fvdl  */
    463   1.2   mycroft int
    464   1.1      fvdl linux_to_bsd_sopt_level(llevel)
    465   1.1      fvdl 	int llevel;
    466   1.1      fvdl {
    467  1.12   mycroft 
    468   1.1      fvdl 	switch (llevel) {
    469   1.1      fvdl 	case LINUX_SOL_SOCKET:
    470   1.1      fvdl 		return SOL_SOCKET;
    471   1.3   mycroft 	case LINUX_SOL_IP:
    472   1.3   mycroft 		return IPPROTO_IP;
    473   1.3   mycroft 	case LINUX_SOL_TCP:
    474   1.3   mycroft 		return IPPROTO_TCP;
    475   1.3   mycroft 	case LINUX_SOL_UDP:
    476   1.3   mycroft 		return IPPROTO_UDP;
    477   1.1      fvdl 	default:
    478   1.1      fvdl 		return -1;
    479   1.1      fvdl 	}
    480   1.1      fvdl }
    481   1.1      fvdl 
    482   1.1      fvdl /*
    483   1.1      fvdl  * Convert Linux socket level socket option numbers to NetBSD values.
    484   1.1      fvdl  */
    485   1.2   mycroft int
    486   1.1      fvdl linux_to_bsd_so_sockopt(lopt)
    487   1.1      fvdl 	int lopt;
    488   1.1      fvdl {
    489  1.12   mycroft 
    490   1.1      fvdl 	switch (lopt) {
    491   1.1      fvdl 	case LINUX_SO_DEBUG:
    492   1.1      fvdl 		return SO_DEBUG;
    493   1.1      fvdl 	case LINUX_SO_REUSEADDR:
    494   1.1      fvdl 		return SO_REUSEADDR;
    495   1.1      fvdl 	case LINUX_SO_TYPE:
    496   1.1      fvdl 		return SO_TYPE;
    497   1.1      fvdl 	case LINUX_SO_ERROR:
    498   1.1      fvdl 		return SO_ERROR;
    499   1.1      fvdl 	case LINUX_SO_DONTROUTE:
    500   1.1      fvdl 		return SO_DONTROUTE;
    501   1.1      fvdl 	case LINUX_SO_BROADCAST:
    502   1.1      fvdl 		return SO_BROADCAST;
    503   1.1      fvdl 	case LINUX_SO_SNDBUF:
    504   1.1      fvdl 		return SO_SNDBUF;
    505   1.1      fvdl 	case LINUX_SO_RCVBUF:
    506   1.1      fvdl 		return SO_RCVBUF;
    507   1.1      fvdl 	case LINUX_SO_KEEPALIVE:
    508   1.1      fvdl 		return SO_KEEPALIVE;
    509   1.1      fvdl 	case LINUX_SO_OOBINLINE:
    510   1.1      fvdl 		return SO_OOBINLINE;
    511   1.1      fvdl 	case LINUX_SO_LINGER:
    512   1.1      fvdl 		return SO_LINGER;
    513   1.1      fvdl 	case LINUX_SO_PRIORITY:
    514   1.1      fvdl 	case LINUX_SO_NO_CHECK:
    515   1.1      fvdl 	default:
    516   1.1      fvdl 		return -1;
    517   1.1      fvdl 	}
    518   1.1      fvdl }
    519   1.1      fvdl 
    520   1.1      fvdl /*
    521   1.3   mycroft  * Convert Linux IP level socket option number to NetBSD values.
    522   1.3   mycroft  */
    523   1.3   mycroft int
    524   1.3   mycroft linux_to_bsd_ip_sockopt(lopt)
    525   1.3   mycroft 	int lopt;
    526   1.3   mycroft {
    527  1.12   mycroft 
    528   1.3   mycroft 	switch (lopt) {
    529   1.3   mycroft 	case LINUX_IP_TOS:
    530   1.3   mycroft 		return IP_TOS;
    531   1.3   mycroft 	case LINUX_IP_TTL:
    532   1.3   mycroft 		return IP_TTL;
    533   1.3   mycroft 	case LINUX_IP_MULTICAST_TTL:
    534   1.3   mycroft 		return IP_MULTICAST_TTL;
    535   1.3   mycroft 	case LINUX_IP_MULTICAST_LOOP:
    536   1.3   mycroft 		return IP_MULTICAST_LOOP;
    537   1.3   mycroft 	case LINUX_IP_MULTICAST_IF:
    538   1.3   mycroft 		return IP_MULTICAST_IF;
    539   1.3   mycroft 	case LINUX_IP_ADD_MEMBERSHIP:
    540   1.3   mycroft 		return IP_ADD_MEMBERSHIP;
    541   1.3   mycroft 	case LINUX_IP_DROP_MEMBERSHIP:
    542   1.3   mycroft 		return IP_DROP_MEMBERSHIP;
    543   1.3   mycroft 	default:
    544   1.3   mycroft 		return -1;
    545   1.3   mycroft 	}
    546   1.3   mycroft }
    547   1.3   mycroft 
    548   1.3   mycroft /*
    549   1.3   mycroft  * Convert Linux TCP level socket option number to NetBSD values.
    550   1.3   mycroft  */
    551   1.3   mycroft int
    552   1.3   mycroft linux_to_bsd_tcp_sockopt(lopt)
    553   1.3   mycroft 	int lopt;
    554   1.3   mycroft {
    555  1.12   mycroft 
    556   1.3   mycroft 	switch (lopt) {
    557   1.6   mycroft 	case LINUX_TCP_NODELAY:
    558   1.6   mycroft 		return TCP_NODELAY;
    559   1.6   mycroft 	case LINUX_TCP_MAXSEG:
    560   1.6   mycroft 		return TCP_MAXSEG;
    561   1.3   mycroft 	default:
    562   1.6   mycroft 		return -1;
    563   1.3   mycroft 	}
    564   1.3   mycroft }
    565   1.3   mycroft 
    566   1.3   mycroft /*
    567   1.3   mycroft  * Convert Linux UDP level socket option number to NetBSD values.
    568   1.3   mycroft  */
    569   1.3   mycroft int
    570   1.3   mycroft linux_to_bsd_udp_sockopt(lopt)
    571   1.3   mycroft 	int lopt;
    572   1.3   mycroft {
    573  1.12   mycroft 
    574   1.3   mycroft 	switch (lopt) {
    575   1.3   mycroft 	default:
    576   1.6   mycroft 		return -1;
    577   1.3   mycroft 	}
    578   1.3   mycroft }
    579   1.3   mycroft 
    580   1.3   mycroft /*
    581   1.5   mycroft  * Another reasonably straightforward function: setsockopt(2).
    582   1.1      fvdl  * The level and option numbers are converted; the values passed
    583   1.1      fvdl  * are not (yet) converted, the ones currently implemented don't
    584   1.1      fvdl  * need conversion, as they are the same on both systems.
    585   1.1      fvdl  */
    586   1.2   mycroft int
    587  1.12   mycroft linux_setsockopt(p, uap, retval)
    588   1.1      fvdl 	struct proc *p;
    589   1.1      fvdl 	struct linux_setsockopt_args /* {
    590   1.1      fvdl 		syscallarg(int) s;
    591   1.1      fvdl 		syscallarg(int) level;
    592   1.1      fvdl 		syscallarg(int) optname;
    593   1.1      fvdl 		syscallarg(void *) optval;
    594   1.1      fvdl 		syscallarg(int) optlen;
    595  1.12   mycroft 	} */ *uap;
    596   1.1      fvdl 	register_t *retval;
    597   1.1      fvdl {
    598   1.1      fvdl 	struct linux_setsockopt_args lsa;
    599  1.12   mycroft 	struct sys_setsockopt_args bsa;
    600   1.1      fvdl 	int error, name;
    601   1.1      fvdl 
    602  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
    603   1.1      fvdl 		return error;
    604   1.1      fvdl 
    605   1.1      fvdl 	SCARG(&bsa, s) = lsa.s;
    606   1.1      fvdl 	SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
    607   1.6   mycroft 	SCARG(&bsa, val) = lsa.optval;
    608   1.6   mycroft 	SCARG(&bsa, valsize) = lsa.optlen;
    609   1.1      fvdl 
    610   1.1      fvdl 	switch (SCARG(&bsa, level)) {
    611   1.1      fvdl 		case SOL_SOCKET:
    612   1.1      fvdl 			name = linux_to_bsd_so_sockopt(lsa.optname);
    613   1.1      fvdl 			break;
    614   1.1      fvdl 		case IPPROTO_IP:
    615   1.1      fvdl 			name = linux_to_bsd_ip_sockopt(lsa.optname);
    616   1.1      fvdl 			break;
    617   1.3   mycroft 		case IPPROTO_TCP:
    618   1.3   mycroft 			name = linux_to_bsd_tcp_sockopt(lsa.optname);
    619   1.3   mycroft 			break;
    620   1.3   mycroft 		case IPPROTO_UDP:
    621   1.3   mycroft 			name = linux_to_bsd_udp_sockopt(lsa.optname);
    622   1.3   mycroft 			break;
    623   1.1      fvdl 		default:
    624   1.1      fvdl 			return EINVAL;
    625   1.1      fvdl 	}
    626   1.1      fvdl 
    627   1.1      fvdl 	if (name == -1)
    628   1.1      fvdl 		return EINVAL;
    629   1.1      fvdl 	SCARG(&bsa, name) = name;
    630   1.1      fvdl 
    631  1.12   mycroft 	return sys_setsockopt(p, &bsa, retval);
    632   1.1      fvdl }
    633   1.1      fvdl 
    634   1.1      fvdl /*
    635   1.1      fvdl  * getsockopt(2) is very much the same as setsockopt(2) (see above)
    636   1.1      fvdl  */
    637   1.2   mycroft int
    638  1.12   mycroft linux_getsockopt(p, uap, retval)
    639   1.1      fvdl 	struct proc *p;
    640   1.1      fvdl 	struct linux_getsockopt_args /* {
    641   1.1      fvdl 		syscallarg(int) s;
    642   1.1      fvdl 		syscallarg(int) level;
    643   1.1      fvdl 		syscallarg(int) optname;
    644   1.1      fvdl 		syscallarg(void *) optval;
    645   1.1      fvdl 		syscallarg(int) *optlen;
    646  1.12   mycroft 	} */ *uap;
    647   1.1      fvdl 	register_t *retval;
    648   1.1      fvdl {
    649   1.1      fvdl 	struct linux_getsockopt_args lga;
    650  1.12   mycroft 	struct sys_getsockopt_args bga;
    651   1.1      fvdl 	int error, name;
    652   1.1      fvdl 
    653  1.12   mycroft 	if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
    654   1.1      fvdl 		return error;
    655   1.1      fvdl 
    656   1.1      fvdl 	SCARG(&bga, s) = lga.s;
    657   1.1      fvdl 	SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
    658   1.6   mycroft 	SCARG(&bga, val) = lga.optval;
    659   1.6   mycroft 	SCARG(&bga, avalsize) = lga.optlen;
    660   1.1      fvdl 
    661   1.1      fvdl 	switch (SCARG(&bga, level)) {
    662   1.1      fvdl 		case SOL_SOCKET:
    663   1.1      fvdl 			name = linux_to_bsd_so_sockopt(lga.optname);
    664   1.1      fvdl 			break;
    665   1.1      fvdl 		case IPPROTO_IP:
    666   1.1      fvdl 			name = linux_to_bsd_ip_sockopt(lga.optname);
    667   1.3   mycroft 			break;
    668   1.3   mycroft 		case IPPROTO_TCP:
    669   1.4   mycroft 			name = linux_to_bsd_tcp_sockopt(lga.optname);
    670   1.3   mycroft 			break;
    671   1.3   mycroft 		case IPPROTO_UDP:
    672   1.4   mycroft 			name = linux_to_bsd_udp_sockopt(lga.optname);
    673   1.1      fvdl 			break;
    674   1.1      fvdl 		default:
    675   1.1      fvdl 			return EINVAL;
    676   1.1      fvdl 	}
    677   1.1      fvdl 
    678   1.1      fvdl 	if (name == -1)
    679   1.1      fvdl 		return EINVAL;
    680   1.5   mycroft 	SCARG(&bga, name) = name;
    681   1.1      fvdl 
    682  1.12   mycroft 	return sys_getsockopt(p, &bga, retval);
    683   1.1      fvdl }
    684   1.1      fvdl 
    685   1.1      fvdl /*
    686   1.1      fvdl  * Entry point to all Linux socket calls. Just check which call to
    687   1.1      fvdl  * make and take appropriate action.
    688   1.1      fvdl  */
    689   1.1      fvdl int
    690  1.12   mycroft linux_sys_socketcall(p, v, retval)
    691   1.1      fvdl 	struct proc *p;
    692  1.11   thorpej 	void *v;
    693  1.11   thorpej 	register_t *retval;
    694  1.11   thorpej {
    695  1.12   mycroft 	struct linux_sys_socketcall_args /* {
    696   1.1      fvdl 		syscallarg(int) what;
    697   1.1      fvdl 		syscallarg(void *) args;
    698  1.11   thorpej 	} */ *uap = v;
    699  1.11   thorpej 
    700   1.1      fvdl 	switch (SCARG(uap, what)) {
    701   1.1      fvdl 	case LINUX_SYS_socket:
    702   1.1      fvdl 		return linux_socket(p, SCARG(uap, args), retval);
    703   1.1      fvdl 	case LINUX_SYS_bind:
    704   1.1      fvdl 		return linux_bind(p, SCARG(uap, args), retval);
    705   1.1      fvdl 	case LINUX_SYS_connect:
    706   1.1      fvdl 		return linux_connect(p, SCARG(uap, args), retval);
    707   1.1      fvdl 	case LINUX_SYS_listen:
    708   1.1      fvdl 		return linux_listen(p, SCARG(uap, args), retval);
    709   1.1      fvdl 	case LINUX_SYS_accept:
    710   1.1      fvdl 		return linux_accept(p, SCARG(uap, args), retval);
    711   1.1      fvdl 	case LINUX_SYS_getsockname:
    712   1.1      fvdl 		return linux_getsockname(p, SCARG(uap, args), retval);
    713   1.1      fvdl 	case LINUX_SYS_getpeername:
    714   1.1      fvdl 		return linux_getpeername(p, SCARG(uap, args), retval);
    715   1.1      fvdl 	case LINUX_SYS_socketpair:
    716   1.1      fvdl 		return linux_socketpair(p, SCARG(uap, args), retval);
    717   1.1      fvdl 	case LINUX_SYS_send:
    718   1.1      fvdl 		return linux_send(p, SCARG(uap, args), retval);
    719   1.1      fvdl 	case LINUX_SYS_recv:
    720   1.1      fvdl 		return linux_recv(p, SCARG(uap, args), retval);
    721   1.1      fvdl 	case LINUX_SYS_sendto:
    722   1.1      fvdl 		return linux_sendto(p, SCARG(uap, args), retval);
    723   1.1      fvdl 	case LINUX_SYS_recvfrom:
    724   1.1      fvdl 		return linux_recvfrom(p, SCARG(uap, args), retval);
    725   1.1      fvdl 	case LINUX_SYS_shutdown:
    726   1.1      fvdl 		return linux_shutdown(p, SCARG(uap, args), retval);
    727   1.1      fvdl 	case LINUX_SYS_setsockopt:
    728   1.1      fvdl 		return linux_setsockopt(p, SCARG(uap, args), retval);
    729   1.1      fvdl 	case LINUX_SYS_getsockopt:
    730   1.1      fvdl 		return linux_getsockopt(p, SCARG(uap, args), retval);
    731   1.1      fvdl 	default:
    732   1.1      fvdl 		return ENOSYS;
    733   1.1      fvdl 	}
    734  1.13   mycroft }
    735  1.13   mycroft 
    736  1.13   mycroft int
    737  1.13   mycroft linux_ioctl_socket(p, uap, retval)
    738  1.13   mycroft 	register struct proc *p;
    739  1.13   mycroft 	register struct linux_sys_ioctl_args /* {
    740  1.13   mycroft 		syscallarg(int) fd;
    741  1.13   mycroft 		syscallarg(u_long) com;
    742  1.13   mycroft 		syscallarg(caddr_t) data;
    743  1.13   mycroft 	} */ *uap;
    744  1.13   mycroft 	register_t *retval;
    745  1.13   mycroft {
    746  1.13   mycroft 	u_long com;
    747  1.13   mycroft 	struct sys_ioctl_args ia;
    748  1.13   mycroft 
    749  1.13   mycroft 	com = SCARG(uap, com);
    750  1.13   mycroft 	retval[0] = 0;
    751  1.13   mycroft 
    752  1.13   mycroft 	switch (com) {
    753  1.13   mycroft 	case LINUX_SIOCGIFCONF:
    754  1.13   mycroft 		SCARG(&ia, com) = OSIOCGIFCONF;
    755  1.13   mycroft 		break;
    756  1.13   mycroft 	case LINUX_SIOCGIFFLAGS:
    757  1.13   mycroft 		SCARG(&ia, com) = SIOCGIFFLAGS;
    758  1.13   mycroft 		break;
    759  1.13   mycroft 	case LINUX_SIOCGIFADDR:
    760  1.13   mycroft 		SCARG(&ia, com) = OSIOCGIFADDR;
    761  1.13   mycroft 		break;
    762  1.13   mycroft 	case LINUX_SIOCGIFDSTADDR:
    763  1.13   mycroft 		SCARG(&ia, com) = OSIOCGIFDSTADDR;
    764  1.13   mycroft 		break;
    765  1.13   mycroft 	case LINUX_SIOCGIFBRDADDR:
    766  1.13   mycroft 		SCARG(&ia, com) = OSIOCGIFBRDADDR;
    767  1.13   mycroft 		break;
    768  1.13   mycroft 	case LINUX_SIOCGIFNETMASK:
    769  1.13   mycroft 		SCARG(&ia, com) = OSIOCGIFNETMASK;
    770  1.13   mycroft 		break;
    771  1.13   mycroft 	case LINUX_SIOCADDMULTI:
    772  1.13   mycroft 		SCARG(&ia, com) = SIOCADDMULTI;
    773  1.13   mycroft 		break;
    774  1.13   mycroft 	case LINUX_SIOCDELMULTI:
    775  1.13   mycroft 		SCARG(&ia, com) = SIOCDELMULTI;
    776  1.13   mycroft 		break;
    777  1.13   mycroft 	default:
    778  1.13   mycroft 		return EINVAL;
    779  1.13   mycroft 	}
    780  1.13   mycroft 
    781  1.13   mycroft 	SCARG(&ia, fd) = SCARG(uap, fd);
    782  1.13   mycroft 	SCARG(&ia, data) = SCARG(uap, data);
    783  1.13   mycroft 	return sys_ioctl(p, &ia, retval);
    784   1.1      fvdl }
    785