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 1521dc7d4fSJens Schweikhardt * derived from this software without 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> 430bf301c0SJonathan Lemon #include <sys/file.h> 44c21dee17SSøren Schmidt #include <sys/socket.h> 450bf301c0SJonathan Lemon #include <sys/socketvar.h> 4608637435SBruce Evans #include <sys/uio.h> 471f3dad5aSBruce Evans 48c21dee17SSøren Schmidt #include <netinet/in.h> 49f2477ae1SMike Smith #include <netinet/in_systm.h> 50f2477ae1SMike Smith #include <netinet/ip.h> 51c21dee17SSøren Schmidt 52ac951e62SMarcel Moolenaar #include <machine/../linux/linux.h> 53ebea8660SMarcel Moolenaar #include <machine/../linux/linux_proto.h> 5440dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 55ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 56c21dee17SSøren Schmidt 574730796cSBill Fenner /* 584730796cSBill Fenner * FreeBSD's socket calls require the sockaddr struct length to agree 594730796cSBill Fenner * with the address family. Linux does not, so we must force it. 604730796cSBill Fenner */ 614730796cSBill Fenner static int 624730796cSBill Fenner linux_to_bsd_namelen(caddr_t name, int namelen) 634730796cSBill Fenner { 644730796cSBill Fenner uint16_t family; /* XXX must match Linux sockaddr */ 654730796cSBill Fenner 664730796cSBill Fenner if (copyin(name, &family, sizeof(family))) 674730796cSBill Fenner return namelen; 684730796cSBill Fenner 694730796cSBill Fenner switch (family) { 704730796cSBill Fenner case AF_INET: 714730796cSBill Fenner return sizeof(struct sockaddr_in); 724730796cSBill Fenner case AF_INET6: 734730796cSBill Fenner return sizeof(struct sockaddr_in6); 744730796cSBill Fenner } 754730796cSBill Fenner return namelen; 764730796cSBill Fenner } 774730796cSBill Fenner 785231fb20SDavid E. O'Brien #ifndef __alpha__ 79c21dee17SSøren Schmidt static int 80c21dee17SSøren Schmidt linux_to_bsd_domain(int domain) 81c21dee17SSøren Schmidt { 823f3a4815SMarcel Moolenaar 83c21dee17SSøren Schmidt switch (domain) { 84c21dee17SSøren Schmidt case LINUX_AF_UNSPEC: 853f3a4815SMarcel Moolenaar return (AF_UNSPEC); 86c21dee17SSøren Schmidt case LINUX_AF_UNIX: 873f3a4815SMarcel Moolenaar return (AF_LOCAL); 88c21dee17SSøren Schmidt case LINUX_AF_INET: 893f3a4815SMarcel Moolenaar return (AF_INET); 90c21dee17SSøren Schmidt case LINUX_AF_AX25: 913f3a4815SMarcel Moolenaar return (AF_CCITT); 92c21dee17SSøren Schmidt case LINUX_AF_IPX: 933f3a4815SMarcel Moolenaar return (AF_IPX); 94c21dee17SSøren Schmidt case LINUX_AF_APPLETALK: 953f3a4815SMarcel Moolenaar return (AF_APPLETALK); 96c21dee17SSøren Schmidt } 973f3a4815SMarcel Moolenaar return (-1); 98c21dee17SSøren Schmidt } 99c21dee17SSøren Schmidt 100c21dee17SSøren Schmidt static int 101c21dee17SSøren Schmidt linux_to_bsd_sockopt_level(int level) 102c21dee17SSøren Schmidt { 1033f3a4815SMarcel Moolenaar 104c21dee17SSøren Schmidt switch (level) { 105c21dee17SSøren Schmidt case LINUX_SOL_SOCKET: 1063f3a4815SMarcel Moolenaar return (SOL_SOCKET); 107c21dee17SSøren Schmidt } 1083f3a4815SMarcel Moolenaar return (level); 109c21dee17SSøren Schmidt } 110c21dee17SSøren Schmidt 1113f3a4815SMarcel Moolenaar static int 1123f3a4815SMarcel Moolenaar linux_to_bsd_ip_sockopt(int opt) 113c21dee17SSøren Schmidt { 1143f3a4815SMarcel Moolenaar 115c21dee17SSøren Schmidt switch (opt) { 116c21dee17SSøren Schmidt case LINUX_IP_TOS: 1173f3a4815SMarcel Moolenaar return (IP_TOS); 118c21dee17SSøren Schmidt case LINUX_IP_TTL: 1193f3a4815SMarcel Moolenaar return (IP_TTL); 12066ff6a3cSBill Fenner case LINUX_IP_OPTIONS: 1213f3a4815SMarcel Moolenaar return (IP_OPTIONS); 12266ff6a3cSBill Fenner case LINUX_IP_MULTICAST_IF: 1233f3a4815SMarcel Moolenaar return (IP_MULTICAST_IF); 12466ff6a3cSBill Fenner case LINUX_IP_MULTICAST_TTL: 1253f3a4815SMarcel Moolenaar return (IP_MULTICAST_TTL); 12666ff6a3cSBill Fenner case LINUX_IP_MULTICAST_LOOP: 1273f3a4815SMarcel Moolenaar return (IP_MULTICAST_LOOP); 12866ff6a3cSBill Fenner case LINUX_IP_ADD_MEMBERSHIP: 1293f3a4815SMarcel Moolenaar return (IP_ADD_MEMBERSHIP); 13066ff6a3cSBill Fenner case LINUX_IP_DROP_MEMBERSHIP: 1313f3a4815SMarcel Moolenaar return (IP_DROP_MEMBERSHIP); 13266ff6a3cSBill Fenner case LINUX_IP_HDRINCL: 1333f3a4815SMarcel Moolenaar return (IP_HDRINCL); 134c21dee17SSøren Schmidt } 1353f3a4815SMarcel Moolenaar return (-1); 136c21dee17SSøren Schmidt } 137c21dee17SSøren Schmidt 138c21dee17SSøren Schmidt static int 139c21dee17SSøren Schmidt linux_to_bsd_so_sockopt(int opt) 140c21dee17SSøren Schmidt { 1413f3a4815SMarcel Moolenaar 142c21dee17SSøren Schmidt switch (opt) { 143c21dee17SSøren Schmidt case LINUX_SO_DEBUG: 1443f3a4815SMarcel Moolenaar return (SO_DEBUG); 145c21dee17SSøren Schmidt case LINUX_SO_REUSEADDR: 1463f3a4815SMarcel Moolenaar return (SO_REUSEADDR); 147c21dee17SSøren Schmidt case LINUX_SO_TYPE: 1483f3a4815SMarcel Moolenaar return (SO_TYPE); 149c21dee17SSøren Schmidt case LINUX_SO_ERROR: 1503f3a4815SMarcel Moolenaar return (SO_ERROR); 151c21dee17SSøren Schmidt case LINUX_SO_DONTROUTE: 1523f3a4815SMarcel Moolenaar return (SO_DONTROUTE); 153c21dee17SSøren Schmidt case LINUX_SO_BROADCAST: 1543f3a4815SMarcel Moolenaar return (SO_BROADCAST); 155c21dee17SSøren Schmidt case LINUX_SO_SNDBUF: 1563f3a4815SMarcel Moolenaar return (SO_SNDBUF); 157c21dee17SSøren Schmidt case LINUX_SO_RCVBUF: 1583f3a4815SMarcel Moolenaar return (SO_RCVBUF); 159c21dee17SSøren Schmidt case LINUX_SO_KEEPALIVE: 1603f3a4815SMarcel Moolenaar return (SO_KEEPALIVE); 161c21dee17SSøren Schmidt case LINUX_SO_OOBINLINE: 1623f3a4815SMarcel Moolenaar return (SO_OOBINLINE); 163c21dee17SSøren Schmidt case LINUX_SO_LINGER: 1643f3a4815SMarcel Moolenaar return (SO_LINGER); 165c21dee17SSøren Schmidt } 1663f3a4815SMarcel Moolenaar return (-1); 167c21dee17SSøren Schmidt } 168c21dee17SSøren Schmidt 16940dbba57SAssar Westerlund static int 17040dbba57SAssar Westerlund linux_to_bsd_msg_flags(int flags) 17140dbba57SAssar Westerlund { 17240dbba57SAssar Westerlund int ret_flags = 0; 17340dbba57SAssar Westerlund 17440dbba57SAssar Westerlund if (flags & LINUX_MSG_OOB) 17540dbba57SAssar Westerlund ret_flags |= MSG_OOB; 17640dbba57SAssar Westerlund if (flags & LINUX_MSG_PEEK) 17740dbba57SAssar Westerlund ret_flags |= MSG_PEEK; 17840dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTROUTE) 17940dbba57SAssar Westerlund ret_flags |= MSG_DONTROUTE; 18040dbba57SAssar Westerlund if (flags & LINUX_MSG_CTRUNC) 18140dbba57SAssar Westerlund ret_flags |= MSG_CTRUNC; 18240dbba57SAssar Westerlund if (flags & LINUX_MSG_TRUNC) 18340dbba57SAssar Westerlund ret_flags |= MSG_TRUNC; 18440dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTWAIT) 18540dbba57SAssar Westerlund ret_flags |= MSG_DONTWAIT; 18640dbba57SAssar Westerlund if (flags & LINUX_MSG_EOR) 18740dbba57SAssar Westerlund ret_flags |= MSG_EOR; 18840dbba57SAssar Westerlund if (flags & LINUX_MSG_WAITALL) 18940dbba57SAssar Westerlund ret_flags |= MSG_WAITALL; 19040dbba57SAssar Westerlund #if 0 /* not handled */ 19140dbba57SAssar Westerlund if (flags & LINUX_MSG_PROXY) 19240dbba57SAssar Westerlund ; 19340dbba57SAssar Westerlund if (flags & LINUX_MSG_FIN) 19440dbba57SAssar Westerlund ; 19540dbba57SAssar Westerlund if (flags & LINUX_MSG_SYN) 19640dbba57SAssar Westerlund ; 19740dbba57SAssar Westerlund if (flags & LINUX_MSG_CONFIRM) 19840dbba57SAssar Westerlund ; 19940dbba57SAssar Westerlund if (flags & LINUX_MSG_RST) 20040dbba57SAssar Westerlund ; 20140dbba57SAssar Westerlund if (flags & LINUX_MSG_ERRQUEUE) 20240dbba57SAssar Westerlund ; 20340dbba57SAssar Westerlund if (flags & LINUX_MSG_NOSIGNAL) 20440dbba57SAssar Westerlund ; 20540dbba57SAssar Westerlund #endif 20640dbba57SAssar Westerlund return ret_flags; 20740dbba57SAssar Westerlund } 20840dbba57SAssar Westerlund 2093f3a4815SMarcel Moolenaar /* Return 0 if IP_HDRINCL is set for the given socket. */ 210f2477ae1SMike Smith static int 211b40ce416SJulian Elischer linux_check_hdrincl(struct thread *td, int s) 212f2477ae1SMike Smith { 213f2477ae1SMike Smith struct getsockopt_args /* { 214f2477ae1SMike Smith int s; 215f2477ae1SMike Smith int level; 216f2477ae1SMike Smith int name; 217f2477ae1SMike Smith caddr_t val; 218f2477ae1SMike Smith int *avalsize; 219f2477ae1SMike Smith } */ bsd_args; 220f2477ae1SMike Smith int error; 221f2477ae1SMike Smith caddr_t sg, val, valsize; 222f2477ae1SMike Smith int size_val = sizeof val; 223f2477ae1SMike Smith int optval; 224f2477ae1SMike Smith 225f2477ae1SMike Smith sg = stackgap_init(); 226f2477ae1SMike Smith val = stackgap_alloc(&sg, sizeof(int)); 227f2477ae1SMike Smith valsize = stackgap_alloc(&sg, sizeof(int)); 228f2477ae1SMike Smith 229f2477ae1SMike Smith if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 2303f3a4815SMarcel Moolenaar return (error); 2313f3a4815SMarcel Moolenaar 232f2477ae1SMike Smith bsd_args.s = s; 233f2477ae1SMike Smith bsd_args.level = IPPROTO_IP; 234f2477ae1SMike Smith bsd_args.name = IP_HDRINCL; 235f2477ae1SMike Smith bsd_args.val = val; 236f2477ae1SMike Smith bsd_args.avalsize = (int *)valsize; 237b40ce416SJulian Elischer if ((error = getsockopt(td, &bsd_args))) 2383f3a4815SMarcel Moolenaar return (error); 2393f3a4815SMarcel Moolenaar 240f2477ae1SMike Smith if ((error = copyin(val, &optval, sizeof(optval)))) 2413f3a4815SMarcel Moolenaar return (error); 2423f3a4815SMarcel Moolenaar 2433f3a4815SMarcel Moolenaar return (optval == 0); 244f2477ae1SMike Smith } 245f2477ae1SMike Smith 246f2477ae1SMike Smith /* 247f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 248f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 249f2477ae1SMike Smith */ 250f2477ae1SMike Smith static int 251b40ce416SJulian Elischer linux_sendto_hdrincl(struct thread *td, struct sendto_args *bsd_args) 252f2477ae1SMike Smith { 253f2477ae1SMike Smith /* 254f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 255f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 256f2477ae1SMike Smith * It should include all the fields we modify (ip_len and ip_off) 257f2477ae1SMike Smith * and be as small as possible to minimize copying overhead. 258f2477ae1SMike Smith */ 259f2477ae1SMike Smith #define linux_ip_copysize 8 260f2477ae1SMike Smith 261f2477ae1SMike Smith caddr_t sg; 262f2477ae1SMike Smith struct ip *packet; 263f2477ae1SMike Smith struct msghdr *msg; 264f2477ae1SMike Smith struct iovec *iov; 265f2477ae1SMike Smith 266f2477ae1SMike Smith int error; 267f2477ae1SMike Smith struct sendmsg_args /* { 268f2477ae1SMike Smith int s; 269f2477ae1SMike Smith caddr_t msg; 270f2477ae1SMike Smith int flags; 271f2477ae1SMike Smith } */ sendmsg_args; 272f2477ae1SMike Smith 273f2477ae1SMike Smith /* Check the packet isn't too small before we mess with it */ 274f2477ae1SMike Smith if (bsd_args->len < linux_ip_copysize) 2753f3a4815SMarcel Moolenaar return (EINVAL); 276f2477ae1SMike Smith 277f2477ae1SMike Smith /* 278f2477ae1SMike Smith * Tweaking the user buffer in place would be bad manners. 279f2477ae1SMike Smith * We create a corrected IP header with just the needed length, 280f2477ae1SMike Smith * then use an iovec to glue it to the rest of the user packet 281f2477ae1SMike Smith * when calling sendmsg(). 282f2477ae1SMike Smith */ 283f2477ae1SMike Smith sg = stackgap_init(); 284f2477ae1SMike Smith packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize); 285f2477ae1SMike Smith msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg)); 286f2477ae1SMike Smith iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2); 287f2477ae1SMike Smith 288f2477ae1SMike Smith /* Make a copy of the beginning of the packet to be sent */ 2893f3a4815SMarcel Moolenaar if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) 2903f3a4815SMarcel Moolenaar return (error); 291f2477ae1SMike Smith 292f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 293f2477ae1SMike Smith packet->ip_len = bsd_args->len; 294f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 295f2477ae1SMike Smith 296f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 297f2477ae1SMike Smith msg->msg_name = bsd_args->to; 298f2477ae1SMike Smith msg->msg_namelen = bsd_args->tolen; 299f2477ae1SMike Smith msg->msg_iov = iov; 300f2477ae1SMike Smith msg->msg_iovlen = 2; 301f2477ae1SMike Smith msg->msg_control = NULL; 302f2477ae1SMike Smith msg->msg_controllen = 0; 303f2477ae1SMike Smith msg->msg_flags = 0; 304f2477ae1SMike Smith iov[0].iov_base = (char *)packet; 305f2477ae1SMike Smith iov[0].iov_len = linux_ip_copysize; 306f2477ae1SMike Smith iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; 307f2477ae1SMike Smith iov[1].iov_len = bsd_args->len - linux_ip_copysize; 308f2477ae1SMike Smith 309f2477ae1SMike Smith sendmsg_args.s = bsd_args->s; 310f2477ae1SMike Smith sendmsg_args.msg = (caddr_t)msg; 311f2477ae1SMike Smith sendmsg_args.flags = bsd_args->flags; 312b40ce416SJulian Elischer return (sendmsg(td, &sendmsg_args)); 313f2477ae1SMike Smith } 314f2477ae1SMike Smith 315c21dee17SSøren Schmidt struct linux_socket_args { 316c21dee17SSøren Schmidt int domain; 317c21dee17SSøren Schmidt int type; 318c21dee17SSøren Schmidt int protocol; 319c21dee17SSøren Schmidt }; 320c21dee17SSøren Schmidt 321c21dee17SSøren Schmidt static int 322b40ce416SJulian Elischer linux_socket(struct thread *td, struct linux_socket_args *args) 323c21dee17SSøren Schmidt { 324c21dee17SSøren Schmidt struct linux_socket_args linux_args; 325ef04503dSPeter Wemm struct socket_args /* { 326c21dee17SSøren Schmidt int domain; 327c21dee17SSøren Schmidt int type; 328c21dee17SSøren Schmidt int protocol; 329ef04503dSPeter Wemm } */ bsd_args; 330c21dee17SSøren Schmidt int error; 331f2477ae1SMike Smith int retval_socket; 332c21dee17SSøren Schmidt 3333f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 3343f3a4815SMarcel Moolenaar return (error); 3353f3a4815SMarcel Moolenaar 336c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 337c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 338c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 339c21dee17SSøren Schmidt if (bsd_args.domain == -1) 3403f3a4815SMarcel Moolenaar return (EINVAL); 341f2477ae1SMike Smith 342b40ce416SJulian Elischer retval_socket = socket(td, &bsd_args); 343f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 344f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 345f2477ae1SMike Smith && bsd_args.domain == AF_INET 346f2477ae1SMike Smith && retval_socket >= 0) { 347f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 348f2477ae1SMike Smith struct setsockopt_args /* { 349f2477ae1SMike Smith int s; 350f2477ae1SMike Smith int level; 351f2477ae1SMike Smith int name; 352f2477ae1SMike Smith caddr_t val; 353f2477ae1SMike Smith int valsize; 354f2477ae1SMike Smith } */ bsd_setsockopt_args; 355f2477ae1SMike Smith caddr_t sg; 356f2477ae1SMike Smith int *hdrincl; 357f2477ae1SMike Smith 358f2477ae1SMike Smith sg = stackgap_init(); 359f2477ae1SMike Smith hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 360f2477ae1SMike Smith *hdrincl = 1; 361b40ce416SJulian Elischer bsd_setsockopt_args.s = td->td_retval[0]; 362f2477ae1SMike Smith bsd_setsockopt_args.level = IPPROTO_IP; 363f2477ae1SMike Smith bsd_setsockopt_args.name = IP_HDRINCL; 364f2477ae1SMike Smith bsd_setsockopt_args.val = (caddr_t)hdrincl; 365f2477ae1SMike Smith bsd_setsockopt_args.valsize = sizeof(*hdrincl); 366f2477ae1SMike Smith /* We ignore any error returned by setsockopt() */ 367b40ce416SJulian Elischer setsockopt(td, &bsd_setsockopt_args); 368f2477ae1SMike Smith /* Copy back the return value from socket() */ 369b40ce416SJulian Elischer td->td_retval[0] = bsd_setsockopt_args.s; 370f2477ae1SMike Smith } 3713f3a4815SMarcel Moolenaar 3723f3a4815SMarcel Moolenaar return (retval_socket); 373c21dee17SSøren Schmidt } 374c21dee17SSøren Schmidt 375c21dee17SSøren Schmidt struct linux_bind_args { 376c21dee17SSøren Schmidt int s; 377c21dee17SSøren Schmidt struct sockaddr *name; 378c21dee17SSøren Schmidt int namelen; 379c21dee17SSøren Schmidt }; 380c21dee17SSøren Schmidt 381c21dee17SSøren Schmidt static int 382b40ce416SJulian Elischer linux_bind(struct thread *td, struct linux_bind_args *args) 383c21dee17SSøren Schmidt { 384c21dee17SSøren Schmidt struct linux_bind_args linux_args; 385ef04503dSPeter Wemm struct bind_args /* { 386c21dee17SSøren Schmidt int s; 387c21dee17SSøren Schmidt caddr_t name; 388c21dee17SSøren Schmidt int namelen; 389ef04503dSPeter Wemm } */ bsd_args; 390c21dee17SSøren Schmidt int error; 391c21dee17SSøren Schmidt 3923f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 3933f3a4815SMarcel Moolenaar return (error); 3943f3a4815SMarcel Moolenaar 395c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 396c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.name; 3974730796cSBill Fenner bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen); 398b40ce416SJulian Elischer return (bind(td, &bsd_args)); 399c21dee17SSøren Schmidt } 400c21dee17SSøren Schmidt 401c21dee17SSøren Schmidt struct linux_connect_args { 402c21dee17SSøren Schmidt int s; 403c21dee17SSøren Schmidt struct sockaddr * name; 404c21dee17SSøren Schmidt int namelen; 405c21dee17SSøren Schmidt }; 406b40ce416SJulian Elischer int linux_connect(struct thread *, struct linux_connect_args *); 407930a65feSAndrew Gallatin #endif /* !__alpha__*/ 408c21dee17SSøren Schmidt 409930a65feSAndrew Gallatin int 410b40ce416SJulian Elischer linux_connect(struct thread *td, struct linux_connect_args *args) 411c21dee17SSøren Schmidt { 412c21dee17SSøren Schmidt struct linux_connect_args linux_args; 413ef04503dSPeter Wemm struct connect_args /* { 414c21dee17SSøren Schmidt int s; 415c21dee17SSøren Schmidt caddr_t name; 416c21dee17SSøren Schmidt int namelen; 417ef04503dSPeter Wemm } */ bsd_args; 4180bf301c0SJonathan Lemon struct socket *so; 41939c95b83SMatthew Dillon u_int fflag; 420c21dee17SSøren Schmidt int error; 421c21dee17SSøren Schmidt 422930a65feSAndrew Gallatin #ifdef __alpha__ 423930a65feSAndrew Gallatin bcopy(args, &linux_args, sizeof(linux_args)); 424930a65feSAndrew Gallatin #else 4253f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 4263f3a4815SMarcel Moolenaar return (error); 427930a65feSAndrew Gallatin #endif /* __alpha__ */ 4283f3a4815SMarcel Moolenaar 429c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 430c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.name; 4314730796cSBill Fenner bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen); 432b40ce416SJulian Elischer error = connect(td, &bsd_args); 4330bf301c0SJonathan Lemon if (error != EISCONN) 4340bf301c0SJonathan Lemon return (error); 4350bf301c0SJonathan Lemon 436dad3b88aSMike Smith /* 437dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 438dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 439dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 440dad3b88aSMike Smith */ 44139c95b83SMatthew Dillon if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) 4423f3a4815SMarcel Moolenaar return(error); 4430bf301c0SJonathan Lemon error = EISCONN; 44439c95b83SMatthew Dillon if (fflag & FNONBLOCK) { 4455002a60fSMarcel Moolenaar if (so->so_emuldata == 0) 4460bf301c0SJonathan Lemon error = so->so_error; 4470bf301c0SJonathan Lemon so->so_emuldata = (void *)1; 448dad3b88aSMike Smith } 44939c95b83SMatthew Dillon fputsock(so); 4503f3a4815SMarcel Moolenaar return (error); 451c21dee17SSøren Schmidt } 452c21dee17SSøren Schmidt 453930a65feSAndrew Gallatin #ifndef __alpha__ 454930a65feSAndrew Gallatin 455c21dee17SSøren Schmidt struct linux_listen_args { 456c21dee17SSøren Schmidt int s; 457c21dee17SSøren Schmidt int backlog; 458c21dee17SSøren Schmidt }; 459c21dee17SSøren Schmidt 460c21dee17SSøren Schmidt static int 461b40ce416SJulian Elischer linux_listen(struct thread *td, struct linux_listen_args *args) 462c21dee17SSøren Schmidt { 463c21dee17SSøren Schmidt struct linux_listen_args linux_args; 464ef04503dSPeter Wemm struct listen_args /* { 465c21dee17SSøren Schmidt int s; 466c21dee17SSøren Schmidt int backlog; 467ef04503dSPeter Wemm } */ bsd_args; 468c21dee17SSøren Schmidt int error; 469c21dee17SSøren Schmidt 4703f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 4713f3a4815SMarcel Moolenaar return (error); 4723f3a4815SMarcel Moolenaar 473c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 474c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 475b40ce416SJulian Elischer return (listen(td, &bsd_args)); 476c21dee17SSøren Schmidt } 477c21dee17SSøren Schmidt 478c21dee17SSøren Schmidt struct linux_accept_args { 479c21dee17SSøren Schmidt int s; 480c21dee17SSøren Schmidt struct sockaddr *addr; 481c21dee17SSøren Schmidt int *namelen; 482c21dee17SSøren Schmidt }; 483c21dee17SSøren Schmidt 484c21dee17SSøren Schmidt static int 485b40ce416SJulian Elischer linux_accept(struct thread *td, struct linux_accept_args *args) 486c21dee17SSøren Schmidt { 487c21dee17SSøren Schmidt struct linux_accept_args linux_args; 488ef04503dSPeter Wemm struct accept_args /* { 489c21dee17SSøren Schmidt int s; 490c21dee17SSøren Schmidt caddr_t name; 491c21dee17SSøren Schmidt int *anamelen; 492ef04503dSPeter Wemm } */ bsd_args; 493dba5ab66SMarcel Moolenaar struct fcntl_args /* { 494dba5ab66SMarcel Moolenaar int fd; 495dba5ab66SMarcel Moolenaar int cmd; 496dba5ab66SMarcel Moolenaar long arg; 497dba5ab66SMarcel Moolenaar } */ f_args; 498c21dee17SSøren Schmidt int error; 499c21dee17SSøren Schmidt 5003f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5013f3a4815SMarcel Moolenaar return (error); 5023f3a4815SMarcel Moolenaar 503c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 504c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.addr; 505c21dee17SSøren Schmidt bsd_args.anamelen = linux_args.namelen; 506044af7c3SJonathan Mini error = oaccept(td, &bsd_args); 507dba5ab66SMarcel Moolenaar if (error) 508dba5ab66SMarcel Moolenaar return (error); 509dba5ab66SMarcel Moolenaar 510dba5ab66SMarcel Moolenaar /* 511dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 512dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 513dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 514dba5ab66SMarcel Moolenaar */ 515b40ce416SJulian Elischer f_args.fd = td->td_retval[0]; 516dba5ab66SMarcel Moolenaar f_args.cmd = F_SETFL; 517dba5ab66SMarcel Moolenaar f_args.arg = 0; 518b40ce416SJulian Elischer (void)fcntl(td, &f_args); 519b40ce416SJulian Elischer td->td_retval[0] = f_args.fd; 520dba5ab66SMarcel Moolenaar return (0); 521c21dee17SSøren Schmidt } 522c21dee17SSøren Schmidt 523c21dee17SSøren Schmidt struct linux_getsockname_args { 524c21dee17SSøren Schmidt int s; 525c21dee17SSøren Schmidt struct sockaddr *addr; 526c21dee17SSøren Schmidt int *namelen; 527c21dee17SSøren Schmidt }; 528c21dee17SSøren Schmidt 529c21dee17SSøren Schmidt static int 530b40ce416SJulian Elischer linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 531c21dee17SSøren Schmidt { 532c21dee17SSøren Schmidt struct linux_getsockname_args linux_args; 533ef04503dSPeter Wemm struct getsockname_args /* { 534c21dee17SSøren Schmidt int fdes; 535c21dee17SSøren Schmidt caddr_t asa; 536c21dee17SSøren Schmidt int *alen; 537ef04503dSPeter Wemm } */ bsd_args; 538c21dee17SSøren Schmidt int error; 539c21dee17SSøren Schmidt 5403f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5413f3a4815SMarcel Moolenaar return (error); 5423f3a4815SMarcel Moolenaar 543c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 544c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 545c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 546044af7c3SJonathan Mini return (ogetsockname(td, &bsd_args)); 547c21dee17SSøren Schmidt } 548c21dee17SSøren Schmidt 549c21dee17SSøren Schmidt struct linux_getpeername_args { 550c21dee17SSøren Schmidt int s; 551c21dee17SSøren Schmidt struct sockaddr *addr; 552c21dee17SSøren Schmidt int *namelen; 553c21dee17SSøren Schmidt }; 554c21dee17SSøren Schmidt 555c21dee17SSøren Schmidt static int 556b40ce416SJulian Elischer linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 557c21dee17SSøren Schmidt { 558c21dee17SSøren Schmidt struct linux_getpeername_args linux_args; 559044af7c3SJonathan Mini struct ogetpeername_args /* { 560c21dee17SSøren Schmidt int fdes; 561c21dee17SSøren Schmidt caddr_t asa; 562c21dee17SSøren Schmidt int *alen; 563ef04503dSPeter Wemm } */ bsd_args; 564c21dee17SSøren Schmidt int error; 565c21dee17SSøren Schmidt 5663f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5673f3a4815SMarcel Moolenaar return (error); 5683f3a4815SMarcel Moolenaar 569c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 570c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 571c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 572044af7c3SJonathan Mini return (ogetpeername(td, &bsd_args)); 573c21dee17SSøren Schmidt } 574c21dee17SSøren Schmidt 575c21dee17SSøren Schmidt struct linux_socketpair_args { 576c21dee17SSøren Schmidt int domain; 577c21dee17SSøren Schmidt int type; 578c21dee17SSøren Schmidt int protocol; 579c21dee17SSøren Schmidt int *rsv; 580c21dee17SSøren Schmidt }; 581c21dee17SSøren Schmidt 582c21dee17SSøren Schmidt static int 583b40ce416SJulian Elischer linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 584c21dee17SSøren Schmidt { 585c21dee17SSøren Schmidt struct linux_socketpair_args linux_args; 586ef04503dSPeter Wemm struct socketpair_args /* { 587c21dee17SSøren Schmidt int domain; 588c21dee17SSøren Schmidt int type; 589c21dee17SSøren Schmidt int protocol; 590c21dee17SSøren Schmidt int *rsv; 591ef04503dSPeter Wemm } */ bsd_args; 592c21dee17SSøren Schmidt int error; 593c21dee17SSøren Schmidt 5943f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5953f3a4815SMarcel Moolenaar return (error); 5963f3a4815SMarcel Moolenaar 597c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 598c21dee17SSøren Schmidt if (bsd_args.domain == -1) 5993f3a4815SMarcel Moolenaar return (EINVAL); 6003f3a4815SMarcel Moolenaar 601c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 602c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 603c21dee17SSøren Schmidt bsd_args.rsv = linux_args.rsv; 604b40ce416SJulian Elischer return (socketpair(td, &bsd_args)); 605c21dee17SSøren Schmidt } 606c21dee17SSøren Schmidt 607c21dee17SSøren Schmidt struct linux_send_args { 608c21dee17SSøren Schmidt int s; 609c21dee17SSøren Schmidt void *msg; 610c21dee17SSøren Schmidt int len; 611c21dee17SSøren Schmidt int flags; 612c21dee17SSøren Schmidt }; 613c21dee17SSøren Schmidt 614c21dee17SSøren Schmidt static int 615b40ce416SJulian Elischer linux_send(struct thread *td, struct linux_send_args *args) 616c21dee17SSøren Schmidt { 617c21dee17SSøren Schmidt struct linux_send_args linux_args; 618044af7c3SJonathan Mini struct osend_args /* { 619c21dee17SSøren Schmidt int s; 620c21dee17SSøren Schmidt caddr_t buf; 621044af7c3SJonathan Mini int len; 622c21dee17SSøren Schmidt int flags; 623ef04503dSPeter Wemm } */ bsd_args; 624c21dee17SSøren Schmidt int error; 625c21dee17SSøren Schmidt 6263f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6273f3a4815SMarcel Moolenaar return (error); 6283f3a4815SMarcel Moolenaar 629c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 630c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 631c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 632c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 633044af7c3SJonathan Mini return (osend(td, &bsd_args)); 634c21dee17SSøren Schmidt } 635c21dee17SSøren Schmidt 636c21dee17SSøren Schmidt struct linux_recv_args { 637c21dee17SSøren Schmidt int s; 638c21dee17SSøren Schmidt void *msg; 639c21dee17SSøren Schmidt int len; 640c21dee17SSøren Schmidt int flags; 641c21dee17SSøren Schmidt }; 642c21dee17SSøren Schmidt 643c21dee17SSøren Schmidt static int 644b40ce416SJulian Elischer linux_recv(struct thread *td, struct linux_recv_args *args) 645c21dee17SSøren Schmidt { 646c21dee17SSøren Schmidt struct linux_recv_args linux_args; 647044af7c3SJonathan Mini struct orecv_args /* { 648c21dee17SSøren Schmidt int s; 649c21dee17SSøren Schmidt caddr_t buf; 650c21dee17SSøren Schmidt int len; 651c21dee17SSøren Schmidt int flags; 652ef04503dSPeter Wemm } */ bsd_args; 653c21dee17SSøren Schmidt int error; 654c21dee17SSøren Schmidt 6553f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6563f3a4815SMarcel Moolenaar return (error); 6573f3a4815SMarcel Moolenaar 658c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 659c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 660c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 661c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 662044af7c3SJonathan Mini return (orecv(td, &bsd_args)); 663c21dee17SSøren Schmidt } 664c21dee17SSøren Schmidt 665c21dee17SSøren Schmidt struct linux_sendto_args { 666c21dee17SSøren Schmidt int s; 667c21dee17SSøren Schmidt void *msg; 668c21dee17SSøren Schmidt int len; 669c21dee17SSøren Schmidt int flags; 670c21dee17SSøren Schmidt caddr_t to; 671c21dee17SSøren Schmidt int tolen; 672c21dee17SSøren Schmidt }; 673c21dee17SSøren Schmidt 674c21dee17SSøren Schmidt static int 675b40ce416SJulian Elischer linux_sendto(struct thread *td, struct linux_sendto_args *args) 676c21dee17SSøren Schmidt { 677c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 678ef04503dSPeter Wemm struct sendto_args /* { 679c21dee17SSøren Schmidt int s; 680c21dee17SSøren Schmidt caddr_t buf; 681c21dee17SSøren Schmidt size_t len; 682c21dee17SSøren Schmidt int flags; 683c21dee17SSøren Schmidt caddr_t to; 684c21dee17SSøren Schmidt int tolen; 685ef04503dSPeter Wemm } */ bsd_args; 686c21dee17SSøren Schmidt int error; 687c21dee17SSøren Schmidt 6883f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6893f3a4815SMarcel Moolenaar return (error); 6903f3a4815SMarcel Moolenaar 691c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 692c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 693c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 694c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 695c21dee17SSøren Schmidt bsd_args.to = linux_args.to; 696c21dee17SSøren Schmidt bsd_args.tolen = linux_args.tolen; 697f2477ae1SMike Smith 698b40ce416SJulian Elischer if (linux_check_hdrincl(td, linux_args.s) == 0) 699f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 700b40ce416SJulian Elischer return (linux_sendto_hdrincl(td, &bsd_args)); 701f2477ae1SMike Smith 702b40ce416SJulian Elischer return (sendto(td, &bsd_args)); 703c21dee17SSøren Schmidt } 704c21dee17SSøren Schmidt 705c21dee17SSøren Schmidt struct linux_recvfrom_args { 706c21dee17SSøren Schmidt int s; 707c21dee17SSøren Schmidt void *buf; 708c21dee17SSøren Schmidt int len; 709c21dee17SSøren Schmidt int flags; 710c21dee17SSøren Schmidt caddr_t from; 711c21dee17SSøren Schmidt int *fromlen; 712c21dee17SSøren Schmidt }; 713c21dee17SSøren Schmidt 714c21dee17SSøren Schmidt static int 715b40ce416SJulian Elischer linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 716c21dee17SSøren Schmidt { 717c21dee17SSøren Schmidt struct linux_recvfrom_args linux_args; 718ef04503dSPeter Wemm struct recvfrom_args /* { 719c21dee17SSøren Schmidt int s; 720c21dee17SSøren Schmidt caddr_t buf; 721c21dee17SSøren Schmidt size_t len; 722c21dee17SSøren Schmidt int flags; 723c21dee17SSøren Schmidt caddr_t from; 724c21dee17SSøren Schmidt int *fromlenaddr; 725ef04503dSPeter Wemm } */ bsd_args; 726c21dee17SSøren Schmidt int error; 727c21dee17SSøren Schmidt 7283f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7293f3a4815SMarcel Moolenaar return (error); 7303f3a4815SMarcel Moolenaar 731c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 732c21dee17SSøren Schmidt bsd_args.buf = linux_args.buf; 733c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 73440dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 735c21dee17SSøren Schmidt bsd_args.from = linux_args.from; 736c21dee17SSøren Schmidt bsd_args.fromlenaddr = linux_args.fromlen; 737044af7c3SJonathan Mini return (orecvfrom(td, &bsd_args)); 738c21dee17SSøren Schmidt } 739c21dee17SSøren Schmidt 74040dbba57SAssar Westerlund struct linux_recvmsg_args { 74140dbba57SAssar Westerlund int s; 74240dbba57SAssar Westerlund struct msghdr *msg; 74340dbba57SAssar Westerlund int flags; 74440dbba57SAssar Westerlund }; 74540dbba57SAssar Westerlund 74640dbba57SAssar Westerlund static int 747b40ce416SJulian Elischer linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 74840dbba57SAssar Westerlund { 74940dbba57SAssar Westerlund struct linux_recvmsg_args linux_args; 75040dbba57SAssar Westerlund struct recvmsg_args /* { 75140dbba57SAssar Westerlund int s; 75240dbba57SAssar Westerlund struct msghdr *msg; 75340dbba57SAssar Westerlund int flags; 75440dbba57SAssar Westerlund } */ bsd_args; 75540dbba57SAssar Westerlund int error; 75640dbba57SAssar Westerlund 75740dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 75840dbba57SAssar Westerlund return (error); 75940dbba57SAssar Westerlund 76040dbba57SAssar Westerlund bsd_args.s = linux_args.s; 76140dbba57SAssar Westerlund bsd_args.msg = linux_args.msg; 76240dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 763b40ce416SJulian Elischer return (recvmsg(td, &bsd_args)); 76440dbba57SAssar Westerlund } 76540dbba57SAssar Westerlund 766c21dee17SSøren Schmidt struct linux_shutdown_args { 767c21dee17SSøren Schmidt int s; 768c21dee17SSøren Schmidt int how; 769c21dee17SSøren Schmidt }; 770c21dee17SSøren Schmidt 771c21dee17SSøren Schmidt static int 772b40ce416SJulian Elischer linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 773c21dee17SSøren Schmidt { 774c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 775ef04503dSPeter Wemm struct shutdown_args /* { 776c21dee17SSøren Schmidt int s; 777c21dee17SSøren Schmidt int how; 778ef04503dSPeter Wemm } */ bsd_args; 779c21dee17SSøren Schmidt int error; 780c21dee17SSøren Schmidt 7813f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7823f3a4815SMarcel Moolenaar return (error); 7833f3a4815SMarcel Moolenaar 784c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 785c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 786b40ce416SJulian Elischer return (shutdown(td, &bsd_args)); 787c21dee17SSøren Schmidt } 788c21dee17SSøren Schmidt 789c21dee17SSøren Schmidt struct linux_setsockopt_args { 790c21dee17SSøren Schmidt int s; 791c21dee17SSøren Schmidt int level; 792c21dee17SSøren Schmidt int optname; 793c21dee17SSøren Schmidt void *optval; 794c21dee17SSøren Schmidt int optlen; 795c21dee17SSøren Schmidt }; 796c21dee17SSøren Schmidt 797c21dee17SSøren Schmidt static int 798b40ce416SJulian Elischer linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 799c21dee17SSøren Schmidt { 800c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 801ef04503dSPeter Wemm struct setsockopt_args /* { 802c21dee17SSøren Schmidt int s; 803c21dee17SSøren Schmidt int level; 804c21dee17SSøren Schmidt int name; 805c21dee17SSøren Schmidt caddr_t val; 806c21dee17SSøren Schmidt int valsize; 807ef04503dSPeter Wemm } */ bsd_args; 808c21dee17SSøren Schmidt int error, name; 809c21dee17SSøren Schmidt 8103f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8113f3a4815SMarcel Moolenaar return (error); 8123f3a4815SMarcel Moolenaar 813c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 814c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 815c21dee17SSøren Schmidt switch (bsd_args.level) { 816c21dee17SSøren Schmidt case SOL_SOCKET: 817c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 818c21dee17SSøren Schmidt break; 819c21dee17SSøren Schmidt case IPPROTO_IP: 820c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 821c21dee17SSøren Schmidt break; 822dad3b88aSMike Smith case IPPROTO_TCP: 823dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 824dad3b88aSMike Smith name = linux_args.optname; 825dad3b88aSMike Smith break; 826c21dee17SSøren Schmidt default: 8273f3a4815SMarcel Moolenaar name = -1; 8283f3a4815SMarcel Moolenaar break; 829c21dee17SSøren Schmidt } 830c21dee17SSøren Schmidt if (name == -1) 8313f3a4815SMarcel Moolenaar return (EINVAL); 8323f3a4815SMarcel Moolenaar 833c21dee17SSøren Schmidt bsd_args.name = name; 834c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 835c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 836b40ce416SJulian Elischer return (setsockopt(td, &bsd_args)); 837c21dee17SSøren Schmidt } 838c21dee17SSøren Schmidt 839c21dee17SSøren Schmidt struct linux_getsockopt_args { 840c21dee17SSøren Schmidt int s; 841c21dee17SSøren Schmidt int level; 842c21dee17SSøren Schmidt int optname; 843c21dee17SSøren Schmidt void *optval; 844c21dee17SSøren Schmidt int *optlen; 845c21dee17SSøren Schmidt }; 846c21dee17SSøren Schmidt 847c21dee17SSøren Schmidt static int 848b40ce416SJulian Elischer linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 849c21dee17SSøren Schmidt { 850c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 851ef04503dSPeter Wemm struct getsockopt_args /* { 852c21dee17SSøren Schmidt int s; 853c21dee17SSøren Schmidt int level; 854c21dee17SSøren Schmidt int name; 855c21dee17SSøren Schmidt caddr_t val; 856c21dee17SSøren Schmidt int *avalsize; 857ef04503dSPeter Wemm } */ bsd_args; 858c21dee17SSøren Schmidt int error, name; 859c21dee17SSøren Schmidt 8603f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8613f3a4815SMarcel Moolenaar return (error); 8623f3a4815SMarcel Moolenaar 863c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 864c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 865c21dee17SSøren Schmidt switch (bsd_args.level) { 866c21dee17SSøren Schmidt case SOL_SOCKET: 867c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 868c21dee17SSøren Schmidt break; 869c21dee17SSøren Schmidt case IPPROTO_IP: 870c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 871c21dee17SSøren Schmidt break; 872dad3b88aSMike Smith case IPPROTO_TCP: 873dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 874dad3b88aSMike Smith name = linux_args.optname; 875dad3b88aSMike Smith break; 876c21dee17SSøren Schmidt default: 8773f3a4815SMarcel Moolenaar name = -1; 8783f3a4815SMarcel Moolenaar break; 879c21dee17SSøren Schmidt } 880c21dee17SSøren Schmidt if (name == -1) 8813f3a4815SMarcel Moolenaar return (EINVAL); 8823f3a4815SMarcel Moolenaar 883f2477ae1SMike Smith bsd_args.name = name; 884c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 885c21dee17SSøren Schmidt bsd_args.avalsize = linux_args.optlen; 886b40ce416SJulian Elischer return (getsockopt(td, &bsd_args)); 887c21dee17SSøren Schmidt } 888c21dee17SSøren Schmidt 889c21dee17SSøren Schmidt int 890b40ce416SJulian Elischer linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 891c21dee17SSøren Schmidt { 8925002a60fSMarcel Moolenaar void *arg = (void *)args->args; 8933f3a4815SMarcel Moolenaar 894c21dee17SSøren Schmidt switch (args->what) { 895c21dee17SSøren Schmidt case LINUX_SOCKET: 896b40ce416SJulian Elischer return (linux_socket(td, arg)); 897c21dee17SSøren Schmidt case LINUX_BIND: 898b40ce416SJulian Elischer return (linux_bind(td, arg)); 899c21dee17SSøren Schmidt case LINUX_CONNECT: 900b40ce416SJulian Elischer return (linux_connect(td, arg)); 901c21dee17SSøren Schmidt case LINUX_LISTEN: 902b40ce416SJulian Elischer return (linux_listen(td, arg)); 903c21dee17SSøren Schmidt case LINUX_ACCEPT: 904b40ce416SJulian Elischer return (linux_accept(td, arg)); 905c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 906b40ce416SJulian Elischer return (linux_getsockname(td, arg)); 907c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 908b40ce416SJulian Elischer return (linux_getpeername(td, arg)); 909c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 910b40ce416SJulian Elischer return (linux_socketpair(td, arg)); 911c21dee17SSøren Schmidt case LINUX_SEND: 912b40ce416SJulian Elischer return (linux_send(td, arg)); 913c21dee17SSøren Schmidt case LINUX_RECV: 914b40ce416SJulian Elischer return (linux_recv(td, arg)); 915c21dee17SSøren Schmidt case LINUX_SENDTO: 916b40ce416SJulian Elischer return (linux_sendto(td, arg)); 917c21dee17SSøren Schmidt case LINUX_RECVFROM: 918b40ce416SJulian Elischer return (linux_recvfrom(td, arg)); 919c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 920b40ce416SJulian Elischer return (linux_shutdown(td, arg)); 921c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 922b40ce416SJulian Elischer return (linux_setsockopt(td, arg)); 923c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 924b40ce416SJulian Elischer return (linux_getsockopt(td, arg)); 925e76bba09SSøren Schmidt case LINUX_SENDMSG: 926096d55fcSMike Smith do { 927096d55fcSMike Smith int error; 928096d55fcSMike Smith int level; 929096d55fcSMike Smith caddr_t control; 930096d55fcSMike Smith struct { 931096d55fcSMike Smith int s; 932096d55fcSMike Smith const struct msghdr *msg; 933096d55fcSMike Smith int flags; 9345002a60fSMarcel Moolenaar } *uap = arg; 935096d55fcSMike Smith 9363f3a4815SMarcel Moolenaar error = copyin(&uap->msg->msg_control, &control, 9373f3a4815SMarcel Moolenaar sizeof(caddr_t)); 938096d55fcSMike Smith if (error) 9393f3a4815SMarcel Moolenaar return (error); 9403f3a4815SMarcel Moolenaar 941096d55fcSMike Smith if (control == NULL) 942096d55fcSMike Smith goto done; 9433f3a4815SMarcel Moolenaar 944096d55fcSMike Smith error = copyin(&((struct cmsghdr*)control)->cmsg_level, 945096d55fcSMike Smith &level, sizeof(int)); 946096d55fcSMike Smith if (error) 9473f3a4815SMarcel Moolenaar return (error); 9483f3a4815SMarcel Moolenaar 949096d55fcSMike Smith if (level == 1) { 950096d55fcSMike Smith /* 9513f3a4815SMarcel Moolenaar * Linux thinks that SOL_SOCKET is 1; we know 9523f3a4815SMarcel Moolenaar * that it's really 0xffff, of course. 953096d55fcSMike Smith */ 954096d55fcSMike Smith level = SOL_SOCKET; 9553f3a4815SMarcel Moolenaar error = copyout(&level, 9563f3a4815SMarcel Moolenaar &((struct cmsghdr *)control)->cmsg_level, 9573f3a4815SMarcel Moolenaar sizeof(int)); 958096d55fcSMike Smith if (error) 9593f3a4815SMarcel Moolenaar return (error); 960096d55fcSMike Smith } 961096d55fcSMike Smith done: 962b40ce416SJulian Elischer return (sendmsg(td, arg)); 963096d55fcSMike Smith } while (0); 964e76bba09SSøren Schmidt case LINUX_RECVMSG: 965b40ce416SJulian Elischer return (linux_recvmsg(td, arg)); 966c21dee17SSøren Schmidt } 9673f3a4815SMarcel Moolenaar 9683f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 9693f3a4815SMarcel Moolenaar return (ENOSYS); 970c21dee17SSøren Schmidt } 9715231fb20SDavid E. O'Brien #endif /*!__alpha__*/ 972