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 */ 28c21dee17SSøren Schmidt 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3016dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 321f3dad5aSBruce Evans /* XXX we use functions that might not exist. */ 335591b823SEivind Eklund #include "opt_compat.h" 34ca26842eSHajimu UMEMOTO #include "opt_inet6.h" 355591b823SEivind Eklund 365591b823SEivind Eklund #ifndef COMPAT_43 375591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 385591b823SEivind Eklund #endif 391f3dad5aSBruce Evans 40c21dee17SSøren Schmidt #include <sys/param.h> 41f2477ae1SMike Smith #include <sys/proc.h> 42c21dee17SSøren Schmidt #include <sys/systm.h> 431f3dad5aSBruce Evans #include <sys/sysproto.h> 44dad3b88aSMike Smith #include <sys/fcntl.h> 450bf301c0SJonathan Lemon #include <sys/file.h> 46104a9b7eSAlexander Kabaev #include <sys/limits.h> 47ca26842eSHajimu UMEMOTO #include <sys/malloc.h> 48c21dee17SSøren Schmidt #include <sys/socket.h> 490bf301c0SJonathan Lemon #include <sys/socketvar.h> 50ca26842eSHajimu UMEMOTO #include <sys/syscallsubr.h> 5108637435SBruce Evans #include <sys/uio.h> 52ca26842eSHajimu UMEMOTO #include <sys/syslog.h> 531f3dad5aSBruce Evans 54c21dee17SSøren Schmidt #include <netinet/in.h> 55f2477ae1SMike Smith #include <netinet/in_systm.h> 56f2477ae1SMike Smith #include <netinet/ip.h> 57ca26842eSHajimu UMEMOTO #ifdef INET6 58ca26842eSHajimu UMEMOTO #include <netinet/ip6.h> 59ca26842eSHajimu UMEMOTO #include <netinet6/ip6_var.h> 60ca26842eSHajimu UMEMOTO #endif 61c21dee17SSøren Schmidt 62ac951e62SMarcel Moolenaar #include <machine/../linux/linux.h> 63ebea8660SMarcel Moolenaar #include <machine/../linux/linux_proto.h> 6440dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 65ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 66c21dee17SSøren Schmidt 67ca26842eSHajimu UMEMOTO static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *, 68ca26842eSHajimu UMEMOTO struct malloc_type *); 69ca26842eSHajimu UMEMOTO static int linux_to_bsd_domain(int); 70ca26842eSHajimu UMEMOTO 714730796cSBill Fenner /* 72ca26842eSHajimu UMEMOTO * Reads a linux sockaddr and does any necessary translation. 73ca26842eSHajimu UMEMOTO * Linux sockaddrs don't have a length field, only a family. 744730796cSBill Fenner */ 754730796cSBill Fenner static int 76ca26842eSHajimu UMEMOTO linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int len) 774730796cSBill Fenner { 78ca26842eSHajimu UMEMOTO int osalen = len; 794730796cSBill Fenner 80ca26842eSHajimu UMEMOTO return (do_sa_get(sap, osa, &osalen, M_SONAME)); 814730796cSBill Fenner } 824730796cSBill Fenner 83ca26842eSHajimu UMEMOTO /* 84ca26842eSHajimu UMEMOTO * Copy the osockaddr structure pointed to by osa to kernel, adjust 85ca26842eSHajimu UMEMOTO * family and convert to sockaddr. 86ca26842eSHajimu UMEMOTO */ 87ca26842eSHajimu UMEMOTO static int 88ca26842eSHajimu UMEMOTO do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, 89ca26842eSHajimu UMEMOTO struct malloc_type *mtype) 90ca26842eSHajimu UMEMOTO { 91ca26842eSHajimu UMEMOTO int error=0, bdom; 92ca26842eSHajimu UMEMOTO struct sockaddr *sa; 93ca26842eSHajimu UMEMOTO struct osockaddr *kosa; 94ca26842eSHajimu UMEMOTO int alloclen; 95ca26842eSHajimu UMEMOTO #ifdef INET6 96ca26842eSHajimu UMEMOTO int oldv6size; 97ca26842eSHajimu UMEMOTO struct sockaddr_in6 *sin6; 98ca26842eSHajimu UMEMOTO #endif 99ca26842eSHajimu UMEMOTO 100ca26842eSHajimu UMEMOTO if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) 101ca26842eSHajimu UMEMOTO return (EINVAL); 102ca26842eSHajimu UMEMOTO 103ca26842eSHajimu UMEMOTO alloclen = *osalen; 104ca26842eSHajimu UMEMOTO #ifdef INET6 105ca26842eSHajimu UMEMOTO oldv6size = 0; 106ca26842eSHajimu UMEMOTO /* 107ca26842eSHajimu UMEMOTO * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 108ca26842eSHajimu UMEMOTO * if it's a v4-mapped address, so reserve the proper space 109ca26842eSHajimu UMEMOTO * for it. 110ca26842eSHajimu UMEMOTO */ 111ca26842eSHajimu UMEMOTO if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { 112ca26842eSHajimu UMEMOTO alloclen = sizeof (struct sockaddr_in6); 113ca26842eSHajimu UMEMOTO oldv6size = 1; 114ca26842eSHajimu UMEMOTO } 115ca26842eSHajimu UMEMOTO #endif 116ca26842eSHajimu UMEMOTO 1175b13e781SHajimu UMEMOTO MALLOC(kosa, struct osockaddr *, alloclen, mtype, M_WAITOK); 118ca26842eSHajimu UMEMOTO 1194b7ef73dSDag-Erling Smørgrav if ((error = copyin(osa, kosa, *osalen))) 120ca26842eSHajimu UMEMOTO goto out; 121ca26842eSHajimu UMEMOTO 122ca26842eSHajimu UMEMOTO bdom = linux_to_bsd_domain(kosa->sa_family); 123ca26842eSHajimu UMEMOTO if (bdom == -1) { 124ca26842eSHajimu UMEMOTO error = EINVAL; 125ca26842eSHajimu UMEMOTO goto out; 126ca26842eSHajimu UMEMOTO } 127ca26842eSHajimu UMEMOTO 128ca26842eSHajimu UMEMOTO #ifdef INET6 129ca26842eSHajimu UMEMOTO /* 130ca26842eSHajimu UMEMOTO * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 131ca26842eSHajimu UMEMOTO * which lacks the scope id compared with RFC2553 one. If we detect 132ca26842eSHajimu UMEMOTO * the situation, reject the address and write a message to system log. 133ca26842eSHajimu UMEMOTO * 134ca26842eSHajimu UMEMOTO * Still accept addresses for which the scope id is not used. 135ca26842eSHajimu UMEMOTO */ 136ca26842eSHajimu UMEMOTO if (oldv6size && bdom == AF_INET6) { 137ca26842eSHajimu UMEMOTO sin6 = (struct sockaddr_in6 *)kosa; 138ca26842eSHajimu UMEMOTO if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 139ca26842eSHajimu UMEMOTO (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 140ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 141ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 142ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 143ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 144ca26842eSHajimu UMEMOTO sin6->sin6_scope_id = 0; 145ca26842eSHajimu UMEMOTO } else { 146ca26842eSHajimu UMEMOTO log(LOG_DEBUG, 147ca26842eSHajimu UMEMOTO "obsolete pre-RFC2553 sockaddr_in6 rejected"); 148ca26842eSHajimu UMEMOTO error = EINVAL; 149ca26842eSHajimu UMEMOTO goto out; 150ca26842eSHajimu UMEMOTO } 151ca26842eSHajimu UMEMOTO } else 152ca26842eSHajimu UMEMOTO #endif 153ca26842eSHajimu UMEMOTO if (bdom == AF_INET) 154ca26842eSHajimu UMEMOTO alloclen = sizeof(struct sockaddr_in); 155ca26842eSHajimu UMEMOTO 156ca26842eSHajimu UMEMOTO sa = (struct sockaddr *) kosa; 157ca26842eSHajimu UMEMOTO sa->sa_family = bdom; 158ca26842eSHajimu UMEMOTO sa->sa_len = alloclen; 159ca26842eSHajimu UMEMOTO 160ca26842eSHajimu UMEMOTO *sap = sa; 161ca26842eSHajimu UMEMOTO *osalen = alloclen; 162ca26842eSHajimu UMEMOTO return (0); 163ca26842eSHajimu UMEMOTO 164ca26842eSHajimu UMEMOTO out: 165ca26842eSHajimu UMEMOTO FREE(kosa, mtype); 166ca26842eSHajimu UMEMOTO return (error); 167ca26842eSHajimu UMEMOTO } 168ca26842eSHajimu UMEMOTO 169c21dee17SSøren Schmidt static int 170c21dee17SSøren Schmidt linux_to_bsd_domain(int domain) 171c21dee17SSøren Schmidt { 1723f3a4815SMarcel Moolenaar 173c21dee17SSøren Schmidt switch (domain) { 174c21dee17SSøren Schmidt case LINUX_AF_UNSPEC: 1753f3a4815SMarcel Moolenaar return (AF_UNSPEC); 176c21dee17SSøren Schmidt case LINUX_AF_UNIX: 1773f3a4815SMarcel Moolenaar return (AF_LOCAL); 178c21dee17SSøren Schmidt case LINUX_AF_INET: 1793f3a4815SMarcel Moolenaar return (AF_INET); 180ca26842eSHajimu UMEMOTO case LINUX_AF_INET6: 181ca26842eSHajimu UMEMOTO return (AF_INET6); 182c21dee17SSøren Schmidt case LINUX_AF_AX25: 1833f3a4815SMarcel Moolenaar return (AF_CCITT); 184c21dee17SSøren Schmidt case LINUX_AF_IPX: 1853f3a4815SMarcel Moolenaar return (AF_IPX); 186c21dee17SSøren Schmidt case LINUX_AF_APPLETALK: 1873f3a4815SMarcel Moolenaar return (AF_APPLETALK); 188c21dee17SSøren Schmidt } 1893f3a4815SMarcel Moolenaar return (-1); 190c21dee17SSøren Schmidt } 191c21dee17SSøren Schmidt 192ca26842eSHajimu UMEMOTO #ifndef __alpha__ 193ca26842eSHajimu UMEMOTO static int 194ca26842eSHajimu UMEMOTO bsd_to_linux_domain(int domain) 195ca26842eSHajimu UMEMOTO { 196ca26842eSHajimu UMEMOTO 197ca26842eSHajimu UMEMOTO switch (domain) { 198ca26842eSHajimu UMEMOTO case AF_UNSPEC: 199ca26842eSHajimu UMEMOTO return (LINUX_AF_UNSPEC); 200ca26842eSHajimu UMEMOTO case AF_LOCAL: 201ca26842eSHajimu UMEMOTO return (LINUX_AF_UNIX); 202ca26842eSHajimu UMEMOTO case AF_INET: 203ca26842eSHajimu UMEMOTO return (LINUX_AF_INET); 204ca26842eSHajimu UMEMOTO case AF_INET6: 205ca26842eSHajimu UMEMOTO return (LINUX_AF_INET6); 206ca26842eSHajimu UMEMOTO case AF_CCITT: 207ca26842eSHajimu UMEMOTO return (LINUX_AF_AX25); 208ca26842eSHajimu UMEMOTO case AF_IPX: 209ca26842eSHajimu UMEMOTO return (LINUX_AF_IPX); 210ca26842eSHajimu UMEMOTO case AF_APPLETALK: 211ca26842eSHajimu UMEMOTO return (LINUX_AF_APPLETALK); 212ca26842eSHajimu UMEMOTO } 213ca26842eSHajimu UMEMOTO return (-1); 214ca26842eSHajimu UMEMOTO } 215ca26842eSHajimu UMEMOTO 216c21dee17SSøren Schmidt static int 217c21dee17SSøren Schmidt linux_to_bsd_sockopt_level(int level) 218c21dee17SSøren Schmidt { 2193f3a4815SMarcel Moolenaar 220c21dee17SSøren Schmidt switch (level) { 221c21dee17SSøren Schmidt case LINUX_SOL_SOCKET: 2223f3a4815SMarcel Moolenaar return (SOL_SOCKET); 223c21dee17SSøren Schmidt } 2243f3a4815SMarcel Moolenaar return (level); 225c21dee17SSøren Schmidt } 226c21dee17SSøren Schmidt 2273f3a4815SMarcel Moolenaar static int 2283f3a4815SMarcel Moolenaar linux_to_bsd_ip_sockopt(int opt) 229c21dee17SSøren Schmidt { 2303f3a4815SMarcel Moolenaar 231c21dee17SSøren Schmidt switch (opt) { 232c21dee17SSøren Schmidt case LINUX_IP_TOS: 2333f3a4815SMarcel Moolenaar return (IP_TOS); 234c21dee17SSøren Schmidt case LINUX_IP_TTL: 2353f3a4815SMarcel Moolenaar return (IP_TTL); 23666ff6a3cSBill Fenner case LINUX_IP_OPTIONS: 2373f3a4815SMarcel Moolenaar return (IP_OPTIONS); 23866ff6a3cSBill Fenner case LINUX_IP_MULTICAST_IF: 2393f3a4815SMarcel Moolenaar return (IP_MULTICAST_IF); 24066ff6a3cSBill Fenner case LINUX_IP_MULTICAST_TTL: 2413f3a4815SMarcel Moolenaar return (IP_MULTICAST_TTL); 24266ff6a3cSBill Fenner case LINUX_IP_MULTICAST_LOOP: 2433f3a4815SMarcel Moolenaar return (IP_MULTICAST_LOOP); 24466ff6a3cSBill Fenner case LINUX_IP_ADD_MEMBERSHIP: 2453f3a4815SMarcel Moolenaar return (IP_ADD_MEMBERSHIP); 24666ff6a3cSBill Fenner case LINUX_IP_DROP_MEMBERSHIP: 2473f3a4815SMarcel Moolenaar return (IP_DROP_MEMBERSHIP); 24866ff6a3cSBill Fenner case LINUX_IP_HDRINCL: 2493f3a4815SMarcel Moolenaar return (IP_HDRINCL); 250c21dee17SSøren Schmidt } 2513f3a4815SMarcel Moolenaar return (-1); 252c21dee17SSøren Schmidt } 253c21dee17SSøren Schmidt 254c21dee17SSøren Schmidt static int 255c21dee17SSøren Schmidt linux_to_bsd_so_sockopt(int opt) 256c21dee17SSøren Schmidt { 2573f3a4815SMarcel Moolenaar 258c21dee17SSøren Schmidt switch (opt) { 259c21dee17SSøren Schmidt case LINUX_SO_DEBUG: 2603f3a4815SMarcel Moolenaar return (SO_DEBUG); 261c21dee17SSøren Schmidt case LINUX_SO_REUSEADDR: 2623f3a4815SMarcel Moolenaar return (SO_REUSEADDR); 263c21dee17SSøren Schmidt case LINUX_SO_TYPE: 2643f3a4815SMarcel Moolenaar return (SO_TYPE); 265c21dee17SSøren Schmidt case LINUX_SO_ERROR: 2663f3a4815SMarcel Moolenaar return (SO_ERROR); 267c21dee17SSøren Schmidt case LINUX_SO_DONTROUTE: 2683f3a4815SMarcel Moolenaar return (SO_DONTROUTE); 269c21dee17SSøren Schmidt case LINUX_SO_BROADCAST: 2703f3a4815SMarcel Moolenaar return (SO_BROADCAST); 271c21dee17SSøren Schmidt case LINUX_SO_SNDBUF: 2723f3a4815SMarcel Moolenaar return (SO_SNDBUF); 273c21dee17SSøren Schmidt case LINUX_SO_RCVBUF: 2743f3a4815SMarcel Moolenaar return (SO_RCVBUF); 275c21dee17SSøren Schmidt case LINUX_SO_KEEPALIVE: 2763f3a4815SMarcel Moolenaar return (SO_KEEPALIVE); 277c21dee17SSøren Schmidt case LINUX_SO_OOBINLINE: 2783f3a4815SMarcel Moolenaar return (SO_OOBINLINE); 279c21dee17SSøren Schmidt case LINUX_SO_LINGER: 2803f3a4815SMarcel Moolenaar return (SO_LINGER); 281c21dee17SSøren Schmidt } 2823f3a4815SMarcel Moolenaar return (-1); 283c21dee17SSøren Schmidt } 284c21dee17SSøren Schmidt 28540dbba57SAssar Westerlund static int 28640dbba57SAssar Westerlund linux_to_bsd_msg_flags(int flags) 28740dbba57SAssar Westerlund { 28840dbba57SAssar Westerlund int ret_flags = 0; 28940dbba57SAssar Westerlund 29040dbba57SAssar Westerlund if (flags & LINUX_MSG_OOB) 29140dbba57SAssar Westerlund ret_flags |= MSG_OOB; 29240dbba57SAssar Westerlund if (flags & LINUX_MSG_PEEK) 29340dbba57SAssar Westerlund ret_flags |= MSG_PEEK; 29440dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTROUTE) 29540dbba57SAssar Westerlund ret_flags |= MSG_DONTROUTE; 29640dbba57SAssar Westerlund if (flags & LINUX_MSG_CTRUNC) 29740dbba57SAssar Westerlund ret_flags |= MSG_CTRUNC; 29840dbba57SAssar Westerlund if (flags & LINUX_MSG_TRUNC) 29940dbba57SAssar Westerlund ret_flags |= MSG_TRUNC; 30040dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTWAIT) 30140dbba57SAssar Westerlund ret_flags |= MSG_DONTWAIT; 30240dbba57SAssar Westerlund if (flags & LINUX_MSG_EOR) 30340dbba57SAssar Westerlund ret_flags |= MSG_EOR; 30440dbba57SAssar Westerlund if (flags & LINUX_MSG_WAITALL) 30540dbba57SAssar Westerlund ret_flags |= MSG_WAITALL; 30640dbba57SAssar Westerlund #if 0 /* not handled */ 30740dbba57SAssar Westerlund if (flags & LINUX_MSG_PROXY) 30840dbba57SAssar Westerlund ; 30940dbba57SAssar Westerlund if (flags & LINUX_MSG_FIN) 31040dbba57SAssar Westerlund ; 31140dbba57SAssar Westerlund if (flags & LINUX_MSG_SYN) 31240dbba57SAssar Westerlund ; 31340dbba57SAssar Westerlund if (flags & LINUX_MSG_CONFIRM) 31440dbba57SAssar Westerlund ; 31540dbba57SAssar Westerlund if (flags & LINUX_MSG_RST) 31640dbba57SAssar Westerlund ; 31740dbba57SAssar Westerlund if (flags & LINUX_MSG_ERRQUEUE) 31840dbba57SAssar Westerlund ; 31940dbba57SAssar Westerlund if (flags & LINUX_MSG_NOSIGNAL) 32040dbba57SAssar Westerlund ; 32140dbba57SAssar Westerlund #endif 32240dbba57SAssar Westerlund return ret_flags; 32340dbba57SAssar Westerlund } 32440dbba57SAssar Westerlund 325ca26842eSHajimu UMEMOTO /* 326ca26842eSHajimu UMEMOTO * Allocate stackgap and put the converted sockaddr structure 327ca26842eSHajimu UMEMOTO * there, address on stackgap returned in sap. 328ca26842eSHajimu UMEMOTO */ 329ca26842eSHajimu UMEMOTO static int 330ca26842eSHajimu UMEMOTO linux_sa_get(caddr_t *sgp, struct sockaddr **sap, 331ca26842eSHajimu UMEMOTO const struct osockaddr *osa, int *osalen) 332ca26842eSHajimu UMEMOTO { 333ca26842eSHajimu UMEMOTO struct sockaddr *sa, *usa; 334ca26842eSHajimu UMEMOTO int alloclen, error; 335ca26842eSHajimu UMEMOTO 336ca26842eSHajimu UMEMOTO alloclen = *osalen; 337ca26842eSHajimu UMEMOTO error = do_sa_get(&sa, osa, &alloclen, M_TEMP); 338ca26842eSHajimu UMEMOTO if (error) 339ca26842eSHajimu UMEMOTO return (error); 340ca26842eSHajimu UMEMOTO 341ca26842eSHajimu UMEMOTO usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen); 342ca26842eSHajimu UMEMOTO if (!usa) { 343ca26842eSHajimu UMEMOTO error = ENOMEM; 344ca26842eSHajimu UMEMOTO goto out; 345ca26842eSHajimu UMEMOTO } 346ca26842eSHajimu UMEMOTO 347ca26842eSHajimu UMEMOTO if ((error = copyout(sa, usa, alloclen))) 348ca26842eSHajimu UMEMOTO goto out; 349ca26842eSHajimu UMEMOTO 350ca26842eSHajimu UMEMOTO *sap = usa; 351ca26842eSHajimu UMEMOTO *osalen = alloclen; 352ca26842eSHajimu UMEMOTO 353ca26842eSHajimu UMEMOTO out: 354ca26842eSHajimu UMEMOTO FREE(sa, M_TEMP); 355ca26842eSHajimu UMEMOTO return (error); 356ca26842eSHajimu UMEMOTO } 357ca26842eSHajimu UMEMOTO 358ca26842eSHajimu UMEMOTO static int 359ca26842eSHajimu UMEMOTO linux_sa_put(struct osockaddr *osa) 360ca26842eSHajimu UMEMOTO { 361ca26842eSHajimu UMEMOTO struct osockaddr sa; 362ca26842eSHajimu UMEMOTO int error, bdom; 363ca26842eSHajimu UMEMOTO 364ca26842eSHajimu UMEMOTO /* 365ca26842eSHajimu UMEMOTO * Only read/write the osockaddr family part, the rest is 366ca26842eSHajimu UMEMOTO * not changed. 367ca26842eSHajimu UMEMOTO */ 3684b7ef73dSDag-Erling Smørgrav error = copyin(osa, &sa, sizeof(sa.sa_family)); 369ca26842eSHajimu UMEMOTO if (error) 370ca26842eSHajimu UMEMOTO return (error); 371ca26842eSHajimu UMEMOTO 372ca26842eSHajimu UMEMOTO bdom = bsd_to_linux_domain(sa.sa_family); 373ca26842eSHajimu UMEMOTO if (bdom == -1) 374ca26842eSHajimu UMEMOTO return (EINVAL); 375ca26842eSHajimu UMEMOTO 376ca26842eSHajimu UMEMOTO sa.sa_family = bdom; 377ca26842eSHajimu UMEMOTO error = copyout(&sa, osa, sizeof(sa.sa_family)); 378ca26842eSHajimu UMEMOTO if (error) 379ca26842eSHajimu UMEMOTO return (error); 380ca26842eSHajimu UMEMOTO 381ca26842eSHajimu UMEMOTO return (0); 382ca26842eSHajimu UMEMOTO } 383ca26842eSHajimu UMEMOTO 3843f3a4815SMarcel Moolenaar /* Return 0 if IP_HDRINCL is set for the given socket. */ 385f2477ae1SMike Smith static int 3864d45de74SDavid Malone linux_check_hdrincl(struct thread *td, caddr_t *sg, int s) 387f2477ae1SMike Smith { 388f2477ae1SMike Smith struct getsockopt_args /* { 389f2477ae1SMike Smith int s; 390f2477ae1SMike Smith int level; 391f2477ae1SMike Smith int name; 392f2477ae1SMike Smith caddr_t val; 393f2477ae1SMike Smith int *avalsize; 394f2477ae1SMike Smith } */ bsd_args; 395f2477ae1SMike Smith int error; 3964d45de74SDavid Malone caddr_t val, valsize; 397f2477ae1SMike Smith int size_val = sizeof val; 398f2477ae1SMike Smith int optval; 399f2477ae1SMike Smith 4004d45de74SDavid Malone val = stackgap_alloc(sg, sizeof(int)); 4014d45de74SDavid Malone valsize = stackgap_alloc(sg, sizeof(int)); 402f2477ae1SMike Smith 403f2477ae1SMike Smith if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 4043f3a4815SMarcel Moolenaar return (error); 4053f3a4815SMarcel Moolenaar 406f2477ae1SMike Smith bsd_args.s = s; 407f2477ae1SMike Smith bsd_args.level = IPPROTO_IP; 408f2477ae1SMike Smith bsd_args.name = IP_HDRINCL; 409f2477ae1SMike Smith bsd_args.val = val; 410f2477ae1SMike Smith bsd_args.avalsize = (int *)valsize; 411b40ce416SJulian Elischer if ((error = getsockopt(td, &bsd_args))) 4123f3a4815SMarcel Moolenaar return (error); 4133f3a4815SMarcel Moolenaar 414f2477ae1SMike Smith if ((error = copyin(val, &optval, sizeof(optval)))) 4153f3a4815SMarcel Moolenaar return (error); 4163f3a4815SMarcel Moolenaar 4173f3a4815SMarcel Moolenaar return (optval == 0); 418f2477ae1SMike Smith } 419f2477ae1SMike Smith 420f2477ae1SMike Smith /* 421f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 422f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 423f2477ae1SMike Smith */ 424f2477ae1SMike Smith static int 4254d45de74SDavid Malone linux_sendto_hdrincl(struct thread *td, caddr_t *sg, struct sendto_args *bsd_args) 426f2477ae1SMike Smith { 427f2477ae1SMike Smith /* 428f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 429f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 430f2477ae1SMike Smith * It should include all the fields we modify (ip_len and ip_off) 431f2477ae1SMike Smith * and be as small as possible to minimize copying overhead. 432f2477ae1SMike Smith */ 433f2477ae1SMike Smith #define linux_ip_copysize 8 434f2477ae1SMike Smith 435f2477ae1SMike Smith struct ip *packet; 436f2477ae1SMike Smith struct msghdr *msg; 437f2477ae1SMike Smith struct iovec *iov; 438f2477ae1SMike Smith 439f2477ae1SMike Smith int error; 440f2477ae1SMike Smith struct sendmsg_args /* { 441f2477ae1SMike Smith int s; 442f2477ae1SMike Smith caddr_t msg; 443f2477ae1SMike Smith int flags; 444f2477ae1SMike Smith } */ sendmsg_args; 445f2477ae1SMike Smith 446f2477ae1SMike Smith /* Check the packet isn't too small before we mess with it */ 447f2477ae1SMike Smith if (bsd_args->len < linux_ip_copysize) 4483f3a4815SMarcel Moolenaar return (EINVAL); 449f2477ae1SMike Smith 450f2477ae1SMike Smith /* 451f2477ae1SMike Smith * Tweaking the user buffer in place would be bad manners. 452f2477ae1SMike Smith * We create a corrected IP header with just the needed length, 453f2477ae1SMike Smith * then use an iovec to glue it to the rest of the user packet 454f2477ae1SMike Smith * when calling sendmsg(). 455f2477ae1SMike Smith */ 4564d45de74SDavid Malone packet = (struct ip *)stackgap_alloc(sg, linux_ip_copysize); 4574d45de74SDavid Malone msg = (struct msghdr *)stackgap_alloc(sg, sizeof(*msg)); 4584d45de74SDavid Malone iov = (struct iovec *)stackgap_alloc(sg, sizeof(*iov)*2); 459f2477ae1SMike Smith 460f2477ae1SMike Smith /* Make a copy of the beginning of the packet to be sent */ 4613f3a4815SMarcel Moolenaar if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) 4623f3a4815SMarcel Moolenaar return (error); 463f2477ae1SMike Smith 464f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 465f2477ae1SMike Smith packet->ip_len = bsd_args->len; 466f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 467f2477ae1SMike Smith 468f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 469f2477ae1SMike Smith msg->msg_name = bsd_args->to; 470f2477ae1SMike Smith msg->msg_namelen = bsd_args->tolen; 471f2477ae1SMike Smith msg->msg_iov = iov; 472f2477ae1SMike Smith msg->msg_iovlen = 2; 473f2477ae1SMike Smith msg->msg_control = NULL; 474f2477ae1SMike Smith msg->msg_controllen = 0; 475f2477ae1SMike Smith msg->msg_flags = 0; 476f2477ae1SMike Smith iov[0].iov_base = (char *)packet; 477f2477ae1SMike Smith iov[0].iov_len = linux_ip_copysize; 478f2477ae1SMike Smith iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; 479f2477ae1SMike Smith iov[1].iov_len = bsd_args->len - linux_ip_copysize; 480f2477ae1SMike Smith 481f2477ae1SMike Smith sendmsg_args.s = bsd_args->s; 482f2477ae1SMike Smith sendmsg_args.msg = (caddr_t)msg; 483f2477ae1SMike Smith sendmsg_args.flags = bsd_args->flags; 484b40ce416SJulian Elischer return (sendmsg(td, &sendmsg_args)); 485f2477ae1SMike Smith } 486f2477ae1SMike Smith 487c21dee17SSøren Schmidt struct linux_socket_args { 488c21dee17SSøren Schmidt int domain; 489c21dee17SSøren Schmidt int type; 490c21dee17SSøren Schmidt int protocol; 491c21dee17SSøren Schmidt }; 492c21dee17SSøren Schmidt 493c21dee17SSøren Schmidt static int 494b40ce416SJulian Elischer linux_socket(struct thread *td, struct linux_socket_args *args) 495c21dee17SSøren Schmidt { 496c21dee17SSøren Schmidt struct linux_socket_args linux_args; 497ef04503dSPeter Wemm struct socket_args /* { 498c21dee17SSøren Schmidt int domain; 499c21dee17SSøren Schmidt int type; 500c21dee17SSøren Schmidt int protocol; 501ef04503dSPeter Wemm } */ bsd_args; 502ca26842eSHajimu UMEMOTO struct setsockopt_args /* { 503ca26842eSHajimu UMEMOTO int s; 504ca26842eSHajimu UMEMOTO int level; 505ca26842eSHajimu UMEMOTO int name; 506ca26842eSHajimu UMEMOTO caddr_t val; 507ca26842eSHajimu UMEMOTO int valsize; 508ca26842eSHajimu UMEMOTO } */ bsd_setsockopt_args; 509c21dee17SSøren Schmidt int error; 510f2477ae1SMike Smith int retval_socket; 511c21dee17SSøren Schmidt 5123f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5133f3a4815SMarcel Moolenaar return (error); 5143f3a4815SMarcel Moolenaar 515c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 516c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 517c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 518c21dee17SSøren Schmidt if (bsd_args.domain == -1) 5193f3a4815SMarcel Moolenaar return (EINVAL); 520f2477ae1SMike Smith 521b40ce416SJulian Elischer retval_socket = socket(td, &bsd_args); 522f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 523f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 524f2477ae1SMike Smith && bsd_args.domain == AF_INET 525f2477ae1SMike Smith && retval_socket >= 0) { 526f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 527f2477ae1SMike Smith caddr_t sg; 528f2477ae1SMike Smith int *hdrincl; 529f2477ae1SMike Smith 530f2477ae1SMike Smith sg = stackgap_init(); 531f2477ae1SMike Smith hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 532f2477ae1SMike Smith *hdrincl = 1; 533b40ce416SJulian Elischer bsd_setsockopt_args.s = td->td_retval[0]; 534f2477ae1SMike Smith bsd_setsockopt_args.level = IPPROTO_IP; 535f2477ae1SMike Smith bsd_setsockopt_args.name = IP_HDRINCL; 536f2477ae1SMike Smith bsd_setsockopt_args.val = (caddr_t)hdrincl; 537f2477ae1SMike Smith bsd_setsockopt_args.valsize = sizeof(*hdrincl); 538f2477ae1SMike Smith /* We ignore any error returned by setsockopt() */ 539b40ce416SJulian Elischer setsockopt(td, &bsd_setsockopt_args); 540f2477ae1SMike Smith /* Copy back the return value from socket() */ 541b40ce416SJulian Elischer td->td_retval[0] = bsd_setsockopt_args.s; 542f2477ae1SMike Smith } 543ca26842eSHajimu UMEMOTO #ifdef INET6 544ca26842eSHajimu UMEMOTO /* 545ca26842eSHajimu UMEMOTO * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 546ca26842eSHajimu UMEMOTO * default and some apps depend on this. So, set V6ONLY to 0 547ca26842eSHajimu UMEMOTO * for Linux apps if the sysctl value is set to 1. 548ca26842eSHajimu UMEMOTO */ 54937e7a5a2SHajimu UMEMOTO if (bsd_args.domain == PF_INET6 && retval_socket >= 0 55037e7a5a2SHajimu UMEMOTO #ifndef KLD_MODULE 55137e7a5a2SHajimu UMEMOTO /* 55237e7a5a2SHajimu UMEMOTO * XXX: Avoid undefined symbol error with an IPv4 only 55337e7a5a2SHajimu UMEMOTO * kernel. 55437e7a5a2SHajimu UMEMOTO */ 55537e7a5a2SHajimu UMEMOTO && ip6_v6only 55637e7a5a2SHajimu UMEMOTO #endif 55737e7a5a2SHajimu UMEMOTO ) { 558ca26842eSHajimu UMEMOTO caddr_t sg; 559ca26842eSHajimu UMEMOTO int *v6only; 560ca26842eSHajimu UMEMOTO 561ca26842eSHajimu UMEMOTO sg = stackgap_init(); 562ca26842eSHajimu UMEMOTO v6only = (int *)stackgap_alloc(&sg, sizeof(*v6only)); 563ca26842eSHajimu UMEMOTO *v6only = 0; 564ca26842eSHajimu UMEMOTO bsd_setsockopt_args.s = td->td_retval[0]; 565ca26842eSHajimu UMEMOTO bsd_setsockopt_args.level = IPPROTO_IPV6; 566ca26842eSHajimu UMEMOTO bsd_setsockopt_args.name = IPV6_V6ONLY; 567ca26842eSHajimu UMEMOTO bsd_setsockopt_args.val = (caddr_t)v6only; 568ca26842eSHajimu UMEMOTO bsd_setsockopt_args.valsize = sizeof(*v6only); 569ca26842eSHajimu UMEMOTO /* We ignore any error returned by setsockopt() */ 570ca26842eSHajimu UMEMOTO setsockopt(td, &bsd_setsockopt_args); 571ca26842eSHajimu UMEMOTO /* Copy back the return value from socket() */ 572ca26842eSHajimu UMEMOTO td->td_retval[0] = bsd_setsockopt_args.s; 573ca26842eSHajimu UMEMOTO } 574ca26842eSHajimu UMEMOTO #endif 5753f3a4815SMarcel Moolenaar 5763f3a4815SMarcel Moolenaar return (retval_socket); 577c21dee17SSøren Schmidt } 578c21dee17SSøren Schmidt 579c21dee17SSøren Schmidt struct linux_bind_args { 580c21dee17SSøren Schmidt int s; 581ca26842eSHajimu UMEMOTO struct osockaddr *name; 582c21dee17SSøren Schmidt int namelen; 583c21dee17SSøren Schmidt }; 584c21dee17SSøren Schmidt 585c21dee17SSøren Schmidt static int 586b40ce416SJulian Elischer linux_bind(struct thread *td, struct linux_bind_args *args) 587c21dee17SSøren Schmidt { 588c21dee17SSøren Schmidt struct linux_bind_args linux_args; 589ca26842eSHajimu UMEMOTO struct sockaddr *sa; 590c21dee17SSøren Schmidt int error; 591c21dee17SSøren Schmidt 5923f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5933f3a4815SMarcel Moolenaar return (error); 5943f3a4815SMarcel Moolenaar 595ca26842eSHajimu UMEMOTO error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); 596ca26842eSHajimu UMEMOTO if (error) 597ca26842eSHajimu UMEMOTO return (error); 598ca26842eSHajimu UMEMOTO 599ca26842eSHajimu UMEMOTO return (kern_bind(td, linux_args.s, sa)); 600c21dee17SSøren Schmidt } 601c21dee17SSøren Schmidt 602c21dee17SSøren Schmidt struct linux_connect_args { 603c21dee17SSøren Schmidt int s; 604ca26842eSHajimu UMEMOTO struct osockaddr * name; 605c21dee17SSøren Schmidt int namelen; 606c21dee17SSøren Schmidt }; 607b40ce416SJulian Elischer int linux_connect(struct thread *, struct linux_connect_args *); 608930a65feSAndrew Gallatin #endif /* !__alpha__*/ 609c21dee17SSøren Schmidt 610930a65feSAndrew Gallatin int 611b40ce416SJulian Elischer linux_connect(struct thread *td, struct linux_connect_args *args) 612c21dee17SSøren Schmidt { 613c21dee17SSøren Schmidt struct linux_connect_args linux_args; 6140bf301c0SJonathan Lemon struct socket *so; 615ca26842eSHajimu UMEMOTO struct sockaddr *sa; 61639c95b83SMatthew Dillon u_int fflag; 617c21dee17SSøren Schmidt int error; 618c21dee17SSøren Schmidt 619930a65feSAndrew Gallatin #ifdef __alpha__ 620930a65feSAndrew Gallatin bcopy(args, &linux_args, sizeof(linux_args)); 621930a65feSAndrew Gallatin #else 6223f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6233f3a4815SMarcel Moolenaar return (error); 624930a65feSAndrew Gallatin #endif /* __alpha__ */ 6253f3a4815SMarcel Moolenaar 6264d45de74SDavid Malone error = linux_getsockaddr(&sa, (struct osockaddr *)linux_args.name, 6274d45de74SDavid Malone linux_args.namelen); 628ca26842eSHajimu UMEMOTO if (error) 629ca26842eSHajimu UMEMOTO return (error); 630ca26842eSHajimu UMEMOTO 631ca26842eSHajimu UMEMOTO error = kern_connect(td, linux_args.s, sa); 6320bf301c0SJonathan Lemon if (error != EISCONN) 6330bf301c0SJonathan Lemon return (error); 6340bf301c0SJonathan Lemon 635dad3b88aSMike Smith /* 636dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 637dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 638dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 639dad3b88aSMike Smith */ 64039c95b83SMatthew Dillon if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) 6413f3a4815SMarcel Moolenaar return(error); 6420bf301c0SJonathan Lemon error = EISCONN; 64339c95b83SMatthew Dillon if (fflag & FNONBLOCK) { 6445002a60fSMarcel Moolenaar if (so->so_emuldata == 0) 6450bf301c0SJonathan Lemon error = so->so_error; 6460bf301c0SJonathan Lemon so->so_emuldata = (void *)1; 647dad3b88aSMike Smith } 64839c95b83SMatthew Dillon fputsock(so); 6493f3a4815SMarcel Moolenaar return (error); 650c21dee17SSøren Schmidt } 651c21dee17SSøren Schmidt 652930a65feSAndrew Gallatin #ifndef __alpha__ 653930a65feSAndrew Gallatin 654c21dee17SSøren Schmidt struct linux_listen_args { 655c21dee17SSøren Schmidt int s; 656c21dee17SSøren Schmidt int backlog; 657c21dee17SSøren Schmidt }; 658c21dee17SSøren Schmidt 659c21dee17SSøren Schmidt static int 660b40ce416SJulian Elischer linux_listen(struct thread *td, struct linux_listen_args *args) 661c21dee17SSøren Schmidt { 662c21dee17SSøren Schmidt struct linux_listen_args linux_args; 663ef04503dSPeter Wemm struct listen_args /* { 664c21dee17SSøren Schmidt int s; 665c21dee17SSøren Schmidt int backlog; 666ef04503dSPeter Wemm } */ bsd_args; 667c21dee17SSøren Schmidt int error; 668c21dee17SSøren Schmidt 6693f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6703f3a4815SMarcel Moolenaar return (error); 6713f3a4815SMarcel Moolenaar 672c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 673c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 674b40ce416SJulian Elischer return (listen(td, &bsd_args)); 675c21dee17SSøren Schmidt } 676c21dee17SSøren Schmidt 677c21dee17SSøren Schmidt struct linux_accept_args { 678c21dee17SSøren Schmidt int s; 679ca26842eSHajimu UMEMOTO struct osockaddr *addr; 680c21dee17SSøren Schmidt int *namelen; 681c21dee17SSøren Schmidt }; 682c21dee17SSøren Schmidt 683c21dee17SSøren Schmidt static int 684b40ce416SJulian Elischer linux_accept(struct thread *td, struct linux_accept_args *args) 685c21dee17SSøren Schmidt { 686c21dee17SSøren Schmidt struct linux_accept_args linux_args; 687ef04503dSPeter Wemm struct accept_args /* { 688c21dee17SSøren Schmidt int s; 689c21dee17SSøren Schmidt caddr_t name; 690c21dee17SSøren Schmidt int *anamelen; 691ef04503dSPeter Wemm } */ bsd_args; 692ca26842eSHajimu UMEMOTO struct close_args /* { 693ca26842eSHajimu UMEMOTO int fd; 694ca26842eSHajimu UMEMOTO } */ c_args; 695dba5ab66SMarcel Moolenaar struct fcntl_args /* { 696dba5ab66SMarcel Moolenaar int fd; 697dba5ab66SMarcel Moolenaar int cmd; 698dba5ab66SMarcel Moolenaar long arg; 699dba5ab66SMarcel Moolenaar } */ f_args; 700c21dee17SSøren Schmidt int error; 701c21dee17SSøren Schmidt 7023f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7033f3a4815SMarcel Moolenaar return (error); 7043f3a4815SMarcel Moolenaar 705c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 706c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.addr; 707c21dee17SSøren Schmidt bsd_args.anamelen = linux_args.namelen; 708044af7c3SJonathan Mini error = oaccept(td, &bsd_args); 709dba5ab66SMarcel Moolenaar if (error) 710dba5ab66SMarcel Moolenaar return (error); 711ca26842eSHajimu UMEMOTO if (linux_args.addr) { 712ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 713ca26842eSHajimu UMEMOTO if (error) { 714ca26842eSHajimu UMEMOTO c_args.fd = td->td_retval[0]; 715ca26842eSHajimu UMEMOTO (void)close(td, &c_args); 716ca26842eSHajimu UMEMOTO return (error); 717ca26842eSHajimu UMEMOTO } 718ca26842eSHajimu UMEMOTO } 719dba5ab66SMarcel Moolenaar 720dba5ab66SMarcel Moolenaar /* 721dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 722dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 723dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 724dba5ab66SMarcel Moolenaar */ 725b40ce416SJulian Elischer f_args.fd = td->td_retval[0]; 726dba5ab66SMarcel Moolenaar f_args.cmd = F_SETFL; 727dba5ab66SMarcel Moolenaar f_args.arg = 0; 728b40ce416SJulian Elischer (void)fcntl(td, &f_args); 729b40ce416SJulian Elischer td->td_retval[0] = f_args.fd; 730dba5ab66SMarcel Moolenaar return (0); 731c21dee17SSøren Schmidt } 732c21dee17SSøren Schmidt 733c21dee17SSøren Schmidt struct linux_getsockname_args { 734c21dee17SSøren Schmidt int s; 735ca26842eSHajimu UMEMOTO struct osockaddr *addr; 736c21dee17SSøren Schmidt int *namelen; 737c21dee17SSøren Schmidt }; 738c21dee17SSøren Schmidt 739c21dee17SSøren Schmidt static int 740b40ce416SJulian Elischer linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 741c21dee17SSøren Schmidt { 742c21dee17SSøren Schmidt struct linux_getsockname_args linux_args; 743ef04503dSPeter Wemm struct getsockname_args /* { 744c21dee17SSøren Schmidt int fdes; 745c21dee17SSøren Schmidt caddr_t asa; 746c21dee17SSøren Schmidt int *alen; 747ef04503dSPeter Wemm } */ bsd_args; 748c21dee17SSøren Schmidt int error; 749c21dee17SSøren Schmidt 7503f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7513f3a4815SMarcel Moolenaar return (error); 7523f3a4815SMarcel Moolenaar 753c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 754c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 755c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 756ca26842eSHajimu UMEMOTO error = ogetsockname(td, &bsd_args); 757ca26842eSHajimu UMEMOTO if (error) 758ca26842eSHajimu UMEMOTO return (error); 759ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 760ca26842eSHajimu UMEMOTO if (error) 761ca26842eSHajimu UMEMOTO return (error); 762ca26842eSHajimu UMEMOTO return (0); 763c21dee17SSøren Schmidt } 764c21dee17SSøren Schmidt 765c21dee17SSøren Schmidt struct linux_getpeername_args { 766c21dee17SSøren Schmidt int s; 767ca26842eSHajimu UMEMOTO struct osockaddr *addr; 768c21dee17SSøren Schmidt int *namelen; 769c21dee17SSøren Schmidt }; 770c21dee17SSøren Schmidt 771c21dee17SSøren Schmidt static int 772b40ce416SJulian Elischer linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 773c21dee17SSøren Schmidt { 774c21dee17SSøren Schmidt struct linux_getpeername_args linux_args; 775044af7c3SJonathan Mini struct ogetpeername_args /* { 776c21dee17SSøren Schmidt int fdes; 777c21dee17SSøren Schmidt caddr_t asa; 778c21dee17SSøren Schmidt int *alen; 779ef04503dSPeter Wemm } */ bsd_args; 780c21dee17SSøren Schmidt int error; 781c21dee17SSøren Schmidt 7823f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7833f3a4815SMarcel Moolenaar return (error); 7843f3a4815SMarcel Moolenaar 785c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 786c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 787c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 788ca26842eSHajimu UMEMOTO error = ogetpeername(td, &bsd_args); 789ca26842eSHajimu UMEMOTO if (error) 790ca26842eSHajimu UMEMOTO return (error); 791ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 792ca26842eSHajimu UMEMOTO if (error) 793ca26842eSHajimu UMEMOTO return (error); 794ca26842eSHajimu UMEMOTO return (0); 795c21dee17SSøren Schmidt } 796c21dee17SSøren Schmidt 797c21dee17SSøren Schmidt struct linux_socketpair_args { 798c21dee17SSøren Schmidt int domain; 799c21dee17SSøren Schmidt int type; 800c21dee17SSøren Schmidt int protocol; 801c21dee17SSøren Schmidt int *rsv; 802c21dee17SSøren Schmidt }; 803c21dee17SSøren Schmidt 804c21dee17SSøren Schmidt static int 805b40ce416SJulian Elischer linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 806c21dee17SSøren Schmidt { 807c21dee17SSøren Schmidt struct linux_socketpair_args linux_args; 808ef04503dSPeter Wemm struct socketpair_args /* { 809c21dee17SSøren Schmidt int domain; 810c21dee17SSøren Schmidt int type; 811c21dee17SSøren Schmidt int protocol; 812c21dee17SSøren Schmidt int *rsv; 813ef04503dSPeter Wemm } */ bsd_args; 814c21dee17SSøren Schmidt int error; 815c21dee17SSøren Schmidt 8163f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8173f3a4815SMarcel Moolenaar return (error); 8183f3a4815SMarcel Moolenaar 819c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 820c21dee17SSøren Schmidt if (bsd_args.domain == -1) 8213f3a4815SMarcel Moolenaar return (EINVAL); 8223f3a4815SMarcel Moolenaar 823c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 824c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 825c21dee17SSøren Schmidt bsd_args.rsv = linux_args.rsv; 826b40ce416SJulian Elischer return (socketpair(td, &bsd_args)); 827c21dee17SSøren Schmidt } 828c21dee17SSøren Schmidt 829c21dee17SSøren Schmidt struct linux_send_args { 830c21dee17SSøren Schmidt int s; 831c21dee17SSøren Schmidt void *msg; 832c21dee17SSøren Schmidt int len; 833c21dee17SSøren Schmidt int flags; 834c21dee17SSøren Schmidt }; 835c21dee17SSøren Schmidt 836c21dee17SSøren Schmidt static int 837b40ce416SJulian Elischer linux_send(struct thread *td, struct linux_send_args *args) 838c21dee17SSøren Schmidt { 839c21dee17SSøren Schmidt struct linux_send_args linux_args; 840044af7c3SJonathan Mini struct osend_args /* { 841c21dee17SSøren Schmidt int s; 842c21dee17SSøren Schmidt caddr_t buf; 843044af7c3SJonathan Mini int len; 844c21dee17SSøren Schmidt int flags; 845ef04503dSPeter Wemm } */ bsd_args; 846c21dee17SSøren Schmidt int error; 847c21dee17SSøren Schmidt 8483f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8493f3a4815SMarcel Moolenaar return (error); 8503f3a4815SMarcel Moolenaar 851c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 852c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 853c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 854c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 855044af7c3SJonathan Mini return (osend(td, &bsd_args)); 856c21dee17SSøren Schmidt } 857c21dee17SSøren Schmidt 858c21dee17SSøren Schmidt struct linux_recv_args { 859c21dee17SSøren Schmidt int s; 860c21dee17SSøren Schmidt void *msg; 861c21dee17SSøren Schmidt int len; 862c21dee17SSøren Schmidt int flags; 863c21dee17SSøren Schmidt }; 864c21dee17SSøren Schmidt 865c21dee17SSøren Schmidt static int 866b40ce416SJulian Elischer linux_recv(struct thread *td, struct linux_recv_args *args) 867c21dee17SSøren Schmidt { 868c21dee17SSøren Schmidt struct linux_recv_args linux_args; 869044af7c3SJonathan Mini struct orecv_args /* { 870c21dee17SSøren Schmidt int s; 871c21dee17SSøren Schmidt caddr_t buf; 872c21dee17SSøren Schmidt int len; 873c21dee17SSøren Schmidt int flags; 874ef04503dSPeter Wemm } */ bsd_args; 875c21dee17SSøren Schmidt int error; 876c21dee17SSøren Schmidt 8773f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8783f3a4815SMarcel Moolenaar return (error); 8793f3a4815SMarcel Moolenaar 880c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 881c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 882c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 883c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 884044af7c3SJonathan Mini return (orecv(td, &bsd_args)); 885c21dee17SSøren Schmidt } 886c21dee17SSøren Schmidt 887c21dee17SSøren Schmidt struct linux_sendto_args { 888c21dee17SSøren Schmidt int s; 889c21dee17SSøren Schmidt void *msg; 890c21dee17SSøren Schmidt int len; 891c21dee17SSøren Schmidt int flags; 892c21dee17SSøren Schmidt caddr_t to; 893c21dee17SSøren Schmidt int tolen; 894c21dee17SSøren Schmidt }; 895c21dee17SSøren Schmidt 896c21dee17SSøren Schmidt static int 897b40ce416SJulian Elischer linux_sendto(struct thread *td, struct linux_sendto_args *args) 898c21dee17SSøren Schmidt { 899c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 900ef04503dSPeter Wemm struct sendto_args /* { 901c21dee17SSøren Schmidt int s; 902c21dee17SSøren Schmidt caddr_t buf; 903c21dee17SSøren Schmidt size_t len; 904c21dee17SSøren Schmidt int flags; 905c21dee17SSøren Schmidt caddr_t to; 906c21dee17SSøren Schmidt int tolen; 907ef04503dSPeter Wemm } */ bsd_args; 908ca26842eSHajimu UMEMOTO caddr_t sg = stackgap_init(); 909ca26842eSHajimu UMEMOTO struct sockaddr *to; 910ca26842eSHajimu UMEMOTO int tolen, error; 911c21dee17SSøren Schmidt 9123f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9133f3a4815SMarcel Moolenaar return (error); 9143f3a4815SMarcel Moolenaar 915ca26842eSHajimu UMEMOTO tolen = linux_args.tolen; 916ca26842eSHajimu UMEMOTO if (linux_args.to) { 917ca26842eSHajimu UMEMOTO error = linux_sa_get(&sg, &to, 918ca26842eSHajimu UMEMOTO (struct osockaddr *) linux_args.to, &tolen); 919ca26842eSHajimu UMEMOTO if (error) 920ca26842eSHajimu UMEMOTO return (error); 921ca26842eSHajimu UMEMOTO } else 922ca26842eSHajimu UMEMOTO to = NULL; 923ca26842eSHajimu UMEMOTO 924c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 925c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 926c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 927c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 928ca26842eSHajimu UMEMOTO bsd_args.to = (caddr_t) to; 929ca26842eSHajimu UMEMOTO bsd_args.tolen = (unsigned int) tolen; 930f2477ae1SMike Smith 9314d45de74SDavid Malone if (linux_check_hdrincl(td, &sg, linux_args.s) == 0) 932f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 9334d45de74SDavid Malone return (linux_sendto_hdrincl(td, &sg, &bsd_args)); 934f2477ae1SMike Smith 935b40ce416SJulian Elischer return (sendto(td, &bsd_args)); 936c21dee17SSøren Schmidt } 937c21dee17SSøren Schmidt 938c21dee17SSøren Schmidt struct linux_recvfrom_args { 939c21dee17SSøren Schmidt int s; 940c21dee17SSøren Schmidt void *buf; 941c21dee17SSøren Schmidt int len; 942c21dee17SSøren Schmidt int flags; 943c21dee17SSøren Schmidt caddr_t from; 944c21dee17SSøren Schmidt int *fromlen; 945c21dee17SSøren Schmidt }; 946c21dee17SSøren Schmidt 947c21dee17SSøren Schmidt static int 948b40ce416SJulian Elischer linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 949c21dee17SSøren Schmidt { 950c21dee17SSøren Schmidt struct linux_recvfrom_args linux_args; 951ef04503dSPeter Wemm struct recvfrom_args /* { 952c21dee17SSøren Schmidt int s; 953c21dee17SSøren Schmidt caddr_t buf; 954c21dee17SSøren Schmidt size_t len; 955c21dee17SSøren Schmidt int flags; 956c21dee17SSøren Schmidt caddr_t from; 957c21dee17SSøren Schmidt int *fromlenaddr; 958ef04503dSPeter Wemm } */ bsd_args; 959c21dee17SSøren Schmidt int error; 960c21dee17SSøren Schmidt 9613f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9623f3a4815SMarcel Moolenaar return (error); 9633f3a4815SMarcel Moolenaar 964c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 965c21dee17SSøren Schmidt bsd_args.buf = linux_args.buf; 966c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 96740dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 968c21dee17SSøren Schmidt bsd_args.from = linux_args.from; 969c21dee17SSøren Schmidt bsd_args.fromlenaddr = linux_args.fromlen; 970ca26842eSHajimu UMEMOTO error = orecvfrom(td, &bsd_args); 971ca26842eSHajimu UMEMOTO if (error) 972ca26842eSHajimu UMEMOTO return (error); 973ca26842eSHajimu UMEMOTO if (linux_args.from) { 974ca26842eSHajimu UMEMOTO error = linux_sa_put((struct osockaddr *) linux_args.from); 975ca26842eSHajimu UMEMOTO if (error) 976ca26842eSHajimu UMEMOTO return (error); 977ca26842eSHajimu UMEMOTO } 978ca26842eSHajimu UMEMOTO return (0); 979ca26842eSHajimu UMEMOTO } 980ca26842eSHajimu UMEMOTO 981ca26842eSHajimu UMEMOTO struct linux_sendmsg_args { 982ca26842eSHajimu UMEMOTO int s; 983ca26842eSHajimu UMEMOTO const struct msghdr *msg; 984ca26842eSHajimu UMEMOTO int flags; 985ca26842eSHajimu UMEMOTO }; 986ca26842eSHajimu UMEMOTO 987ca26842eSHajimu UMEMOTO static int 988ca26842eSHajimu UMEMOTO linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 989ca26842eSHajimu UMEMOTO { 990ca26842eSHajimu UMEMOTO struct linux_sendmsg_args linux_args; 991ca26842eSHajimu UMEMOTO struct sendmsg_args /* { 992ca26842eSHajimu UMEMOTO int s; 993ca26842eSHajimu UMEMOTO const struct msghdr *msg; 994ca26842eSHajimu UMEMOTO int flags; 995ca26842eSHajimu UMEMOTO } */ bsd_args; 996ca26842eSHajimu UMEMOTO struct msghdr msg; 997ca26842eSHajimu UMEMOTO struct msghdr *nmsg = NULL; 998ca26842eSHajimu UMEMOTO int error; 999ca26842eSHajimu UMEMOTO int level; 1000ca26842eSHajimu UMEMOTO caddr_t control; 1001ca26842eSHajimu UMEMOTO 1002ca26842eSHajimu UMEMOTO if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1003ca26842eSHajimu UMEMOTO return (error); 1004ca26842eSHajimu UMEMOTO 10054b7ef73dSDag-Erling Smørgrav error = copyin(linux_args.msg, &msg, sizeof(msg)); 1006ca26842eSHajimu UMEMOTO if (error) 1007ca26842eSHajimu UMEMOTO return (error); 1008ca26842eSHajimu UMEMOTO 1009ca26842eSHajimu UMEMOTO if (msg.msg_name) { 1010ca26842eSHajimu UMEMOTO struct sockaddr *sa; 1011ca26842eSHajimu UMEMOTO caddr_t sg = stackgap_init(); 1012ca26842eSHajimu UMEMOTO 1013ca26842eSHajimu UMEMOTO nmsg = (struct msghdr *) stackgap_alloc(&sg, 1014ca26842eSHajimu UMEMOTO sizeof(struct msghdr)); 1015ca26842eSHajimu UMEMOTO if (!nmsg) 1016ca26842eSHajimu UMEMOTO return (ENOMEM); 1017ca26842eSHajimu UMEMOTO 1018ca26842eSHajimu UMEMOTO error = linux_sa_get(&sg, &sa, 1019ca26842eSHajimu UMEMOTO (struct osockaddr *) msg.msg_name, &msg.msg_namelen); 1020ca26842eSHajimu UMEMOTO if (error) 1021ca26842eSHajimu UMEMOTO return (error); 1022ca26842eSHajimu UMEMOTO 1023ca26842eSHajimu UMEMOTO msg.msg_name = (struct sockaddr *) sa; 1024ca26842eSHajimu UMEMOTO error = copyout(&msg, nmsg, sizeof(struct msghdr)); 1025ca26842eSHajimu UMEMOTO if (error) 1026ca26842eSHajimu UMEMOTO return (error); 1027ca26842eSHajimu UMEMOTO } 1028ca26842eSHajimu UMEMOTO 1029ca26842eSHajimu UMEMOTO error = copyin(&linux_args.msg->msg_control, &control, 1030ca26842eSHajimu UMEMOTO sizeof(caddr_t)); 1031ca26842eSHajimu UMEMOTO if (error) 1032ca26842eSHajimu UMEMOTO return (error); 1033ca26842eSHajimu UMEMOTO 1034ca26842eSHajimu UMEMOTO if (control == NULL) 1035ca26842eSHajimu UMEMOTO goto done; 1036ca26842eSHajimu UMEMOTO 1037ca26842eSHajimu UMEMOTO error = copyin(&((struct cmsghdr*)control)->cmsg_level, &level, 1038ca26842eSHajimu UMEMOTO sizeof(int)); 1039ca26842eSHajimu UMEMOTO if (error) 1040ca26842eSHajimu UMEMOTO return (error); 1041ca26842eSHajimu UMEMOTO 1042ca26842eSHajimu UMEMOTO if (level == 1) { 1043ca26842eSHajimu UMEMOTO /* 1044ca26842eSHajimu UMEMOTO * Linux thinks that SOL_SOCKET is 1; we know 1045ca26842eSHajimu UMEMOTO * that it's really 0xffff, of course. 1046ca26842eSHajimu UMEMOTO */ 1047ca26842eSHajimu UMEMOTO level = SOL_SOCKET; 1048ca26842eSHajimu UMEMOTO error = copyout(&level, 1049ca26842eSHajimu UMEMOTO &((struct cmsghdr *)control)->cmsg_level, sizeof(int)); 1050ca26842eSHajimu UMEMOTO if (error) 1051ca26842eSHajimu UMEMOTO return (error); 1052ca26842eSHajimu UMEMOTO } 1053ca26842eSHajimu UMEMOTO done: 10544d45de74SDavid Malone bsd_args.s = linux_args.s; 10554d45de74SDavid Malone bsd_args.msg = (caddr_t)nmsg; 10564d45de74SDavid Malone bsd_args.flags = linux_args.flags; 1057ca26842eSHajimu UMEMOTO return (sendmsg(td, &bsd_args)); 1058c21dee17SSøren Schmidt } 1059c21dee17SSøren Schmidt 106040dbba57SAssar Westerlund struct linux_recvmsg_args { 106140dbba57SAssar Westerlund int s; 106240dbba57SAssar Westerlund struct msghdr *msg; 106340dbba57SAssar Westerlund int flags; 106440dbba57SAssar Westerlund }; 106540dbba57SAssar Westerlund 106640dbba57SAssar Westerlund static int 1067b40ce416SJulian Elischer linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 106840dbba57SAssar Westerlund { 106940dbba57SAssar Westerlund struct linux_recvmsg_args linux_args; 107040dbba57SAssar Westerlund struct recvmsg_args /* { 107140dbba57SAssar Westerlund int s; 107240dbba57SAssar Westerlund struct msghdr *msg; 107340dbba57SAssar Westerlund int flags; 107440dbba57SAssar Westerlund } */ bsd_args; 1075ca26842eSHajimu UMEMOTO struct msghdr msg; 107640dbba57SAssar Westerlund int error; 107740dbba57SAssar Westerlund 107840dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 107940dbba57SAssar Westerlund return (error); 108040dbba57SAssar Westerlund 108140dbba57SAssar Westerlund bsd_args.s = linux_args.s; 108240dbba57SAssar Westerlund bsd_args.msg = linux_args.msg; 108340dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 1084ca26842eSHajimu UMEMOTO error = recvmsg(td, &bsd_args); 1085ca26842eSHajimu UMEMOTO if (error) 1086ca26842eSHajimu UMEMOTO return (error); 1087ca26842eSHajimu UMEMOTO 10884b7ef73dSDag-Erling Smørgrav error = copyin(linux_args.msg, &msg, sizeof(msg)); 1089ca26842eSHajimu UMEMOTO if (error) 1090ca26842eSHajimu UMEMOTO return (error); 1091ca26842eSHajimu UMEMOTO if (msg.msg_name && msg.msg_namelen > 2) 1092ca26842eSHajimu UMEMOTO error = linux_sa_put(msg.msg_name); 1093ca26842eSHajimu UMEMOTO return (error); 109440dbba57SAssar Westerlund } 109540dbba57SAssar Westerlund 1096c21dee17SSøren Schmidt struct linux_shutdown_args { 1097c21dee17SSøren Schmidt int s; 1098c21dee17SSøren Schmidt int how; 1099c21dee17SSøren Schmidt }; 1100c21dee17SSøren Schmidt 1101c21dee17SSøren Schmidt static int 1102b40ce416SJulian Elischer linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1103c21dee17SSøren Schmidt { 1104c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 1105ef04503dSPeter Wemm struct shutdown_args /* { 1106c21dee17SSøren Schmidt int s; 1107c21dee17SSøren Schmidt int how; 1108ef04503dSPeter Wemm } */ bsd_args; 1109c21dee17SSøren Schmidt int error; 1110c21dee17SSøren Schmidt 11113f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11123f3a4815SMarcel Moolenaar return (error); 11133f3a4815SMarcel Moolenaar 1114c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1115c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 1116b40ce416SJulian Elischer return (shutdown(td, &bsd_args)); 1117c21dee17SSøren Schmidt } 1118c21dee17SSøren Schmidt 1119c21dee17SSøren Schmidt struct linux_setsockopt_args { 1120c21dee17SSøren Schmidt int s; 1121c21dee17SSøren Schmidt int level; 1122c21dee17SSøren Schmidt int optname; 1123c21dee17SSøren Schmidt void *optval; 1124c21dee17SSøren Schmidt int optlen; 1125c21dee17SSøren Schmidt }; 1126c21dee17SSøren Schmidt 1127c21dee17SSøren Schmidt static int 1128b40ce416SJulian Elischer linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1129c21dee17SSøren Schmidt { 1130c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 1131ef04503dSPeter Wemm struct setsockopt_args /* { 1132c21dee17SSøren Schmidt int s; 1133c21dee17SSøren Schmidt int level; 1134c21dee17SSøren Schmidt int name; 1135c21dee17SSøren Schmidt caddr_t val; 1136c21dee17SSøren Schmidt int valsize; 1137ef04503dSPeter Wemm } */ bsd_args; 1138c21dee17SSøren Schmidt int error, name; 1139c21dee17SSøren Schmidt 11403f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11413f3a4815SMarcel Moolenaar return (error); 11423f3a4815SMarcel Moolenaar 1143c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1144c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1145c21dee17SSøren Schmidt switch (bsd_args.level) { 1146c21dee17SSøren Schmidt case SOL_SOCKET: 1147c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1148c21dee17SSøren Schmidt break; 1149c21dee17SSøren Schmidt case IPPROTO_IP: 1150c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1151c21dee17SSøren Schmidt break; 1152dad3b88aSMike Smith case IPPROTO_TCP: 1153dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1154dad3b88aSMike Smith name = linux_args.optname; 1155dad3b88aSMike Smith break; 1156c21dee17SSøren Schmidt default: 11573f3a4815SMarcel Moolenaar name = -1; 11583f3a4815SMarcel Moolenaar break; 1159c21dee17SSøren Schmidt } 1160c21dee17SSøren Schmidt if (name == -1) 11613f3a4815SMarcel Moolenaar return (EINVAL); 11623f3a4815SMarcel Moolenaar 1163c21dee17SSøren Schmidt bsd_args.name = name; 1164c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1165c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 1166b40ce416SJulian Elischer return (setsockopt(td, &bsd_args)); 1167c21dee17SSøren Schmidt } 1168c21dee17SSøren Schmidt 1169c21dee17SSøren Schmidt struct linux_getsockopt_args { 1170c21dee17SSøren Schmidt int s; 1171c21dee17SSøren Schmidt int level; 1172c21dee17SSøren Schmidt int optname; 1173c21dee17SSøren Schmidt void *optval; 1174c21dee17SSøren Schmidt int *optlen; 1175c21dee17SSøren Schmidt }; 1176c21dee17SSøren Schmidt 1177c21dee17SSøren Schmidt static int 1178b40ce416SJulian Elischer linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1179c21dee17SSøren Schmidt { 1180c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 1181ef04503dSPeter Wemm struct getsockopt_args /* { 1182c21dee17SSøren Schmidt int s; 1183c21dee17SSøren Schmidt int level; 1184c21dee17SSøren Schmidt int name; 1185c21dee17SSøren Schmidt caddr_t val; 1186c21dee17SSøren Schmidt int *avalsize; 1187ef04503dSPeter Wemm } */ bsd_args; 1188c21dee17SSøren Schmidt int error, name; 1189c21dee17SSøren Schmidt 11903f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11913f3a4815SMarcel Moolenaar return (error); 11923f3a4815SMarcel Moolenaar 1193c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1194c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1195c21dee17SSøren Schmidt switch (bsd_args.level) { 1196c21dee17SSøren Schmidt case SOL_SOCKET: 1197c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1198c21dee17SSøren Schmidt break; 1199c21dee17SSøren Schmidt case IPPROTO_IP: 1200c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1201c21dee17SSøren Schmidt break; 1202dad3b88aSMike Smith case IPPROTO_TCP: 1203dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1204dad3b88aSMike Smith name = linux_args.optname; 1205dad3b88aSMike Smith break; 1206c21dee17SSøren Schmidt default: 12073f3a4815SMarcel Moolenaar name = -1; 12083f3a4815SMarcel Moolenaar break; 1209c21dee17SSøren Schmidt } 1210c21dee17SSøren Schmidt if (name == -1) 12113f3a4815SMarcel Moolenaar return (EINVAL); 12123f3a4815SMarcel Moolenaar 1213f2477ae1SMike Smith bsd_args.name = name; 1214c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1215c21dee17SSøren Schmidt bsd_args.avalsize = linux_args.optlen; 1216b40ce416SJulian Elischer return (getsockopt(td, &bsd_args)); 1217c21dee17SSøren Schmidt } 1218c21dee17SSøren Schmidt 1219c21dee17SSøren Schmidt int 1220b40ce416SJulian Elischer linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1221c21dee17SSøren Schmidt { 12225002a60fSMarcel Moolenaar void *arg = (void *)args->args; 12233f3a4815SMarcel Moolenaar 1224c21dee17SSøren Schmidt switch (args->what) { 1225c21dee17SSøren Schmidt case LINUX_SOCKET: 1226b40ce416SJulian Elischer return (linux_socket(td, arg)); 1227c21dee17SSøren Schmidt case LINUX_BIND: 1228b40ce416SJulian Elischer return (linux_bind(td, arg)); 1229c21dee17SSøren Schmidt case LINUX_CONNECT: 1230b40ce416SJulian Elischer return (linux_connect(td, arg)); 1231c21dee17SSøren Schmidt case LINUX_LISTEN: 1232b40ce416SJulian Elischer return (linux_listen(td, arg)); 1233c21dee17SSøren Schmidt case LINUX_ACCEPT: 1234b40ce416SJulian Elischer return (linux_accept(td, arg)); 1235c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 1236b40ce416SJulian Elischer return (linux_getsockname(td, arg)); 1237c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 1238b40ce416SJulian Elischer return (linux_getpeername(td, arg)); 1239c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 1240b40ce416SJulian Elischer return (linux_socketpair(td, arg)); 1241c21dee17SSøren Schmidt case LINUX_SEND: 1242b40ce416SJulian Elischer return (linux_send(td, arg)); 1243c21dee17SSøren Schmidt case LINUX_RECV: 1244b40ce416SJulian Elischer return (linux_recv(td, arg)); 1245c21dee17SSøren Schmidt case LINUX_SENDTO: 1246b40ce416SJulian Elischer return (linux_sendto(td, arg)); 1247c21dee17SSøren Schmidt case LINUX_RECVFROM: 1248b40ce416SJulian Elischer return (linux_recvfrom(td, arg)); 1249c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 1250b40ce416SJulian Elischer return (linux_shutdown(td, arg)); 1251c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 1252b40ce416SJulian Elischer return (linux_setsockopt(td, arg)); 1253c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 1254b40ce416SJulian Elischer return (linux_getsockopt(td, arg)); 1255e76bba09SSøren Schmidt case LINUX_SENDMSG: 1256ca26842eSHajimu UMEMOTO return (linux_sendmsg(td, arg)); 1257e76bba09SSøren Schmidt case LINUX_RECVMSG: 1258b40ce416SJulian Elischer return (linux_recvmsg(td, arg)); 1259c21dee17SSøren Schmidt } 12603f3a4815SMarcel Moolenaar 12613f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 12623f3a4815SMarcel Moolenaar return (ENOSYS); 1263c21dee17SSøren Schmidt } 12645231fb20SDavid E. O'Brien #endif /*!__alpha__*/ 1265