1c21dee17SSøren Schmidt /*- 2c21dee17SSøren Schmidt * Copyright (c) 1995 S�ren Schmidt 3c21dee17SSøren Schmidt * All rights reserved. 4c21dee17SSøren Schmidt * 5c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without 6c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions 7c21dee17SSøren Schmidt * are met: 8c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 9c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer 10c21dee17SSøren Schmidt * in this position and unchanged. 11c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 12c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 13c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution. 14c21dee17SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 15c21dee17SSøren Schmidt * derived from this software withough specific prior written permission 16c21dee17SSøren Schmidt * 17c21dee17SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18c21dee17SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19c21dee17SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20c21dee17SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21c21dee17SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22c21dee17SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23c21dee17SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24c21dee17SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25c21dee17SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26c21dee17SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27c21dee17SSøren Schmidt * 28c3aac50fSPeter Wemm * $FreeBSD$ 29c21dee17SSøren Schmidt */ 30c21dee17SSøren Schmidt 311f3dad5aSBruce Evans /* XXX we use functions that might not exist. */ 325591b823SEivind Eklund #include "opt_compat.h" 335591b823SEivind Eklund 345591b823SEivind Eklund #ifndef COMPAT_43 355591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 365591b823SEivind Eklund #endif 371f3dad5aSBruce Evans 38c21dee17SSøren Schmidt #include <sys/param.h> 39f2477ae1SMike Smith #include <sys/proc.h> 40c21dee17SSøren Schmidt #include <sys/systm.h> 411f3dad5aSBruce Evans #include <sys/sysproto.h> 42dad3b88aSMike Smith #include <sys/fcntl.h> 43c21dee17SSøren Schmidt #include <sys/socket.h> 4408637435SBruce Evans #include <sys/uio.h> 451f3dad5aSBruce Evans 46c21dee17SSøren Schmidt #include <netinet/in.h> 47f2477ae1SMike Smith #include <netinet/in_systm.h> 48f2477ae1SMike Smith #include <netinet/ip.h> 49c21dee17SSøren Schmidt 50ac951e62SMarcel Moolenaar #include <machine/../linux/linux.h> 51ebea8660SMarcel Moolenaar #include <machine/../linux/linux_proto.h> 5240dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 53ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 54c21dee17SSøren Schmidt 555231fb20SDavid E. O'Brien #ifndef __alpha__ 56c21dee17SSøren Schmidt static int 57c21dee17SSøren Schmidt linux_to_bsd_domain(int domain) 58c21dee17SSøren Schmidt { 593f3a4815SMarcel Moolenaar 60c21dee17SSøren Schmidt switch (domain) { 61c21dee17SSøren Schmidt case LINUX_AF_UNSPEC: 623f3a4815SMarcel Moolenaar return (AF_UNSPEC); 63c21dee17SSøren Schmidt case LINUX_AF_UNIX: 643f3a4815SMarcel Moolenaar return (AF_LOCAL); 65c21dee17SSøren Schmidt case LINUX_AF_INET: 663f3a4815SMarcel Moolenaar return (AF_INET); 67c21dee17SSøren Schmidt case LINUX_AF_AX25: 683f3a4815SMarcel Moolenaar return (AF_CCITT); 69c21dee17SSøren Schmidt case LINUX_AF_IPX: 703f3a4815SMarcel Moolenaar return (AF_IPX); 71c21dee17SSøren Schmidt case LINUX_AF_APPLETALK: 723f3a4815SMarcel Moolenaar return (AF_APPLETALK); 73c21dee17SSøren Schmidt } 743f3a4815SMarcel Moolenaar return (-1); 75c21dee17SSøren Schmidt } 76c21dee17SSøren Schmidt 77c21dee17SSøren Schmidt static int 78c21dee17SSøren Schmidt linux_to_bsd_sockopt_level(int level) 79c21dee17SSøren Schmidt { 803f3a4815SMarcel Moolenaar 81c21dee17SSøren Schmidt switch (level) { 82c21dee17SSøren Schmidt case LINUX_SOL_SOCKET: 833f3a4815SMarcel Moolenaar return (SOL_SOCKET); 84c21dee17SSøren Schmidt } 853f3a4815SMarcel Moolenaar return (level); 86c21dee17SSøren Schmidt } 87c21dee17SSøren Schmidt 883f3a4815SMarcel Moolenaar static int 893f3a4815SMarcel Moolenaar linux_to_bsd_ip_sockopt(int opt) 90c21dee17SSøren Schmidt { 913f3a4815SMarcel Moolenaar 92c21dee17SSøren Schmidt switch (opt) { 93c21dee17SSøren Schmidt case LINUX_IP_TOS: 943f3a4815SMarcel Moolenaar return (IP_TOS); 95c21dee17SSøren Schmidt case LINUX_IP_TTL: 963f3a4815SMarcel Moolenaar return (IP_TTL); 9766ff6a3cSBill Fenner case LINUX_IP_OPTIONS: 983f3a4815SMarcel Moolenaar return (IP_OPTIONS); 9966ff6a3cSBill Fenner case LINUX_IP_MULTICAST_IF: 1003f3a4815SMarcel Moolenaar return (IP_MULTICAST_IF); 10166ff6a3cSBill Fenner case LINUX_IP_MULTICAST_TTL: 1023f3a4815SMarcel Moolenaar return (IP_MULTICAST_TTL); 10366ff6a3cSBill Fenner case LINUX_IP_MULTICAST_LOOP: 1043f3a4815SMarcel Moolenaar return (IP_MULTICAST_LOOP); 10566ff6a3cSBill Fenner case LINUX_IP_ADD_MEMBERSHIP: 1063f3a4815SMarcel Moolenaar return (IP_ADD_MEMBERSHIP); 10766ff6a3cSBill Fenner case LINUX_IP_DROP_MEMBERSHIP: 1083f3a4815SMarcel Moolenaar return (IP_DROP_MEMBERSHIP); 10966ff6a3cSBill Fenner case LINUX_IP_HDRINCL: 1103f3a4815SMarcel Moolenaar return (IP_HDRINCL); 111c21dee17SSøren Schmidt } 1123f3a4815SMarcel Moolenaar return (-1); 113c21dee17SSøren Schmidt } 114c21dee17SSøren Schmidt 115c21dee17SSøren Schmidt static int 116c21dee17SSøren Schmidt linux_to_bsd_so_sockopt(int opt) 117c21dee17SSøren Schmidt { 1183f3a4815SMarcel Moolenaar 119c21dee17SSøren Schmidt switch (opt) { 120c21dee17SSøren Schmidt case LINUX_SO_DEBUG: 1213f3a4815SMarcel Moolenaar return (SO_DEBUG); 122c21dee17SSøren Schmidt case LINUX_SO_REUSEADDR: 1233f3a4815SMarcel Moolenaar return (SO_REUSEADDR); 124c21dee17SSøren Schmidt case LINUX_SO_TYPE: 1253f3a4815SMarcel Moolenaar return (SO_TYPE); 126c21dee17SSøren Schmidt case LINUX_SO_ERROR: 1273f3a4815SMarcel Moolenaar return (SO_ERROR); 128c21dee17SSøren Schmidt case LINUX_SO_DONTROUTE: 1293f3a4815SMarcel Moolenaar return (SO_DONTROUTE); 130c21dee17SSøren Schmidt case LINUX_SO_BROADCAST: 1313f3a4815SMarcel Moolenaar return (SO_BROADCAST); 132c21dee17SSøren Schmidt case LINUX_SO_SNDBUF: 1333f3a4815SMarcel Moolenaar return (SO_SNDBUF); 134c21dee17SSøren Schmidt case LINUX_SO_RCVBUF: 1353f3a4815SMarcel Moolenaar return (SO_RCVBUF); 136c21dee17SSøren Schmidt case LINUX_SO_KEEPALIVE: 1373f3a4815SMarcel Moolenaar return (SO_KEEPALIVE); 138c21dee17SSøren Schmidt case LINUX_SO_OOBINLINE: 1393f3a4815SMarcel Moolenaar return (SO_OOBINLINE); 140c21dee17SSøren Schmidt case LINUX_SO_LINGER: 1413f3a4815SMarcel Moolenaar return (SO_LINGER); 142c21dee17SSøren Schmidt } 1433f3a4815SMarcel Moolenaar return (-1); 144c21dee17SSøren Schmidt } 145c21dee17SSøren Schmidt 14640dbba57SAssar Westerlund static int 14740dbba57SAssar Westerlund linux_to_bsd_msg_flags(int flags) 14840dbba57SAssar Westerlund { 14940dbba57SAssar Westerlund int ret_flags = 0; 15040dbba57SAssar Westerlund 15140dbba57SAssar Westerlund if (flags & LINUX_MSG_OOB) 15240dbba57SAssar Westerlund ret_flags |= MSG_OOB; 15340dbba57SAssar Westerlund if (flags & LINUX_MSG_PEEK) 15440dbba57SAssar Westerlund ret_flags |= MSG_PEEK; 15540dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTROUTE) 15640dbba57SAssar Westerlund ret_flags |= MSG_DONTROUTE; 15740dbba57SAssar Westerlund if (flags & LINUX_MSG_CTRUNC) 15840dbba57SAssar Westerlund ret_flags |= MSG_CTRUNC; 15940dbba57SAssar Westerlund if (flags & LINUX_MSG_TRUNC) 16040dbba57SAssar Westerlund ret_flags |= MSG_TRUNC; 16140dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTWAIT) 16240dbba57SAssar Westerlund ret_flags |= MSG_DONTWAIT; 16340dbba57SAssar Westerlund if (flags & LINUX_MSG_EOR) 16440dbba57SAssar Westerlund ret_flags |= MSG_EOR; 16540dbba57SAssar Westerlund if (flags & LINUX_MSG_WAITALL) 16640dbba57SAssar Westerlund ret_flags |= MSG_WAITALL; 16740dbba57SAssar Westerlund #if 0 /* not handled */ 16840dbba57SAssar Westerlund if (flags & LINUX_MSG_PROXY) 16940dbba57SAssar Westerlund ; 17040dbba57SAssar Westerlund if (flags & LINUX_MSG_FIN) 17140dbba57SAssar Westerlund ; 17240dbba57SAssar Westerlund if (flags & LINUX_MSG_SYN) 17340dbba57SAssar Westerlund ; 17440dbba57SAssar Westerlund if (flags & LINUX_MSG_CONFIRM) 17540dbba57SAssar Westerlund ; 17640dbba57SAssar Westerlund if (flags & LINUX_MSG_RST) 17740dbba57SAssar Westerlund ; 17840dbba57SAssar Westerlund if (flags & LINUX_MSG_ERRQUEUE) 17940dbba57SAssar Westerlund ; 18040dbba57SAssar Westerlund if (flags & LINUX_MSG_NOSIGNAL) 18140dbba57SAssar Westerlund ; 18240dbba57SAssar Westerlund #endif 18340dbba57SAssar Westerlund return ret_flags; 18440dbba57SAssar Westerlund } 18540dbba57SAssar Westerlund 1863f3a4815SMarcel Moolenaar /* Return 0 if IP_HDRINCL is set for the given socket. */ 187f2477ae1SMike Smith static int 188f2477ae1SMike Smith linux_check_hdrincl(struct proc *p, int s) 189f2477ae1SMike Smith { 190f2477ae1SMike Smith struct getsockopt_args /* { 191f2477ae1SMike Smith int s; 192f2477ae1SMike Smith int level; 193f2477ae1SMike Smith int name; 194f2477ae1SMike Smith caddr_t val; 195f2477ae1SMike Smith int *avalsize; 196f2477ae1SMike Smith } */ bsd_args; 197f2477ae1SMike Smith int error; 198f2477ae1SMike Smith caddr_t sg, val, valsize; 199f2477ae1SMike Smith int size_val = sizeof val; 200f2477ae1SMike Smith int optval; 201f2477ae1SMike Smith 202f2477ae1SMike Smith sg = stackgap_init(); 203f2477ae1SMike Smith val = stackgap_alloc(&sg, sizeof(int)); 204f2477ae1SMike Smith valsize = stackgap_alloc(&sg, sizeof(int)); 205f2477ae1SMike Smith 206f2477ae1SMike Smith if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 2073f3a4815SMarcel Moolenaar return (error); 2083f3a4815SMarcel Moolenaar 209f2477ae1SMike Smith bsd_args.s = s; 210f2477ae1SMike Smith bsd_args.level = IPPROTO_IP; 211f2477ae1SMike Smith bsd_args.name = IP_HDRINCL; 212f2477ae1SMike Smith bsd_args.val = val; 213f2477ae1SMike Smith bsd_args.avalsize = (int *)valsize; 214f2477ae1SMike Smith if ((error = getsockopt(p, &bsd_args))) 2153f3a4815SMarcel Moolenaar return (error); 2163f3a4815SMarcel Moolenaar 217f2477ae1SMike Smith if ((error = copyin(val, &optval, sizeof(optval)))) 2183f3a4815SMarcel Moolenaar return (error); 2193f3a4815SMarcel Moolenaar 2203f3a4815SMarcel Moolenaar return (optval == 0); 221f2477ae1SMike Smith } 222f2477ae1SMike Smith 223f2477ae1SMike Smith /* 224f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 225f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 226f2477ae1SMike Smith */ 227f2477ae1SMike Smith static int 228f2477ae1SMike Smith linux_sendto_hdrincl(struct proc *p, struct sendto_args *bsd_args) 229f2477ae1SMike Smith { 230f2477ae1SMike Smith /* 231f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 232f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 233f2477ae1SMike Smith * It should include all the fields we modify (ip_len and ip_off) 234f2477ae1SMike Smith * and be as small as possible to minimize copying overhead. 235f2477ae1SMike Smith */ 236f2477ae1SMike Smith #define linux_ip_copysize 8 237f2477ae1SMike Smith 238f2477ae1SMike Smith caddr_t sg; 239f2477ae1SMike Smith struct ip *packet; 240f2477ae1SMike Smith struct msghdr *msg; 241f2477ae1SMike Smith struct iovec *iov; 242f2477ae1SMike Smith 243f2477ae1SMike Smith int error; 244f2477ae1SMike Smith struct sendmsg_args /* { 245f2477ae1SMike Smith int s; 246f2477ae1SMike Smith caddr_t msg; 247f2477ae1SMike Smith int flags; 248f2477ae1SMike Smith } */ sendmsg_args; 249f2477ae1SMike Smith 250f2477ae1SMike Smith /* Check the packet isn't too small before we mess with it */ 251f2477ae1SMike Smith if (bsd_args->len < linux_ip_copysize) 2523f3a4815SMarcel Moolenaar return (EINVAL); 253f2477ae1SMike Smith 254f2477ae1SMike Smith /* 255f2477ae1SMike Smith * Tweaking the user buffer in place would be bad manners. 256f2477ae1SMike Smith * We create a corrected IP header with just the needed length, 257f2477ae1SMike Smith * then use an iovec to glue it to the rest of the user packet 258f2477ae1SMike Smith * when calling sendmsg(). 259f2477ae1SMike Smith */ 260f2477ae1SMike Smith sg = stackgap_init(); 261f2477ae1SMike Smith packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize); 262f2477ae1SMike Smith msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg)); 263f2477ae1SMike Smith iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2); 264f2477ae1SMike Smith 265f2477ae1SMike Smith /* Make a copy of the beginning of the packet to be sent */ 2663f3a4815SMarcel Moolenaar if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) 2673f3a4815SMarcel Moolenaar return (error); 268f2477ae1SMike Smith 269f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 270f2477ae1SMike Smith packet->ip_len = bsd_args->len; 271f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 272f2477ae1SMike Smith 273f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 274f2477ae1SMike Smith msg->msg_name = bsd_args->to; 275f2477ae1SMike Smith msg->msg_namelen = bsd_args->tolen; 276f2477ae1SMike Smith msg->msg_iov = iov; 277f2477ae1SMike Smith msg->msg_iovlen = 2; 278f2477ae1SMike Smith msg->msg_control = NULL; 279f2477ae1SMike Smith msg->msg_controllen = 0; 280f2477ae1SMike Smith msg->msg_flags = 0; 281f2477ae1SMike Smith iov[0].iov_base = (char *)packet; 282f2477ae1SMike Smith iov[0].iov_len = linux_ip_copysize; 283f2477ae1SMike Smith iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; 284f2477ae1SMike Smith iov[1].iov_len = bsd_args->len - linux_ip_copysize; 285f2477ae1SMike Smith 286f2477ae1SMike Smith sendmsg_args.s = bsd_args->s; 287f2477ae1SMike Smith sendmsg_args.msg = (caddr_t)msg; 288f2477ae1SMike Smith sendmsg_args.flags = bsd_args->flags; 2893f3a4815SMarcel Moolenaar return (sendmsg(p, &sendmsg_args)); 290f2477ae1SMike Smith } 291f2477ae1SMike Smith 292c21dee17SSøren Schmidt struct linux_socket_args { 293c21dee17SSøren Schmidt int domain; 294c21dee17SSøren Schmidt int type; 295c21dee17SSøren Schmidt int protocol; 296c21dee17SSøren Schmidt }; 297c21dee17SSøren Schmidt 298c21dee17SSøren Schmidt static int 299cb226aaaSPoul-Henning Kamp linux_socket(struct proc *p, struct linux_socket_args *args) 300c21dee17SSøren Schmidt { 301c21dee17SSøren Schmidt struct linux_socket_args linux_args; 302ef04503dSPeter Wemm struct socket_args /* { 303c21dee17SSøren Schmidt int domain; 304c21dee17SSøren Schmidt int type; 305c21dee17SSøren Schmidt int protocol; 306ef04503dSPeter Wemm } */ bsd_args; 307c21dee17SSøren Schmidt int error; 308f2477ae1SMike Smith int retval_socket; 309c21dee17SSøren Schmidt 3103f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 3113f3a4815SMarcel Moolenaar return (error); 3123f3a4815SMarcel Moolenaar 313c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 314c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 315c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 316c21dee17SSøren Schmidt if (bsd_args.domain == -1) 3173f3a4815SMarcel Moolenaar return (EINVAL); 318f2477ae1SMike Smith 319f2477ae1SMike Smith retval_socket = socket(p, &bsd_args); 320f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 321f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 322f2477ae1SMike Smith && bsd_args.domain == AF_INET 323f2477ae1SMike Smith && retval_socket >= 0) { 324f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 325f2477ae1SMike Smith struct setsockopt_args /* { 326f2477ae1SMike Smith int s; 327f2477ae1SMike Smith int level; 328f2477ae1SMike Smith int name; 329f2477ae1SMike Smith caddr_t val; 330f2477ae1SMike Smith int valsize; 331f2477ae1SMike Smith } */ bsd_setsockopt_args; 332f2477ae1SMike Smith caddr_t sg; 333f2477ae1SMike Smith int *hdrincl; 334f2477ae1SMike Smith 335f2477ae1SMike Smith sg = stackgap_init(); 336f2477ae1SMike Smith hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 337f2477ae1SMike Smith *hdrincl = 1; 338f2477ae1SMike Smith bsd_setsockopt_args.s = p->p_retval[0]; 339f2477ae1SMike Smith bsd_setsockopt_args.level = IPPROTO_IP; 340f2477ae1SMike Smith bsd_setsockopt_args.name = IP_HDRINCL; 341f2477ae1SMike Smith bsd_setsockopt_args.val = (caddr_t)hdrincl; 342f2477ae1SMike Smith bsd_setsockopt_args.valsize = sizeof(*hdrincl); 343f2477ae1SMike Smith /* We ignore any error returned by setsockopt() */ 344f2477ae1SMike Smith setsockopt(p, &bsd_setsockopt_args); 345f2477ae1SMike Smith /* Copy back the return value from socket() */ 346f2477ae1SMike Smith p->p_retval[0] = bsd_setsockopt_args.s; 347f2477ae1SMike Smith } 3483f3a4815SMarcel Moolenaar 3493f3a4815SMarcel Moolenaar return (retval_socket); 350c21dee17SSøren Schmidt } 351c21dee17SSøren Schmidt 352c21dee17SSøren Schmidt struct linux_bind_args { 353c21dee17SSøren Schmidt int s; 354c21dee17SSøren Schmidt struct sockaddr *name; 355c21dee17SSøren Schmidt int namelen; 356c21dee17SSøren Schmidt }; 357c21dee17SSøren Schmidt 358c21dee17SSøren Schmidt static int 359cb226aaaSPoul-Henning Kamp linux_bind(struct proc *p, struct linux_bind_args *args) 360c21dee17SSøren Schmidt { 361c21dee17SSøren Schmidt struct linux_bind_args linux_args; 362ef04503dSPeter Wemm struct bind_args /* { 363c21dee17SSøren Schmidt int s; 364c21dee17SSøren Schmidt caddr_t name; 365c21dee17SSøren Schmidt int namelen; 366ef04503dSPeter Wemm } */ bsd_args; 367c21dee17SSøren Schmidt int error; 368c21dee17SSøren Schmidt 3693f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 3703f3a4815SMarcel Moolenaar return (error); 3713f3a4815SMarcel Moolenaar 372c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 373c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.name; 374c21dee17SSøren Schmidt bsd_args.namelen = linux_args.namelen; 3753f3a4815SMarcel Moolenaar return (bind(p, &bsd_args)); 376c21dee17SSøren Schmidt } 377c21dee17SSøren Schmidt 378c21dee17SSøren Schmidt struct linux_connect_args { 379c21dee17SSøren Schmidt int s; 380c21dee17SSøren Schmidt struct sockaddr * name; 381c21dee17SSøren Schmidt int namelen; 382c21dee17SSøren Schmidt }; 383930a65feSAndrew Gallatin int linux_connect(struct proc *, struct linux_connect_args *); 384930a65feSAndrew Gallatin #endif /* !__alpha__*/ 385c21dee17SSøren Schmidt 386930a65feSAndrew Gallatin int 387cb226aaaSPoul-Henning Kamp linux_connect(struct proc *p, struct linux_connect_args *args) 388c21dee17SSøren Schmidt { 389c21dee17SSøren Schmidt struct linux_connect_args linux_args; 390ef04503dSPeter Wemm struct connect_args /* { 391c21dee17SSøren Schmidt int s; 392c21dee17SSøren Schmidt caddr_t name; 393c21dee17SSøren Schmidt int namelen; 394ef04503dSPeter Wemm } */ bsd_args; 395c21dee17SSøren Schmidt int error; 396c21dee17SSøren Schmidt 397930a65feSAndrew Gallatin #ifdef __alpha__ 398930a65feSAndrew Gallatin bcopy(args, &linux_args, sizeof(linux_args)); 399930a65feSAndrew Gallatin #else 4003f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 4013f3a4815SMarcel Moolenaar return (error); 402930a65feSAndrew Gallatin #endif /* __alpha__ */ 4033f3a4815SMarcel Moolenaar 404c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 405c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.name; 406c21dee17SSøren Schmidt bsd_args.namelen = linux_args.namelen; 407dad3b88aSMike Smith error = connect(p, &bsd_args); 408dad3b88aSMike Smith if (error == EISCONN) { 409dad3b88aSMike Smith /* 410dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 411dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 412dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 413dad3b88aSMike Smith */ 414dad3b88aSMike Smith struct fcntl_args /* { 415dad3b88aSMike Smith int fd; 416dad3b88aSMike Smith int cmd; 417dad3b88aSMike Smith int arg; 418dad3b88aSMike Smith } */ bsd_fcntl_args; 419dad3b88aSMike Smith struct getsockopt_args /* { 420dad3b88aSMike Smith int s; 421dad3b88aSMike Smith int level; 422dad3b88aSMike Smith int name; 423dad3b88aSMike Smith caddr_t val; 424dad3b88aSMike Smith int *avalsize; 425dad3b88aSMike Smith } */ bsd_getsockopt_args; 426dad3b88aSMike Smith void *status, *statusl; 427dad3b88aSMike Smith int stat, statl = sizeof stat; 428dad3b88aSMike Smith caddr_t sg; 429dad3b88aSMike Smith 430dad3b88aSMike Smith /* Check for non-blocking */ 431dad3b88aSMike Smith bsd_fcntl_args.fd = linux_args.s; 432dad3b88aSMike Smith bsd_fcntl_args.cmd = F_GETFL; 433dad3b88aSMike Smith bsd_fcntl_args.arg = 0; 434dad3b88aSMike Smith error = fcntl(p, &bsd_fcntl_args); 435dad3b88aSMike Smith if (error == 0 && (p->p_retval[0] & O_NONBLOCK)) { 436dad3b88aSMike Smith sg = stackgap_init(); 437dad3b88aSMike Smith status = stackgap_alloc(&sg, sizeof stat); 438dad3b88aSMike Smith statusl = stackgap_alloc(&sg, sizeof statusl); 439dad3b88aSMike Smith 440dad3b88aSMike Smith if ((error = copyout(&statl, statusl, sizeof statl))) 4413f3a4815SMarcel Moolenaar return (error); 442dad3b88aSMike Smith 443dad3b88aSMike Smith bsd_getsockopt_args.s = linux_args.s; 444dad3b88aSMike Smith bsd_getsockopt_args.level = SOL_SOCKET; 445dad3b88aSMike Smith bsd_getsockopt_args.name = SO_ERROR; 446dad3b88aSMike Smith bsd_getsockopt_args.val = status; 447dad3b88aSMike Smith bsd_getsockopt_args.avalsize = statusl; 448dad3b88aSMike Smith 449dad3b88aSMike Smith error = getsockopt(p, &bsd_getsockopt_args); 450dad3b88aSMike Smith if (error) 4513f3a4815SMarcel Moolenaar return (error); 4523f3a4815SMarcel Moolenaar 453dad3b88aSMike Smith if ((error = copyin(status, &stat, sizeof stat))) 4543f3a4815SMarcel Moolenaar return (error); 4553f3a4815SMarcel Moolenaar 456dad3b88aSMike Smith p->p_retval[0] = stat; 4573f3a4815SMarcel Moolenaar return (0); 458dad3b88aSMike Smith } 459dad3b88aSMike Smith } 4603f3a4815SMarcel Moolenaar 4613f3a4815SMarcel Moolenaar return (error); 462c21dee17SSøren Schmidt } 463c21dee17SSøren Schmidt 464930a65feSAndrew Gallatin #ifndef __alpha__ 465930a65feSAndrew Gallatin 466c21dee17SSøren Schmidt struct linux_listen_args { 467c21dee17SSøren Schmidt int s; 468c21dee17SSøren Schmidt int backlog; 469c21dee17SSøren Schmidt }; 470c21dee17SSøren Schmidt 471c21dee17SSøren Schmidt static int 472cb226aaaSPoul-Henning Kamp linux_listen(struct proc *p, struct linux_listen_args *args) 473c21dee17SSøren Schmidt { 474c21dee17SSøren Schmidt struct linux_listen_args linux_args; 475ef04503dSPeter Wemm struct listen_args /* { 476c21dee17SSøren Schmidt int s; 477c21dee17SSøren Schmidt int backlog; 478ef04503dSPeter Wemm } */ bsd_args; 479c21dee17SSøren Schmidt int error; 480c21dee17SSøren Schmidt 4813f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 4823f3a4815SMarcel Moolenaar return (error); 4833f3a4815SMarcel Moolenaar 484c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 485c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 4863f3a4815SMarcel Moolenaar return (listen(p, &bsd_args)); 487c21dee17SSøren Schmidt } 488c21dee17SSøren Schmidt 489c21dee17SSøren Schmidt struct linux_accept_args { 490c21dee17SSøren Schmidt int s; 491c21dee17SSøren Schmidt struct sockaddr *addr; 492c21dee17SSøren Schmidt int *namelen; 493c21dee17SSøren Schmidt }; 494c21dee17SSøren Schmidt 495c21dee17SSøren Schmidt static int 496cb226aaaSPoul-Henning Kamp linux_accept(struct proc *p, struct linux_accept_args *args) 497c21dee17SSøren Schmidt { 498c21dee17SSøren Schmidt struct linux_accept_args linux_args; 499ef04503dSPeter Wemm struct accept_args /* { 500c21dee17SSøren Schmidt int s; 501c21dee17SSøren Schmidt caddr_t name; 502c21dee17SSøren Schmidt int *anamelen; 503ef04503dSPeter Wemm } */ bsd_args; 504dba5ab66SMarcel Moolenaar struct fcntl_args /* { 505dba5ab66SMarcel Moolenaar int fd; 506dba5ab66SMarcel Moolenaar int cmd; 507dba5ab66SMarcel Moolenaar long arg; 508dba5ab66SMarcel Moolenaar } */ f_args; 509c21dee17SSøren Schmidt int error; 510c21dee17SSøren Schmidt 5113f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5123f3a4815SMarcel Moolenaar return (error); 5133f3a4815SMarcel Moolenaar 514c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 515c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.addr; 516c21dee17SSøren Schmidt bsd_args.anamelen = linux_args.namelen; 517dba5ab66SMarcel Moolenaar error = oaccept(p, &bsd_args); 518dba5ab66SMarcel Moolenaar if (error) 519dba5ab66SMarcel Moolenaar return (error); 520dba5ab66SMarcel Moolenaar 521dba5ab66SMarcel Moolenaar /* 522dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 523dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 524dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 525dba5ab66SMarcel Moolenaar */ 526dba5ab66SMarcel Moolenaar f_args.fd = p->p_retval[0]; 527dba5ab66SMarcel Moolenaar f_args.cmd = F_SETFL; 528dba5ab66SMarcel Moolenaar f_args.arg = 0; 529dba5ab66SMarcel Moolenaar (void)fcntl(p, &f_args); 530dba5ab66SMarcel Moolenaar p->p_retval[0] = f_args.fd; 531dba5ab66SMarcel Moolenaar return (0); 532c21dee17SSøren Schmidt } 533c21dee17SSøren Schmidt 534c21dee17SSøren Schmidt struct linux_getsockname_args { 535c21dee17SSøren Schmidt int s; 536c21dee17SSøren Schmidt struct sockaddr *addr; 537c21dee17SSøren Schmidt int *namelen; 538c21dee17SSøren Schmidt }; 539c21dee17SSøren Schmidt 540c21dee17SSøren Schmidt static int 541cb226aaaSPoul-Henning Kamp linux_getsockname(struct proc *p, struct linux_getsockname_args *args) 542c21dee17SSøren Schmidt { 543c21dee17SSøren Schmidt struct linux_getsockname_args linux_args; 544ef04503dSPeter Wemm struct getsockname_args /* { 545c21dee17SSøren Schmidt int fdes; 546c21dee17SSøren Schmidt caddr_t asa; 547c21dee17SSøren Schmidt int *alen; 548ef04503dSPeter Wemm } */ bsd_args; 549c21dee17SSøren Schmidt int error; 550c21dee17SSøren Schmidt 5513f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5523f3a4815SMarcel Moolenaar return (error); 5533f3a4815SMarcel Moolenaar 554c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 555c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 556c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 5573f3a4815SMarcel Moolenaar return (ogetsockname(p, &bsd_args)); 558c21dee17SSøren Schmidt } 559c21dee17SSøren Schmidt 560c21dee17SSøren Schmidt struct linux_getpeername_args { 561c21dee17SSøren Schmidt int s; 562c21dee17SSøren Schmidt struct sockaddr *addr; 563c21dee17SSøren Schmidt int *namelen; 564c21dee17SSøren Schmidt }; 565c21dee17SSøren Schmidt 566c21dee17SSøren Schmidt static int 567cb226aaaSPoul-Henning Kamp linux_getpeername(struct proc *p, struct linux_getpeername_args *args) 568c21dee17SSøren Schmidt { 569c21dee17SSøren Schmidt struct linux_getpeername_args linux_args; 570ef04503dSPeter Wemm struct ogetpeername_args /* { 571c21dee17SSøren Schmidt int fdes; 572c21dee17SSøren Schmidt caddr_t asa; 573c21dee17SSøren Schmidt int *alen; 574ef04503dSPeter Wemm } */ bsd_args; 575c21dee17SSøren Schmidt int error; 576c21dee17SSøren Schmidt 5773f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5783f3a4815SMarcel Moolenaar return (error); 5793f3a4815SMarcel Moolenaar 580c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 581c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 582c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 5833f3a4815SMarcel Moolenaar return (ogetpeername(p, &bsd_args)); 584c21dee17SSøren Schmidt } 585c21dee17SSøren Schmidt 586c21dee17SSøren Schmidt struct linux_socketpair_args { 587c21dee17SSøren Schmidt int domain; 588c21dee17SSøren Schmidt int type; 589c21dee17SSøren Schmidt int protocol; 590c21dee17SSøren Schmidt int *rsv; 591c21dee17SSøren Schmidt }; 592c21dee17SSøren Schmidt 593c21dee17SSøren Schmidt static int 594cb226aaaSPoul-Henning Kamp linux_socketpair(struct proc *p, struct linux_socketpair_args *args) 595c21dee17SSøren Schmidt { 596c21dee17SSøren Schmidt struct linux_socketpair_args linux_args; 597ef04503dSPeter Wemm struct socketpair_args /* { 598c21dee17SSøren Schmidt int domain; 599c21dee17SSøren Schmidt int type; 600c21dee17SSøren Schmidt int protocol; 601c21dee17SSøren Schmidt int *rsv; 602ef04503dSPeter Wemm } */ bsd_args; 603c21dee17SSøren Schmidt int error; 604c21dee17SSøren Schmidt 6053f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6063f3a4815SMarcel Moolenaar return (error); 6073f3a4815SMarcel Moolenaar 608c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 609c21dee17SSøren Schmidt if (bsd_args.domain == -1) 6103f3a4815SMarcel Moolenaar return (EINVAL); 6113f3a4815SMarcel Moolenaar 612c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 613c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 614c21dee17SSøren Schmidt bsd_args.rsv = linux_args.rsv; 6153f3a4815SMarcel Moolenaar return (socketpair(p, &bsd_args)); 616c21dee17SSøren Schmidt } 617c21dee17SSøren Schmidt 618c21dee17SSøren Schmidt struct linux_send_args { 619c21dee17SSøren Schmidt int s; 620c21dee17SSøren Schmidt void *msg; 621c21dee17SSøren Schmidt int len; 622c21dee17SSøren Schmidt int flags; 623c21dee17SSøren Schmidt }; 624c21dee17SSøren Schmidt 625c21dee17SSøren Schmidt static int 626cb226aaaSPoul-Henning Kamp linux_send(struct proc *p, struct linux_send_args *args) 627c21dee17SSøren Schmidt { 628c21dee17SSøren Schmidt struct linux_send_args linux_args; 629ef04503dSPeter Wemm struct osend_args /* { 630c21dee17SSøren Schmidt int s; 631c21dee17SSøren Schmidt caddr_t buf; 632c21dee17SSøren Schmidt int len; 633c21dee17SSøren Schmidt int flags; 634ef04503dSPeter Wemm } */ bsd_args; 635c21dee17SSøren Schmidt int error; 636c21dee17SSøren Schmidt 6373f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6383f3a4815SMarcel Moolenaar return (error); 6393f3a4815SMarcel Moolenaar 640c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 641c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 642c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 643c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 6443f3a4815SMarcel Moolenaar return (osend(p, &bsd_args)); 645c21dee17SSøren Schmidt } 646c21dee17SSøren Schmidt 647c21dee17SSøren Schmidt struct linux_recv_args { 648c21dee17SSøren Schmidt int s; 649c21dee17SSøren Schmidt void *msg; 650c21dee17SSøren Schmidt int len; 651c21dee17SSøren Schmidt int flags; 652c21dee17SSøren Schmidt }; 653c21dee17SSøren Schmidt 654c21dee17SSøren Schmidt static int 655cb226aaaSPoul-Henning Kamp linux_recv(struct proc *p, struct linux_recv_args *args) 656c21dee17SSøren Schmidt { 657c21dee17SSøren Schmidt struct linux_recv_args linux_args; 658ef04503dSPeter Wemm struct orecv_args /* { 659c21dee17SSøren Schmidt int s; 660c21dee17SSøren Schmidt caddr_t buf; 661c21dee17SSøren Schmidt int len; 662c21dee17SSøren Schmidt int flags; 663ef04503dSPeter Wemm } */ bsd_args; 664c21dee17SSøren Schmidt int error; 665c21dee17SSøren Schmidt 6663f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6673f3a4815SMarcel Moolenaar return (error); 6683f3a4815SMarcel Moolenaar 669c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 670c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 671c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 672c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 6733f3a4815SMarcel Moolenaar return (orecv(p, &bsd_args)); 674c21dee17SSøren Schmidt } 675c21dee17SSøren Schmidt 676c21dee17SSøren Schmidt struct linux_sendto_args { 677c21dee17SSøren Schmidt int s; 678c21dee17SSøren Schmidt void *msg; 679c21dee17SSøren Schmidt int len; 680c21dee17SSøren Schmidt int flags; 681c21dee17SSøren Schmidt caddr_t to; 682c21dee17SSøren Schmidt int tolen; 683c21dee17SSøren Schmidt }; 684c21dee17SSøren Schmidt 685c21dee17SSøren Schmidt static int 686cb226aaaSPoul-Henning Kamp linux_sendto(struct proc *p, struct linux_sendto_args *args) 687c21dee17SSøren Schmidt { 688c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 689ef04503dSPeter Wemm struct sendto_args /* { 690c21dee17SSøren Schmidt int s; 691c21dee17SSøren Schmidt caddr_t buf; 692c21dee17SSøren Schmidt size_t len; 693c21dee17SSøren Schmidt int flags; 694c21dee17SSøren Schmidt caddr_t to; 695c21dee17SSøren Schmidt int tolen; 696ef04503dSPeter Wemm } */ bsd_args; 697c21dee17SSøren Schmidt int error; 698c21dee17SSøren Schmidt 6993f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7003f3a4815SMarcel Moolenaar return (error); 7013f3a4815SMarcel Moolenaar 702c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 703c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 704c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 705c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 706c21dee17SSøren Schmidt bsd_args.to = linux_args.to; 707c21dee17SSøren Schmidt bsd_args.tolen = linux_args.tolen; 708f2477ae1SMike Smith 709f2477ae1SMike Smith if (linux_check_hdrincl(p, linux_args.s) == 0) 710f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 7113f3a4815SMarcel Moolenaar return (linux_sendto_hdrincl(p, &bsd_args)); 712f2477ae1SMike Smith 7133f3a4815SMarcel Moolenaar return (sendto(p, &bsd_args)); 714c21dee17SSøren Schmidt } 715c21dee17SSøren Schmidt 716c21dee17SSøren Schmidt struct linux_recvfrom_args { 717c21dee17SSøren Schmidt int s; 718c21dee17SSøren Schmidt void *buf; 719c21dee17SSøren Schmidt int len; 720c21dee17SSøren Schmidt int flags; 721c21dee17SSøren Schmidt caddr_t from; 722c21dee17SSøren Schmidt int *fromlen; 723c21dee17SSøren Schmidt }; 724c21dee17SSøren Schmidt 725c21dee17SSøren Schmidt static int 726cb226aaaSPoul-Henning Kamp linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args) 727c21dee17SSøren Schmidt { 728c21dee17SSøren Schmidt struct linux_recvfrom_args linux_args; 729ef04503dSPeter Wemm struct recvfrom_args /* { 730c21dee17SSøren Schmidt int s; 731c21dee17SSøren Schmidt caddr_t buf; 732c21dee17SSøren Schmidt size_t len; 733c21dee17SSøren Schmidt int flags; 734c21dee17SSøren Schmidt caddr_t from; 735c21dee17SSøren Schmidt int *fromlenaddr; 736ef04503dSPeter Wemm } */ bsd_args; 737c21dee17SSøren Schmidt int error; 738c21dee17SSøren Schmidt 7393f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7403f3a4815SMarcel Moolenaar return (error); 7413f3a4815SMarcel Moolenaar 742c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 743c21dee17SSøren Schmidt bsd_args.buf = linux_args.buf; 744c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 74540dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 746c21dee17SSøren Schmidt bsd_args.from = linux_args.from; 747c21dee17SSøren Schmidt bsd_args.fromlenaddr = linux_args.fromlen; 7483f3a4815SMarcel Moolenaar return (orecvfrom(p, &bsd_args)); 749c21dee17SSøren Schmidt } 750c21dee17SSøren Schmidt 75140dbba57SAssar Westerlund struct linux_recvmsg_args { 75240dbba57SAssar Westerlund int s; 75340dbba57SAssar Westerlund struct msghdr *msg; 75440dbba57SAssar Westerlund int flags; 75540dbba57SAssar Westerlund }; 75640dbba57SAssar Westerlund 75740dbba57SAssar Westerlund static int 75840dbba57SAssar Westerlund linux_recvmsg(struct proc *p, struct linux_recvmsg_args *args) 75940dbba57SAssar Westerlund { 76040dbba57SAssar Westerlund struct linux_recvmsg_args linux_args; 76140dbba57SAssar Westerlund struct recvmsg_args /* { 76240dbba57SAssar Westerlund int s; 76340dbba57SAssar Westerlund struct msghdr *msg; 76440dbba57SAssar Westerlund int flags; 76540dbba57SAssar Westerlund } */ bsd_args; 76640dbba57SAssar Westerlund int error; 76740dbba57SAssar Westerlund 76840dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 76940dbba57SAssar Westerlund return (error); 77040dbba57SAssar Westerlund 77140dbba57SAssar Westerlund bsd_args.s = linux_args.s; 77240dbba57SAssar Westerlund bsd_args.msg = linux_args.msg; 77340dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 77440dbba57SAssar Westerlund return (recvmsg(p, &bsd_args)); 77540dbba57SAssar Westerlund } 77640dbba57SAssar Westerlund 777c21dee17SSøren Schmidt struct linux_shutdown_args { 778c21dee17SSøren Schmidt int s; 779c21dee17SSøren Schmidt int how; 780c21dee17SSøren Schmidt }; 781c21dee17SSøren Schmidt 782c21dee17SSøren Schmidt static int 783cb226aaaSPoul-Henning Kamp linux_shutdown(struct proc *p, struct linux_shutdown_args *args) 784c21dee17SSøren Schmidt { 785c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 786ef04503dSPeter Wemm struct shutdown_args /* { 787c21dee17SSøren Schmidt int s; 788c21dee17SSøren Schmidt int how; 789ef04503dSPeter Wemm } */ bsd_args; 790c21dee17SSøren Schmidt int error; 791c21dee17SSøren Schmidt 7923f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7933f3a4815SMarcel Moolenaar return (error); 7943f3a4815SMarcel Moolenaar 795c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 796c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 7973f3a4815SMarcel Moolenaar return (shutdown(p, &bsd_args)); 798c21dee17SSøren Schmidt } 799c21dee17SSøren Schmidt 800c21dee17SSøren Schmidt struct linux_setsockopt_args { 801c21dee17SSøren Schmidt int s; 802c21dee17SSøren Schmidt int level; 803c21dee17SSøren Schmidt int optname; 804c21dee17SSøren Schmidt void *optval; 805c21dee17SSøren Schmidt int optlen; 806c21dee17SSøren Schmidt }; 807c21dee17SSøren Schmidt 808c21dee17SSøren Schmidt static int 809cb226aaaSPoul-Henning Kamp linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args) 810c21dee17SSøren Schmidt { 811c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 812ef04503dSPeter Wemm struct setsockopt_args /* { 813c21dee17SSøren Schmidt int s; 814c21dee17SSøren Schmidt int level; 815c21dee17SSøren Schmidt int name; 816c21dee17SSøren Schmidt caddr_t val; 817c21dee17SSøren Schmidt int valsize; 818ef04503dSPeter Wemm } */ bsd_args; 819c21dee17SSøren Schmidt int error, name; 820c21dee17SSøren Schmidt 8213f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8223f3a4815SMarcel Moolenaar return (error); 8233f3a4815SMarcel Moolenaar 824c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 825c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 826c21dee17SSøren Schmidt switch (bsd_args.level) { 827c21dee17SSøren Schmidt case SOL_SOCKET: 828c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 829c21dee17SSøren Schmidt break; 830c21dee17SSøren Schmidt case IPPROTO_IP: 831c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 832c21dee17SSøren Schmidt break; 833dad3b88aSMike Smith case IPPROTO_TCP: 834dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 835dad3b88aSMike Smith name = linux_args.optname; 836dad3b88aSMike Smith break; 837c21dee17SSøren Schmidt default: 8383f3a4815SMarcel Moolenaar name = -1; 8393f3a4815SMarcel Moolenaar break; 840c21dee17SSøren Schmidt } 841c21dee17SSøren Schmidt if (name == -1) 8423f3a4815SMarcel Moolenaar return (EINVAL); 8433f3a4815SMarcel Moolenaar 844c21dee17SSøren Schmidt bsd_args.name = name; 845c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 846c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 8473f3a4815SMarcel Moolenaar return (setsockopt(p, &bsd_args)); 848c21dee17SSøren Schmidt } 849c21dee17SSøren Schmidt 850c21dee17SSøren Schmidt struct linux_getsockopt_args { 851c21dee17SSøren Schmidt int s; 852c21dee17SSøren Schmidt int level; 853c21dee17SSøren Schmidt int optname; 854c21dee17SSøren Schmidt void *optval; 855c21dee17SSøren Schmidt int *optlen; 856c21dee17SSøren Schmidt }; 857c21dee17SSøren Schmidt 858c21dee17SSøren Schmidt static int 859cb226aaaSPoul-Henning Kamp linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args) 860c21dee17SSøren Schmidt { 861c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 862ef04503dSPeter Wemm struct getsockopt_args /* { 863c21dee17SSøren Schmidt int s; 864c21dee17SSøren Schmidt int level; 865c21dee17SSøren Schmidt int name; 866c21dee17SSøren Schmidt caddr_t val; 867c21dee17SSøren Schmidt int *avalsize; 868ef04503dSPeter Wemm } */ bsd_args; 869c21dee17SSøren Schmidt int error, name; 870c21dee17SSøren Schmidt 8713f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8723f3a4815SMarcel Moolenaar return (error); 8733f3a4815SMarcel Moolenaar 874c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 875c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 876c21dee17SSøren Schmidt switch (bsd_args.level) { 877c21dee17SSøren Schmidt case SOL_SOCKET: 878c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 879c21dee17SSøren Schmidt break; 880c21dee17SSøren Schmidt case IPPROTO_IP: 881c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 882c21dee17SSøren Schmidt break; 883dad3b88aSMike Smith case IPPROTO_TCP: 884dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 885dad3b88aSMike Smith name = linux_args.optname; 886dad3b88aSMike Smith break; 887c21dee17SSøren Schmidt default: 8883f3a4815SMarcel Moolenaar name = -1; 8893f3a4815SMarcel Moolenaar break; 890c21dee17SSøren Schmidt } 891c21dee17SSøren Schmidt if (name == -1) 8923f3a4815SMarcel Moolenaar return (EINVAL); 8933f3a4815SMarcel Moolenaar 894f2477ae1SMike Smith bsd_args.name = name; 895c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 896c21dee17SSøren Schmidt bsd_args.avalsize = linux_args.optlen; 8973f3a4815SMarcel Moolenaar return (getsockopt(p, &bsd_args)); 898c21dee17SSøren Schmidt } 899c21dee17SSøren Schmidt 900c21dee17SSøren Schmidt int 901cb226aaaSPoul-Henning Kamp linux_socketcall(struct proc *p, struct linux_socketcall_args *args) 902c21dee17SSøren Schmidt { 9033f3a4815SMarcel Moolenaar 904c21dee17SSøren Schmidt switch (args->what) { 905c21dee17SSøren Schmidt case LINUX_SOCKET: 9063f3a4815SMarcel Moolenaar return (linux_socket(p, args->args)); 907c21dee17SSøren Schmidt case LINUX_BIND: 9083f3a4815SMarcel Moolenaar return (linux_bind(p, args->args)); 909c21dee17SSøren Schmidt case LINUX_CONNECT: 9103f3a4815SMarcel Moolenaar return (linux_connect(p, args->args)); 911c21dee17SSøren Schmidt case LINUX_LISTEN: 9123f3a4815SMarcel Moolenaar return (linux_listen(p, args->args)); 913c21dee17SSøren Schmidt case LINUX_ACCEPT: 9143f3a4815SMarcel Moolenaar return (linux_accept(p, args->args)); 915c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 9163f3a4815SMarcel Moolenaar return (linux_getsockname(p, args->args)); 917c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 9183f3a4815SMarcel Moolenaar return (linux_getpeername(p, args->args)); 919c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 9203f3a4815SMarcel Moolenaar return (linux_socketpair(p, args->args)); 921c21dee17SSøren Schmidt case LINUX_SEND: 9223f3a4815SMarcel Moolenaar return (linux_send(p, args->args)); 923c21dee17SSøren Schmidt case LINUX_RECV: 9243f3a4815SMarcel Moolenaar return (linux_recv(p, args->args)); 925c21dee17SSøren Schmidt case LINUX_SENDTO: 9263f3a4815SMarcel Moolenaar return (linux_sendto(p, args->args)); 927c21dee17SSøren Schmidt case LINUX_RECVFROM: 9283f3a4815SMarcel Moolenaar return (linux_recvfrom(p, args->args)); 929c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 9303f3a4815SMarcel Moolenaar return (linux_shutdown(p, args->args)); 931c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 9323f3a4815SMarcel Moolenaar return (linux_setsockopt(p, args->args)); 933c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 9343f3a4815SMarcel Moolenaar return (linux_getsockopt(p, args->args)); 935e76bba09SSøren Schmidt case LINUX_SENDMSG: 936096d55fcSMike Smith do { 937096d55fcSMike Smith int error; 938096d55fcSMike Smith int level; 939096d55fcSMike Smith caddr_t control; 940096d55fcSMike Smith struct { 941096d55fcSMike Smith int s; 942096d55fcSMike Smith const struct msghdr *msg; 943096d55fcSMike Smith int flags; 944096d55fcSMike Smith } *uap = args->args; 945096d55fcSMike Smith 9463f3a4815SMarcel Moolenaar error = copyin(&uap->msg->msg_control, &control, 9473f3a4815SMarcel Moolenaar sizeof(caddr_t)); 948096d55fcSMike Smith if (error) 9493f3a4815SMarcel Moolenaar return (error); 9503f3a4815SMarcel Moolenaar 951096d55fcSMike Smith if (control == NULL) 952096d55fcSMike Smith goto done; 9533f3a4815SMarcel Moolenaar 954096d55fcSMike Smith error = copyin(&((struct cmsghdr*)control)->cmsg_level, 955096d55fcSMike Smith &level, sizeof(int)); 956096d55fcSMike Smith if (error) 9573f3a4815SMarcel Moolenaar return (error); 9583f3a4815SMarcel Moolenaar 959096d55fcSMike Smith if (level == 1) { 960096d55fcSMike Smith /* 9613f3a4815SMarcel Moolenaar * Linux thinks that SOL_SOCKET is 1; we know 9623f3a4815SMarcel Moolenaar * that it's really 0xffff, of course. 963096d55fcSMike Smith */ 964096d55fcSMike Smith level = SOL_SOCKET; 9653f3a4815SMarcel Moolenaar error = copyout(&level, 9663f3a4815SMarcel Moolenaar &((struct cmsghdr *)control)->cmsg_level, 9673f3a4815SMarcel Moolenaar sizeof(int)); 968096d55fcSMike Smith if (error) 9693f3a4815SMarcel Moolenaar return (error); 970096d55fcSMike Smith } 971096d55fcSMike Smith done: 9723f3a4815SMarcel Moolenaar return (sendmsg(p, args->args)); 973096d55fcSMike Smith } while (0); 974e76bba09SSøren Schmidt case LINUX_RECVMSG: 97540dbba57SAssar Westerlund return (linux_recvmsg(p, args->args)); 976c21dee17SSøren Schmidt } 9773f3a4815SMarcel Moolenaar 9783f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 9793f3a4815SMarcel Moolenaar return (ENOSYS); 980c21dee17SSøren Schmidt } 9815231fb20SDavid E. O'Brien #endif /*!__alpha__*/ 982