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. */ 33aefce619SRuslan Ermilov #include "opt_compat.h" 34ca26842eSHajimu UMEMOTO #include "opt_inet6.h" 355591b823SEivind Eklund 36c21dee17SSøren Schmidt #include <sys/param.h> 37f2477ae1SMike Smith #include <sys/proc.h> 38c21dee17SSøren Schmidt #include <sys/systm.h> 391f3dad5aSBruce Evans #include <sys/sysproto.h> 40dad3b88aSMike Smith #include <sys/fcntl.h> 410bf301c0SJonathan Lemon #include <sys/file.h> 42104a9b7eSAlexander Kabaev #include <sys/limits.h> 434641373fSJohn Baldwin #include <sys/lock.h> 44ca26842eSHajimu UMEMOTO #include <sys/malloc.h> 454641373fSJohn Baldwin #include <sys/mutex.h> 465a8a13e0SDavid Malone #include <sys/mbuf.h> 47c21dee17SSøren Schmidt #include <sys/socket.h> 480bf301c0SJonathan Lemon #include <sys/socketvar.h> 49ca26842eSHajimu UMEMOTO #include <sys/syscallsubr.h> 5008637435SBruce Evans #include <sys/uio.h> 51ca26842eSHajimu UMEMOTO #include <sys/syslog.h> 52d0b2365eSKonstantin Belousov #include <sys/un.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 621997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 634af27623STim J. Robbins #include <machine/../linux32/linux.h> 644af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h> 651997c537SDavid E. O'Brien #else 661997c537SDavid E. O'Brien #include <machine/../linux/linux.h> 671997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h> 684af27623STim J. Robbins #endif 6940dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 70ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 71c21dee17SSøren Schmidt 72ca26842eSHajimu UMEMOTO static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *, 73ca26842eSHajimu UMEMOTO struct malloc_type *); 74ca26842eSHajimu UMEMOTO static int linux_to_bsd_domain(int); 75ca26842eSHajimu UMEMOTO 764730796cSBill Fenner /* 77ca26842eSHajimu UMEMOTO * Reads a linux sockaddr and does any necessary translation. 78ca26842eSHajimu UMEMOTO * Linux sockaddrs don't have a length field, only a family. 794730796cSBill Fenner */ 804730796cSBill Fenner static int 81ca26842eSHajimu UMEMOTO linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int len) 824730796cSBill Fenner { 83ca26842eSHajimu UMEMOTO int osalen = len; 844730796cSBill Fenner 85ca26842eSHajimu UMEMOTO return (do_sa_get(sap, osa, &osalen, M_SONAME)); 864730796cSBill Fenner } 874730796cSBill Fenner 88ca26842eSHajimu UMEMOTO /* 89ca26842eSHajimu UMEMOTO * Copy the osockaddr structure pointed to by osa to kernel, adjust 90ca26842eSHajimu UMEMOTO * family and convert to sockaddr. 91ca26842eSHajimu UMEMOTO */ 92ca26842eSHajimu UMEMOTO static int 93ca26842eSHajimu UMEMOTO do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, 94ca26842eSHajimu UMEMOTO struct malloc_type *mtype) 95ca26842eSHajimu UMEMOTO { 96ca26842eSHajimu UMEMOTO int error=0, bdom; 97ca26842eSHajimu UMEMOTO struct sockaddr *sa; 98ca26842eSHajimu UMEMOTO struct osockaddr *kosa; 99ca26842eSHajimu UMEMOTO int alloclen; 100ca26842eSHajimu UMEMOTO #ifdef INET6 101ca26842eSHajimu UMEMOTO int oldv6size; 102ca26842eSHajimu UMEMOTO struct sockaddr_in6 *sin6; 103ca26842eSHajimu UMEMOTO #endif 104ca26842eSHajimu UMEMOTO 105ca26842eSHajimu UMEMOTO if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) 106ca26842eSHajimu UMEMOTO return (EINVAL); 107ca26842eSHajimu UMEMOTO 108ca26842eSHajimu UMEMOTO alloclen = *osalen; 109ca26842eSHajimu UMEMOTO #ifdef INET6 110ca26842eSHajimu UMEMOTO oldv6size = 0; 111ca26842eSHajimu UMEMOTO /* 112ca26842eSHajimu UMEMOTO * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 113ca26842eSHajimu UMEMOTO * if it's a v4-mapped address, so reserve the proper space 114ca26842eSHajimu UMEMOTO * for it. 115ca26842eSHajimu UMEMOTO */ 116ca26842eSHajimu UMEMOTO if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { 117ca26842eSHajimu UMEMOTO alloclen = sizeof (struct sockaddr_in6); 118ca26842eSHajimu UMEMOTO oldv6size = 1; 119ca26842eSHajimu UMEMOTO } 120ca26842eSHajimu UMEMOTO #endif 121ca26842eSHajimu UMEMOTO 1225b13e781SHajimu UMEMOTO MALLOC(kosa, struct osockaddr *, alloclen, mtype, M_WAITOK); 123ca26842eSHajimu UMEMOTO 1244b7ef73dSDag-Erling Smørgrav if ((error = copyin(osa, kosa, *osalen))) 125ca26842eSHajimu UMEMOTO goto out; 126ca26842eSHajimu UMEMOTO 127ca26842eSHajimu UMEMOTO bdom = linux_to_bsd_domain(kosa->sa_family); 128ca26842eSHajimu UMEMOTO if (bdom == -1) { 129ca26842eSHajimu UMEMOTO error = EINVAL; 130ca26842eSHajimu UMEMOTO goto out; 131ca26842eSHajimu UMEMOTO } 132ca26842eSHajimu UMEMOTO 133ca26842eSHajimu UMEMOTO #ifdef INET6 134ca26842eSHajimu UMEMOTO /* 135ca26842eSHajimu UMEMOTO * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 136ca26842eSHajimu UMEMOTO * which lacks the scope id compared with RFC2553 one. If we detect 137ca26842eSHajimu UMEMOTO * the situation, reject the address and write a message to system log. 138ca26842eSHajimu UMEMOTO * 139ca26842eSHajimu UMEMOTO * Still accept addresses for which the scope id is not used. 140ca26842eSHajimu UMEMOTO */ 141ca26842eSHajimu UMEMOTO if (oldv6size && bdom == AF_INET6) { 142ca26842eSHajimu UMEMOTO sin6 = (struct sockaddr_in6 *)kosa; 143ca26842eSHajimu UMEMOTO if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 144ca26842eSHajimu UMEMOTO (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 145ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 146ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 147ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 148ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 149ca26842eSHajimu UMEMOTO sin6->sin6_scope_id = 0; 150ca26842eSHajimu UMEMOTO } else { 151ca26842eSHajimu UMEMOTO log(LOG_DEBUG, 1523c616032SGleb Smirnoff "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); 153ca26842eSHajimu UMEMOTO error = EINVAL; 154ca26842eSHajimu UMEMOTO goto out; 155ca26842eSHajimu UMEMOTO } 156ca26842eSHajimu UMEMOTO } else 157ca26842eSHajimu UMEMOTO #endif 158ca26842eSHajimu UMEMOTO if (bdom == AF_INET) 159ca26842eSHajimu UMEMOTO alloclen = sizeof(struct sockaddr_in); 160ca26842eSHajimu UMEMOTO 161ca26842eSHajimu UMEMOTO sa = (struct sockaddr *) kosa; 162ca26842eSHajimu UMEMOTO sa->sa_family = bdom; 163ca26842eSHajimu UMEMOTO sa->sa_len = alloclen; 164ca26842eSHajimu UMEMOTO 165ca26842eSHajimu UMEMOTO *sap = sa; 166ca26842eSHajimu UMEMOTO *osalen = alloclen; 167ca26842eSHajimu UMEMOTO return (0); 168ca26842eSHajimu UMEMOTO 169ca26842eSHajimu UMEMOTO out: 170ca26842eSHajimu UMEMOTO FREE(kosa, mtype); 171ca26842eSHajimu UMEMOTO return (error); 172ca26842eSHajimu UMEMOTO } 173ca26842eSHajimu UMEMOTO 174c21dee17SSøren Schmidt static int 175c21dee17SSøren Schmidt linux_to_bsd_domain(int domain) 176c21dee17SSøren Schmidt { 1773f3a4815SMarcel Moolenaar 178c21dee17SSøren Schmidt switch (domain) { 179c21dee17SSøren Schmidt case LINUX_AF_UNSPEC: 1803f3a4815SMarcel Moolenaar return (AF_UNSPEC); 181c21dee17SSøren Schmidt case LINUX_AF_UNIX: 1823f3a4815SMarcel Moolenaar return (AF_LOCAL); 183c21dee17SSøren Schmidt case LINUX_AF_INET: 1843f3a4815SMarcel Moolenaar return (AF_INET); 185ca26842eSHajimu UMEMOTO case LINUX_AF_INET6: 186ca26842eSHajimu UMEMOTO return (AF_INET6); 187c21dee17SSøren Schmidt case LINUX_AF_AX25: 1883f3a4815SMarcel Moolenaar return (AF_CCITT); 189c21dee17SSøren Schmidt case LINUX_AF_IPX: 1903f3a4815SMarcel Moolenaar return (AF_IPX); 191c21dee17SSøren Schmidt case LINUX_AF_APPLETALK: 1923f3a4815SMarcel Moolenaar return (AF_APPLETALK); 193c21dee17SSøren Schmidt } 1943f3a4815SMarcel Moolenaar return (-1); 195c21dee17SSøren Schmidt } 196c21dee17SSøren Schmidt 197ca26842eSHajimu UMEMOTO static int 198ca26842eSHajimu UMEMOTO bsd_to_linux_domain(int domain) 199ca26842eSHajimu UMEMOTO { 200ca26842eSHajimu UMEMOTO 201ca26842eSHajimu UMEMOTO switch (domain) { 202ca26842eSHajimu UMEMOTO case AF_UNSPEC: 203ca26842eSHajimu UMEMOTO return (LINUX_AF_UNSPEC); 204ca26842eSHajimu UMEMOTO case AF_LOCAL: 205ca26842eSHajimu UMEMOTO return (LINUX_AF_UNIX); 206ca26842eSHajimu UMEMOTO case AF_INET: 207ca26842eSHajimu UMEMOTO return (LINUX_AF_INET); 208ca26842eSHajimu UMEMOTO case AF_INET6: 209ca26842eSHajimu UMEMOTO return (LINUX_AF_INET6); 210ca26842eSHajimu UMEMOTO case AF_CCITT: 211ca26842eSHajimu UMEMOTO return (LINUX_AF_AX25); 212ca26842eSHajimu UMEMOTO case AF_IPX: 213ca26842eSHajimu UMEMOTO return (LINUX_AF_IPX); 214ca26842eSHajimu UMEMOTO case AF_APPLETALK: 215ca26842eSHajimu UMEMOTO return (LINUX_AF_APPLETALK); 216ca26842eSHajimu UMEMOTO } 217ca26842eSHajimu UMEMOTO return (-1); 218ca26842eSHajimu UMEMOTO } 219ca26842eSHajimu UMEMOTO 220c21dee17SSøren Schmidt static int 221c21dee17SSøren Schmidt linux_to_bsd_sockopt_level(int level) 222c21dee17SSøren Schmidt { 2233f3a4815SMarcel Moolenaar 224c21dee17SSøren Schmidt switch (level) { 225c21dee17SSøren Schmidt case LINUX_SOL_SOCKET: 2263f3a4815SMarcel Moolenaar return (SOL_SOCKET); 227c21dee17SSøren Schmidt } 2283f3a4815SMarcel Moolenaar return (level); 229c21dee17SSøren Schmidt } 230c21dee17SSøren Schmidt 2313f3a4815SMarcel Moolenaar static int 23284b11cd8SMitsuru IWASAKI bsd_to_linux_sockopt_level(int level) 23384b11cd8SMitsuru IWASAKI { 23484b11cd8SMitsuru IWASAKI 23584b11cd8SMitsuru IWASAKI switch (level) { 23684b11cd8SMitsuru IWASAKI case SOL_SOCKET: 23784b11cd8SMitsuru IWASAKI return (LINUX_SOL_SOCKET); 23884b11cd8SMitsuru IWASAKI } 23984b11cd8SMitsuru IWASAKI return (level); 24084b11cd8SMitsuru IWASAKI } 24184b11cd8SMitsuru IWASAKI 24284b11cd8SMitsuru IWASAKI static int 2433f3a4815SMarcel Moolenaar linux_to_bsd_ip_sockopt(int opt) 244c21dee17SSøren Schmidt { 2453f3a4815SMarcel Moolenaar 246c21dee17SSøren Schmidt switch (opt) { 247c21dee17SSøren Schmidt case LINUX_IP_TOS: 2483f3a4815SMarcel Moolenaar return (IP_TOS); 249c21dee17SSøren Schmidt case LINUX_IP_TTL: 2503f3a4815SMarcel Moolenaar return (IP_TTL); 25166ff6a3cSBill Fenner case LINUX_IP_OPTIONS: 2523f3a4815SMarcel Moolenaar return (IP_OPTIONS); 25366ff6a3cSBill Fenner case LINUX_IP_MULTICAST_IF: 2543f3a4815SMarcel Moolenaar return (IP_MULTICAST_IF); 25566ff6a3cSBill Fenner case LINUX_IP_MULTICAST_TTL: 2563f3a4815SMarcel Moolenaar return (IP_MULTICAST_TTL); 25766ff6a3cSBill Fenner case LINUX_IP_MULTICAST_LOOP: 2583f3a4815SMarcel Moolenaar return (IP_MULTICAST_LOOP); 25966ff6a3cSBill Fenner case LINUX_IP_ADD_MEMBERSHIP: 2603f3a4815SMarcel Moolenaar return (IP_ADD_MEMBERSHIP); 26166ff6a3cSBill Fenner case LINUX_IP_DROP_MEMBERSHIP: 2623f3a4815SMarcel Moolenaar return (IP_DROP_MEMBERSHIP); 26366ff6a3cSBill Fenner case LINUX_IP_HDRINCL: 2643f3a4815SMarcel Moolenaar return (IP_HDRINCL); 265c21dee17SSøren Schmidt } 2663f3a4815SMarcel Moolenaar return (-1); 267c21dee17SSøren Schmidt } 268c21dee17SSøren Schmidt 269c21dee17SSøren Schmidt static int 270c21dee17SSøren Schmidt linux_to_bsd_so_sockopt(int opt) 271c21dee17SSøren Schmidt { 2723f3a4815SMarcel Moolenaar 273c21dee17SSøren Schmidt switch (opt) { 274c21dee17SSøren Schmidt case LINUX_SO_DEBUG: 2753f3a4815SMarcel Moolenaar return (SO_DEBUG); 276c21dee17SSøren Schmidt case LINUX_SO_REUSEADDR: 2773f3a4815SMarcel Moolenaar return (SO_REUSEADDR); 278c21dee17SSøren Schmidt case LINUX_SO_TYPE: 2793f3a4815SMarcel Moolenaar return (SO_TYPE); 280c21dee17SSøren Schmidt case LINUX_SO_ERROR: 2813f3a4815SMarcel Moolenaar return (SO_ERROR); 282c21dee17SSøren Schmidt case LINUX_SO_DONTROUTE: 2833f3a4815SMarcel Moolenaar return (SO_DONTROUTE); 284c21dee17SSøren Schmidt case LINUX_SO_BROADCAST: 2853f3a4815SMarcel Moolenaar return (SO_BROADCAST); 286c21dee17SSøren Schmidt case LINUX_SO_SNDBUF: 2873f3a4815SMarcel Moolenaar return (SO_SNDBUF); 288c21dee17SSøren Schmidt case LINUX_SO_RCVBUF: 2893f3a4815SMarcel Moolenaar return (SO_RCVBUF); 290c21dee17SSøren Schmidt case LINUX_SO_KEEPALIVE: 2913f3a4815SMarcel Moolenaar return (SO_KEEPALIVE); 292c21dee17SSøren Schmidt case LINUX_SO_OOBINLINE: 2933f3a4815SMarcel Moolenaar return (SO_OOBINLINE); 294c21dee17SSøren Schmidt case LINUX_SO_LINGER: 2953f3a4815SMarcel Moolenaar return (SO_LINGER); 296d0b2365eSKonstantin Belousov case LINUX_SO_PEERCRED: 297d0b2365eSKonstantin Belousov return (LOCAL_PEERCRED); 298d0b2365eSKonstantin Belousov case LINUX_SO_RCVLOWAT: 299d0b2365eSKonstantin Belousov return (SO_RCVLOWAT); 300d0b2365eSKonstantin Belousov case LINUX_SO_SNDLOWAT: 301d0b2365eSKonstantin Belousov return (SO_SNDLOWAT); 302d0b2365eSKonstantin Belousov case LINUX_SO_RCVTIMEO: 303d0b2365eSKonstantin Belousov return (SO_RCVTIMEO); 304d0b2365eSKonstantin Belousov case LINUX_SO_SNDTIMEO: 305d0b2365eSKonstantin Belousov return (SO_SNDTIMEO); 306d0b2365eSKonstantin Belousov case LINUX_SO_TIMESTAMP: 307d0b2365eSKonstantin Belousov return (SO_TIMESTAMP); 308d0b2365eSKonstantin Belousov case LINUX_SO_ACCEPTCONN: 309d0b2365eSKonstantin Belousov return (SO_ACCEPTCONN); 310c21dee17SSøren Schmidt } 3113f3a4815SMarcel Moolenaar return (-1); 312c21dee17SSøren Schmidt } 313c21dee17SSøren Schmidt 31440dbba57SAssar Westerlund static int 31540dbba57SAssar Westerlund linux_to_bsd_msg_flags(int flags) 31640dbba57SAssar Westerlund { 31740dbba57SAssar Westerlund int ret_flags = 0; 31840dbba57SAssar Westerlund 31940dbba57SAssar Westerlund if (flags & LINUX_MSG_OOB) 32040dbba57SAssar Westerlund ret_flags |= MSG_OOB; 32140dbba57SAssar Westerlund if (flags & LINUX_MSG_PEEK) 32240dbba57SAssar Westerlund ret_flags |= MSG_PEEK; 32340dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTROUTE) 32440dbba57SAssar Westerlund ret_flags |= MSG_DONTROUTE; 32540dbba57SAssar Westerlund if (flags & LINUX_MSG_CTRUNC) 32640dbba57SAssar Westerlund ret_flags |= MSG_CTRUNC; 32740dbba57SAssar Westerlund if (flags & LINUX_MSG_TRUNC) 32840dbba57SAssar Westerlund ret_flags |= MSG_TRUNC; 32940dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTWAIT) 33040dbba57SAssar Westerlund ret_flags |= MSG_DONTWAIT; 33140dbba57SAssar Westerlund if (flags & LINUX_MSG_EOR) 33240dbba57SAssar Westerlund ret_flags |= MSG_EOR; 33340dbba57SAssar Westerlund if (flags & LINUX_MSG_WAITALL) 33440dbba57SAssar Westerlund ret_flags |= MSG_WAITALL; 3358d6e40c3SMaxim Sobolev if (flags & LINUX_MSG_NOSIGNAL) 3368d6e40c3SMaxim Sobolev ret_flags |= MSG_NOSIGNAL; 33740dbba57SAssar Westerlund #if 0 /* not handled */ 33840dbba57SAssar Westerlund if (flags & LINUX_MSG_PROXY) 33940dbba57SAssar Westerlund ; 34040dbba57SAssar Westerlund if (flags & LINUX_MSG_FIN) 34140dbba57SAssar Westerlund ; 34240dbba57SAssar Westerlund if (flags & LINUX_MSG_SYN) 34340dbba57SAssar Westerlund ; 34440dbba57SAssar Westerlund if (flags & LINUX_MSG_CONFIRM) 34540dbba57SAssar Westerlund ; 34640dbba57SAssar Westerlund if (flags & LINUX_MSG_RST) 34740dbba57SAssar Westerlund ; 34840dbba57SAssar Westerlund if (flags & LINUX_MSG_ERRQUEUE) 34940dbba57SAssar Westerlund ; 35040dbba57SAssar Westerlund #endif 35140dbba57SAssar Westerlund return ret_flags; 35240dbba57SAssar Westerlund } 35340dbba57SAssar Westerlund 3545c8919adSAlexander Leidinger /* 3555c8919adSAlexander Leidinger * If bsd_to_linux_sockaddr() or linux_to_bsd_sockaddr() faults, then the 3565c8919adSAlexander Leidinger * native syscall will fault. Thus, we don't really need to check the 3575c8919adSAlexander Leidinger * return values for these functions. 3585c8919adSAlexander Leidinger */ 3595c8919adSAlexander Leidinger 3605c8919adSAlexander Leidinger static int 3615c8919adSAlexander Leidinger bsd_to_linux_sockaddr(struct sockaddr *arg) 3625c8919adSAlexander Leidinger { 3635c8919adSAlexander Leidinger struct sockaddr sa; 3645c8919adSAlexander Leidinger size_t sa_len = sizeof(struct sockaddr); 3655c8919adSAlexander Leidinger int error; 3665c8919adSAlexander Leidinger 3675c8919adSAlexander Leidinger if ((error = copyin(arg, &sa, sa_len))) 3685c8919adSAlexander Leidinger return (error); 3695c8919adSAlexander Leidinger 3705c8919adSAlexander Leidinger *(u_short *)&sa = sa.sa_family; 3715c8919adSAlexander Leidinger 3725c8919adSAlexander Leidinger error = copyout(&sa, arg, sa_len); 3735c8919adSAlexander Leidinger 3745c8919adSAlexander Leidinger return (error); 3755c8919adSAlexander Leidinger } 3765c8919adSAlexander Leidinger 3775c8919adSAlexander Leidinger static int 3785c8919adSAlexander Leidinger linux_to_bsd_sockaddr(struct sockaddr *arg, int len) 3795c8919adSAlexander Leidinger { 3805c8919adSAlexander Leidinger struct sockaddr sa; 3815c8919adSAlexander Leidinger size_t sa_len = sizeof(struct sockaddr); 3825c8919adSAlexander Leidinger int error; 3835c8919adSAlexander Leidinger 3845c8919adSAlexander Leidinger if ((error = copyin(arg, &sa, sa_len))) 3855c8919adSAlexander Leidinger return (error); 3865c8919adSAlexander Leidinger 3875c8919adSAlexander Leidinger sa.sa_family = *(sa_family_t *)&sa; 3885c8919adSAlexander Leidinger sa.sa_len = len; 3895c8919adSAlexander Leidinger 3905c8919adSAlexander Leidinger error = copyout(&sa, arg, sa_len); 3915c8919adSAlexander Leidinger 3925c8919adSAlexander Leidinger return (error); 3935c8919adSAlexander Leidinger } 3945c8919adSAlexander Leidinger 3955c8919adSAlexander Leidinger 396ca26842eSHajimu UMEMOTO static int 397ca26842eSHajimu UMEMOTO linux_sa_put(struct osockaddr *osa) 398ca26842eSHajimu UMEMOTO { 399ca26842eSHajimu UMEMOTO struct osockaddr sa; 400ca26842eSHajimu UMEMOTO int error, bdom; 401ca26842eSHajimu UMEMOTO 402ca26842eSHajimu UMEMOTO /* 403ca26842eSHajimu UMEMOTO * Only read/write the osockaddr family part, the rest is 404ca26842eSHajimu UMEMOTO * not changed. 405ca26842eSHajimu UMEMOTO */ 4064b7ef73dSDag-Erling Smørgrav error = copyin(osa, &sa, sizeof(sa.sa_family)); 407ca26842eSHajimu UMEMOTO if (error) 408ca26842eSHajimu UMEMOTO return (error); 409ca26842eSHajimu UMEMOTO 410ca26842eSHajimu UMEMOTO bdom = bsd_to_linux_domain(sa.sa_family); 411ca26842eSHajimu UMEMOTO if (bdom == -1) 412ca26842eSHajimu UMEMOTO return (EINVAL); 413ca26842eSHajimu UMEMOTO 414ca26842eSHajimu UMEMOTO sa.sa_family = bdom; 415ca26842eSHajimu UMEMOTO error = copyout(&sa, osa, sizeof(sa.sa_family)); 416ca26842eSHajimu UMEMOTO if (error) 417ca26842eSHajimu UMEMOTO return (error); 418ca26842eSHajimu UMEMOTO 419ca26842eSHajimu UMEMOTO return (0); 420ca26842eSHajimu UMEMOTO } 421ca26842eSHajimu UMEMOTO 4225a8a13e0SDavid Malone static int 423a6886ef1SMaxim Sobolev linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags, 424a6886ef1SMaxim Sobolev enum uio_seg segflg) 4255a8a13e0SDavid Malone { 4265a8a13e0SDavid Malone struct mbuf *control; 4275a8a13e0SDavid Malone struct sockaddr *to; 4285a8a13e0SDavid Malone int error; 4295a8a13e0SDavid Malone 4305a8a13e0SDavid Malone if (mp->msg_name != NULL) { 4315a8a13e0SDavid Malone error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen); 4325a8a13e0SDavid Malone if (error) 4335a8a13e0SDavid Malone return (error); 4345a8a13e0SDavid Malone mp->msg_name = to; 4355a8a13e0SDavid Malone } else 4365a8a13e0SDavid Malone to = NULL; 4375a8a13e0SDavid Malone 4385a8a13e0SDavid Malone if (mp->msg_control != NULL) { 4395a8a13e0SDavid Malone struct cmsghdr *cmsg; 4405a8a13e0SDavid Malone 4415a8a13e0SDavid Malone if (mp->msg_controllen < sizeof(struct cmsghdr)) { 4425a8a13e0SDavid Malone error = EINVAL; 4435a8a13e0SDavid Malone goto bad; 4445a8a13e0SDavid Malone } 4455a8a13e0SDavid Malone error = sockargs(&control, mp->msg_control, 4465a8a13e0SDavid Malone mp->msg_controllen, MT_CONTROL); 4475a8a13e0SDavid Malone if (error) 4485a8a13e0SDavid Malone goto bad; 4495a8a13e0SDavid Malone 4505a8a13e0SDavid Malone cmsg = mtod(control, struct cmsghdr *); 4515a8a13e0SDavid Malone cmsg->cmsg_level = linux_to_bsd_sockopt_level(cmsg->cmsg_level); 4525a8a13e0SDavid Malone } else 4535a8a13e0SDavid Malone control = NULL; 4545a8a13e0SDavid Malone 455a6886ef1SMaxim Sobolev error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control, 456a6886ef1SMaxim Sobolev segflg); 4575a8a13e0SDavid Malone 4585a8a13e0SDavid Malone bad: 4595a8a13e0SDavid Malone if (to) 4605a8a13e0SDavid Malone FREE(to, M_SONAME); 4615a8a13e0SDavid Malone return (error); 4625a8a13e0SDavid Malone } 4635a8a13e0SDavid Malone 4643f3a4815SMarcel Moolenaar /* Return 0 if IP_HDRINCL is set for the given socket. */ 465f2477ae1SMike Smith static int 466e140eb43SDavid Malone linux_check_hdrincl(struct thread *td, int s) 467f2477ae1SMike Smith { 4683db2a843SBruce Evans int error, optval, size_val; 469f2477ae1SMike Smith 470e140eb43SDavid Malone size_val = sizeof(optval); 471e140eb43SDavid Malone error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL, 472e140eb43SDavid Malone &optval, UIO_SYSSPACE, &size_val); 473e140eb43SDavid Malone if (error) 4743f3a4815SMarcel Moolenaar return (error); 4753f3a4815SMarcel Moolenaar 4763f3a4815SMarcel Moolenaar return (optval == 0); 477f2477ae1SMike Smith } 478f2477ae1SMike Smith 4795a8a13e0SDavid Malone struct linux_sendto_args { 4805a8a13e0SDavid Malone int s; 4814af27623STim J. Robbins l_uintptr_t msg; 4825a8a13e0SDavid Malone int len; 4835a8a13e0SDavid Malone int flags; 4844af27623STim J. Robbins l_uintptr_t to; 4855a8a13e0SDavid Malone int tolen; 4865a8a13e0SDavid Malone }; 4875a8a13e0SDavid Malone 488f2477ae1SMike Smith /* 489f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 490f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 491f2477ae1SMike Smith */ 492f2477ae1SMike Smith static int 49338da2381SRobert Watson linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args) 494f2477ae1SMike Smith { 495f2477ae1SMike Smith /* 496f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 497f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 498a6886ef1SMaxim Sobolev * It should include all the fields we modify (ip_len and ip_off). 499f2477ae1SMike Smith */ 500f2477ae1SMike Smith #define linux_ip_copysize 8 501f2477ae1SMike Smith 502f2477ae1SMike Smith struct ip *packet; 5035a8a13e0SDavid Malone struct msghdr msg; 504a6886ef1SMaxim Sobolev struct iovec aiov[1]; 505f2477ae1SMike Smith int error; 506f2477ae1SMike Smith 507aa675b57SDavid Schultz /* Check that the packet isn't too big or too small. */ 508aa675b57SDavid Schultz if (linux_args->len < linux_ip_copysize || 509aa675b57SDavid Schultz linux_args->len > IP_MAXPACKET) 5103f3a4815SMarcel Moolenaar return (EINVAL); 511f2477ae1SMike Smith 512a6886ef1SMaxim Sobolev packet = (struct ip *)malloc(linux_args->len, M_TEMP, M_WAITOK); 513f2477ae1SMike Smith 514a6886ef1SMaxim Sobolev /* Make kernel copy of the packet to be sent */ 5154af27623STim J. Robbins if ((error = copyin(PTRIN(linux_args->msg), packet, 516a6886ef1SMaxim Sobolev linux_args->len))) 517a6886ef1SMaxim Sobolev goto goout; 518f2477ae1SMike Smith 519f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 5205a8a13e0SDavid Malone packet->ip_len = linux_args->len; 521f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 522f2477ae1SMike Smith 523f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 5244af27623STim J. Robbins msg.msg_name = PTRIN(linux_args->to); 5255a8a13e0SDavid Malone msg.msg_namelen = linux_args->tolen; 5265a8a13e0SDavid Malone msg.msg_iov = aiov; 527a6886ef1SMaxim Sobolev msg.msg_iovlen = 1; 5285a8a13e0SDavid Malone msg.msg_control = NULL; 5295a8a13e0SDavid Malone msg.msg_flags = 0; 5305a8a13e0SDavid Malone aiov[0].iov_base = (char *)packet; 531a6886ef1SMaxim Sobolev aiov[0].iov_len = linux_args->len; 532a6886ef1SMaxim Sobolev error = linux_sendit(td, linux_args->s, &msg, linux_args->flags, 533a6886ef1SMaxim Sobolev UIO_SYSSPACE); 534a6886ef1SMaxim Sobolev goout: 535a6886ef1SMaxim Sobolev free(packet, M_TEMP); 5365a8a13e0SDavid Malone return (error); 537f2477ae1SMike Smith } 538f2477ae1SMike Smith 539c21dee17SSøren Schmidt struct linux_socket_args { 540c21dee17SSøren Schmidt int domain; 541c21dee17SSøren Schmidt int type; 542c21dee17SSøren Schmidt int protocol; 543c21dee17SSøren Schmidt }; 544c21dee17SSøren Schmidt 545c21dee17SSøren Schmidt static int 546b40ce416SJulian Elischer linux_socket(struct thread *td, struct linux_socket_args *args) 547c21dee17SSøren Schmidt { 548c21dee17SSøren Schmidt struct linux_socket_args linux_args; 549ef04503dSPeter Wemm struct socket_args /* { 550c21dee17SSøren Schmidt int domain; 551c21dee17SSøren Schmidt int type; 552c21dee17SSøren Schmidt int protocol; 553ef04503dSPeter Wemm } */ bsd_args; 554c21dee17SSøren Schmidt int error; 555f2477ae1SMike Smith int retval_socket; 556c21dee17SSøren Schmidt 5573f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5583f3a4815SMarcel Moolenaar return (error); 5593f3a4815SMarcel Moolenaar 560c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 561c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 562c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 563c21dee17SSøren Schmidt if (bsd_args.domain == -1) 5643f3a4815SMarcel Moolenaar return (EINVAL); 565f2477ae1SMike Smith 566b40ce416SJulian Elischer retval_socket = socket(td, &bsd_args); 567f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 568f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 569f2477ae1SMike Smith && bsd_args.domain == AF_INET 570f2477ae1SMike Smith && retval_socket >= 0) { 571f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 572e140eb43SDavid Malone int hdrincl; 573f2477ae1SMike Smith 574e140eb43SDavid Malone hdrincl = 1; 575e140eb43SDavid Malone /* We ignore any error returned by kern_setsockopt() */ 576e140eb43SDavid Malone kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL, 577e140eb43SDavid Malone &hdrincl, UIO_SYSSPACE, sizeof(hdrincl)); 578f2477ae1SMike Smith } 579ca26842eSHajimu UMEMOTO #ifdef INET6 580ca26842eSHajimu UMEMOTO /* 581ca26842eSHajimu UMEMOTO * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 582ca26842eSHajimu UMEMOTO * default and some apps depend on this. So, set V6ONLY to 0 583ca26842eSHajimu UMEMOTO * for Linux apps if the sysctl value is set to 1. 584ca26842eSHajimu UMEMOTO */ 58537e7a5a2SHajimu UMEMOTO if (bsd_args.domain == PF_INET6 && retval_socket >= 0 58637e7a5a2SHajimu UMEMOTO #ifndef KLD_MODULE 58737e7a5a2SHajimu UMEMOTO /* 58837e7a5a2SHajimu UMEMOTO * XXX: Avoid undefined symbol error with an IPv4 only 58937e7a5a2SHajimu UMEMOTO * kernel. 59037e7a5a2SHajimu UMEMOTO */ 59137e7a5a2SHajimu UMEMOTO && ip6_v6only 59237e7a5a2SHajimu UMEMOTO #endif 59337e7a5a2SHajimu UMEMOTO ) { 594e140eb43SDavid Malone int v6only; 595ca26842eSHajimu UMEMOTO 596e140eb43SDavid Malone v6only = 0; 597ca26842eSHajimu UMEMOTO /* We ignore any error returned by setsockopt() */ 598e140eb43SDavid Malone kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY, 599e140eb43SDavid Malone &v6only, UIO_SYSSPACE, sizeof(v6only)); 600ca26842eSHajimu UMEMOTO } 601ca26842eSHajimu UMEMOTO #endif 6023f3a4815SMarcel Moolenaar 6033f3a4815SMarcel Moolenaar return (retval_socket); 604c21dee17SSøren Schmidt } 605c21dee17SSøren Schmidt 606c21dee17SSøren Schmidt struct linux_bind_args { 607c21dee17SSøren Schmidt int s; 6084af27623STim J. Robbins l_uintptr_t name; 609c21dee17SSøren Schmidt int namelen; 610c21dee17SSøren Schmidt }; 611c21dee17SSøren Schmidt 612c21dee17SSøren Schmidt static int 613b40ce416SJulian Elischer linux_bind(struct thread *td, struct linux_bind_args *args) 614c21dee17SSøren Schmidt { 615c21dee17SSøren Schmidt struct linux_bind_args linux_args; 616ca26842eSHajimu UMEMOTO struct sockaddr *sa; 617c21dee17SSøren Schmidt int error; 618c21dee17SSøren Schmidt 6193f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6203f3a4815SMarcel Moolenaar return (error); 6213f3a4815SMarcel Moolenaar 6224af27623STim J. Robbins error = linux_getsockaddr(&sa, PTRIN(linux_args.name), 6234af27623STim J. Robbins linux_args.namelen); 624ca26842eSHajimu UMEMOTO if (error) 625ca26842eSHajimu UMEMOTO return (error); 626ca26842eSHajimu UMEMOTO 627b33887eaSJohn Baldwin error = kern_bind(td, linux_args.s, sa); 628b33887eaSJohn Baldwin free(sa, M_SONAME); 629d4b7423fSAlexander Leidinger if (error == EADDRNOTAVAIL && linux_args.namelen != sizeof(struct sockaddr_in)) 630d4b7423fSAlexander Leidinger return (EINVAL); 631b33887eaSJohn Baldwin return (error); 632c21dee17SSøren Schmidt } 633c21dee17SSøren Schmidt 63401e0ffbaSAlexander Leidinger struct linux_connect_args { 635c21dee17SSøren Schmidt int s; 6364af27623STim J. Robbins l_uintptr_t name; 637c21dee17SSøren Schmidt int namelen; 638c21dee17SSøren Schmidt }; 639b40ce416SJulian Elischer int linux_connect(struct thread *, struct linux_connect_args *); 640c21dee17SSøren Schmidt 641930a65feSAndrew Gallatin int 642b40ce416SJulian Elischer linux_connect(struct thread *td, struct linux_connect_args *args) 643c21dee17SSøren Schmidt { 64401e0ffbaSAlexander Leidinger struct linux_connect_args linux_args; 6450bf301c0SJonathan Lemon struct socket *so; 646ca26842eSHajimu UMEMOTO struct sockaddr *sa; 64739c95b83SMatthew Dillon u_int fflag; 648c21dee17SSøren Schmidt int error; 649c21dee17SSøren Schmidt 6503f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6513f3a4815SMarcel Moolenaar return (error); 6523f3a4815SMarcel Moolenaar 6534af27623STim J. Robbins error = linux_getsockaddr(&sa, 6544af27623STim J. Robbins (struct osockaddr *)PTRIN(linux_args.name), 6554d45de74SDavid Malone linux_args.namelen); 656ca26842eSHajimu UMEMOTO if (error) 657ca26842eSHajimu UMEMOTO return (error); 658ca26842eSHajimu UMEMOTO 659ca26842eSHajimu UMEMOTO error = kern_connect(td, linux_args.s, sa); 660b33887eaSJohn Baldwin free(sa, M_SONAME); 6610bf301c0SJonathan Lemon if (error != EISCONN) 6620bf301c0SJonathan Lemon return (error); 6630bf301c0SJonathan Lemon 664dad3b88aSMike Smith /* 665dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 666dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 667dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 668f7f45ac8SRobert Watson * 669f7f45ac8SRobert Watson * XXXRW: Instead of using fgetsock(), check that it is a 670f7f45ac8SRobert Watson * socket and use the file descriptor reference instead of 671f7f45ac8SRobert Watson * creating a new one. 672dad3b88aSMike Smith */ 6734641373fSJohn Baldwin NET_LOCK_GIANT(); 6744641373fSJohn Baldwin error = fgetsock(td, linux_args.s, &so, &fflag); 6754641373fSJohn Baldwin if (error == 0) { 6760bf301c0SJonathan Lemon error = EISCONN; 67739c95b83SMatthew Dillon if (fflag & FNONBLOCK) { 6784641373fSJohn Baldwin SOCK_LOCK(so); 6795002a60fSMarcel Moolenaar if (so->so_emuldata == 0) 6800bf301c0SJonathan Lemon error = so->so_error; 6810bf301c0SJonathan Lemon so->so_emuldata = (void *)1; 6824641373fSJohn Baldwin SOCK_UNLOCK(so); 683dad3b88aSMike Smith } 68439c95b83SMatthew Dillon fputsock(so); 6854641373fSJohn Baldwin } 6864641373fSJohn Baldwin NET_UNLOCK_GIANT(); 6873f3a4815SMarcel Moolenaar return (error); 688c21dee17SSøren Schmidt } 689c21dee17SSøren Schmidt 690c21dee17SSøren Schmidt struct linux_listen_args { 691c21dee17SSøren Schmidt int s; 692c21dee17SSøren Schmidt int backlog; 693c21dee17SSøren Schmidt }; 694c21dee17SSøren Schmidt 695c21dee17SSøren Schmidt static int 696b40ce416SJulian Elischer linux_listen(struct thread *td, struct linux_listen_args *args) 697c21dee17SSøren Schmidt { 698c21dee17SSøren Schmidt struct linux_listen_args linux_args; 699ef04503dSPeter Wemm struct listen_args /* { 700c21dee17SSøren Schmidt int s; 701c21dee17SSøren Schmidt int backlog; 702ef04503dSPeter Wemm } */ bsd_args; 703c21dee17SSøren Schmidt int error; 704c21dee17SSøren Schmidt 7053f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7063f3a4815SMarcel Moolenaar return (error); 7073f3a4815SMarcel Moolenaar 708c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 709c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 710b40ce416SJulian Elischer return (listen(td, &bsd_args)); 711c21dee17SSøren Schmidt } 712c21dee17SSøren Schmidt 71301e0ffbaSAlexander Leidinger struct linux_accept_args { 714c21dee17SSøren Schmidt int s; 7154af27623STim J. Robbins l_uintptr_t addr; 7164af27623STim J. Robbins l_uintptr_t namelen; 717c21dee17SSøren Schmidt }; 718c21dee17SSøren Schmidt 71901e0ffbaSAlexander Leidinger static int 720b40ce416SJulian Elischer linux_accept(struct thread *td, struct linux_accept_args *args) 721c21dee17SSøren Schmidt { 72201e0ffbaSAlexander Leidinger struct linux_accept_args linux_args; 723ef04503dSPeter Wemm struct accept_args /* { 724c21dee17SSøren Schmidt int s; 7253db2a843SBruce Evans struct sockaddr * __restrict name; 7263db2a843SBruce Evans socklen_t * __restrict anamelen; 727ef04503dSPeter Wemm } */ bsd_args; 7282ca25ab5SJohn Baldwin int error, fd; 729c21dee17SSøren Schmidt 7303f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7313f3a4815SMarcel Moolenaar return (error); 7323f3a4815SMarcel Moolenaar 733c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 7343db2a843SBruce Evans /* XXX: */ 7354af27623STim J. Robbins bsd_args.name = (struct sockaddr * __restrict)PTRIN(linux_args.addr); 7364af27623STim J. Robbins bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */ 7375c8919adSAlexander Leidinger error = accept(td, &bsd_args); 7385c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name); 739d4b7423fSAlexander Leidinger if (error) { 740d4b7423fSAlexander Leidinger if (error == EFAULT && linux_args.namelen != sizeof(struct sockaddr_in)) 741d4b7423fSAlexander Leidinger return (EINVAL); 742dba5ab66SMarcel Moolenaar return (error); 743d4b7423fSAlexander Leidinger } 744ca26842eSHajimu UMEMOTO if (linux_args.addr) { 7454af27623STim J. Robbins error = linux_sa_put(PTRIN(linux_args.addr)); 746ca26842eSHajimu UMEMOTO if (error) { 747c1cccebeSJohn Baldwin (void)kern_close(td, td->td_retval[0]); 748ca26842eSHajimu UMEMOTO return (error); 749ca26842eSHajimu UMEMOTO } 750ca26842eSHajimu UMEMOTO } 751dba5ab66SMarcel Moolenaar 752dba5ab66SMarcel Moolenaar /* 753dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 754dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 755dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 756dba5ab66SMarcel Moolenaar */ 7572ca25ab5SJohn Baldwin fd = td->td_retval[0]; 7582ca25ab5SJohn Baldwin (void)kern_fcntl(td, fd, F_SETFL, 0); 7592ca25ab5SJohn Baldwin td->td_retval[0] = fd; 760dba5ab66SMarcel Moolenaar return (0); 761c21dee17SSøren Schmidt } 762c21dee17SSøren Schmidt 76301e0ffbaSAlexander Leidinger struct linux_getsockname_args { 764c21dee17SSøren Schmidt int s; 7654af27623STim J. Robbins l_uintptr_t addr; 7664af27623STim J. Robbins l_uintptr_t namelen; 767c21dee17SSøren Schmidt }; 768c21dee17SSøren Schmidt 76901e0ffbaSAlexander Leidinger static int 770b40ce416SJulian Elischer linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 771c21dee17SSøren Schmidt { 77201e0ffbaSAlexander Leidinger struct linux_getsockname_args linux_args; 773ef04503dSPeter Wemm struct getsockname_args /* { 774c21dee17SSøren Schmidt int fdes; 7753db2a843SBruce Evans struct sockaddr * __restrict asa; 7763db2a843SBruce Evans socklen_t * __restrict alen; 777ef04503dSPeter Wemm } */ bsd_args; 778c21dee17SSøren Schmidt int error; 779c21dee17SSøren Schmidt 7803f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7813f3a4815SMarcel Moolenaar return (error); 7823f3a4815SMarcel Moolenaar 783c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 7843db2a843SBruce Evans /* XXX: */ 7854af27623STim J. Robbins bsd_args.asa = (struct sockaddr * __restrict)PTRIN(linux_args.addr); 7864af27623STim J. Robbins bsd_args.alen = PTRIN(linux_args.namelen); /* XXX */ 7875c8919adSAlexander Leidinger error = getsockname(td, &bsd_args); 7885c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa); 789ca26842eSHajimu UMEMOTO if (error) 790ca26842eSHajimu UMEMOTO return (error); 7914af27623STim J. Robbins error = linux_sa_put(PTRIN(linux_args.addr)); 792ca26842eSHajimu UMEMOTO if (error) 793ca26842eSHajimu UMEMOTO return (error); 794ca26842eSHajimu UMEMOTO return (0); 795c21dee17SSøren Schmidt } 796c21dee17SSøren Schmidt 79701e0ffbaSAlexander Leidinger struct linux_getpeername_args { 798c21dee17SSøren Schmidt int s; 7994af27623STim J. Robbins l_uintptr_t addr; 8004af27623STim J. Robbins l_uintptr_t namelen; 801c21dee17SSøren Schmidt }; 802c21dee17SSøren Schmidt 80301e0ffbaSAlexander Leidinger static int 804b40ce416SJulian Elischer linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 805c21dee17SSøren Schmidt { 80601e0ffbaSAlexander Leidinger struct linux_getpeername_args linux_args; 8075c8919adSAlexander Leidinger struct getpeername_args /* { 808c21dee17SSøren Schmidt int fdes; 809c21dee17SSøren Schmidt caddr_t asa; 810c21dee17SSøren Schmidt int *alen; 811ef04503dSPeter Wemm } */ bsd_args; 812c21dee17SSøren Schmidt int error; 813c21dee17SSøren Schmidt 8143f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8153f3a4815SMarcel Moolenaar return (error); 8163f3a4815SMarcel Moolenaar 817c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 8185c8919adSAlexander Leidinger bsd_args.asa = (struct sockaddr *)PTRIN(linux_args.addr); 8194af27623STim J. Robbins bsd_args.alen = (int *)PTRIN(linux_args.namelen); 8205c8919adSAlexander Leidinger error = getpeername(td, &bsd_args); 8215c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa); 822ca26842eSHajimu UMEMOTO if (error) 823ca26842eSHajimu UMEMOTO return (error); 8244af27623STim J. Robbins error = linux_sa_put(PTRIN(linux_args.addr)); 825ca26842eSHajimu UMEMOTO if (error) 826ca26842eSHajimu UMEMOTO return (error); 827ca26842eSHajimu UMEMOTO return (0); 828c21dee17SSøren Schmidt } 829c21dee17SSøren Schmidt 83001e0ffbaSAlexander Leidinger struct linux_socketpair_args { 831c21dee17SSøren Schmidt int domain; 832c21dee17SSøren Schmidt int type; 833c21dee17SSøren Schmidt int protocol; 8344af27623STim J. Robbins l_uintptr_t rsv; 835c21dee17SSøren Schmidt }; 836c21dee17SSøren Schmidt 83701e0ffbaSAlexander Leidinger static int 838b40ce416SJulian Elischer linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 839c21dee17SSøren Schmidt { 84001e0ffbaSAlexander Leidinger struct linux_socketpair_args linux_args; 841ef04503dSPeter Wemm struct socketpair_args /* { 842c21dee17SSøren Schmidt int domain; 843c21dee17SSøren Schmidt int type; 844c21dee17SSøren Schmidt int protocol; 845c21dee17SSøren Schmidt int *rsv; 846ef04503dSPeter Wemm } */ bsd_args; 847c21dee17SSøren Schmidt int error; 848c21dee17SSøren Schmidt 8493f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8503f3a4815SMarcel Moolenaar return (error); 8513f3a4815SMarcel Moolenaar 852c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 853c21dee17SSøren Schmidt if (bsd_args.domain == -1) 8543f3a4815SMarcel Moolenaar return (EINVAL); 8553f3a4815SMarcel Moolenaar 856c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 857c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 8584af27623STim J. Robbins bsd_args.rsv = (int *)PTRIN(linux_args.rsv); 859b40ce416SJulian Elischer return (socketpair(td, &bsd_args)); 860c21dee17SSøren Schmidt } 861c21dee17SSøren Schmidt 86201e0ffbaSAlexander Leidinger struct linux_send_args { 863c21dee17SSøren Schmidt int s; 8644af27623STim J. Robbins l_uintptr_t msg; 865c21dee17SSøren Schmidt int len; 866c21dee17SSøren Schmidt int flags; 867c21dee17SSøren Schmidt }; 868c21dee17SSøren Schmidt 86901e0ffbaSAlexander Leidinger static int 870b40ce416SJulian Elischer linux_send(struct thread *td, struct linux_send_args *args) 871c21dee17SSøren Schmidt { 87201e0ffbaSAlexander Leidinger struct linux_send_args linux_args; 87387d72a8fSPoul-Henning Kamp struct sendto_args /* { 874c21dee17SSøren Schmidt int s; 875c21dee17SSøren Schmidt caddr_t buf; 876044af7c3SJonathan Mini int len; 877c21dee17SSøren Schmidt int flags; 87887d72a8fSPoul-Henning Kamp caddr_t to; 87987d72a8fSPoul-Henning Kamp int tolen; 880ef04503dSPeter Wemm } */ bsd_args; 8818d6e40c3SMaxim Sobolev int error; 882c21dee17SSøren Schmidt 8833f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8843f3a4815SMarcel Moolenaar return (error); 8853f3a4815SMarcel Moolenaar 886c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 8874af27623STim J. Robbins bsd_args.buf = (caddr_t)PTRIN(linux_args.msg); 888c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 889c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 89087d72a8fSPoul-Henning Kamp bsd_args.to = NULL; 89187d72a8fSPoul-Henning Kamp bsd_args.tolen = 0; 8928d6e40c3SMaxim Sobolev return sendto(td, &bsd_args); 893c21dee17SSøren Schmidt } 894c21dee17SSøren Schmidt 89501e0ffbaSAlexander Leidinger struct linux_recv_args { 896c21dee17SSøren Schmidt int s; 8974af27623STim J. Robbins l_uintptr_t msg; 898c21dee17SSøren Schmidt int len; 899c21dee17SSøren Schmidt int flags; 900c21dee17SSøren Schmidt }; 901c21dee17SSøren Schmidt 90201e0ffbaSAlexander Leidinger static int 903b40ce416SJulian Elischer linux_recv(struct thread *td, struct linux_recv_args *args) 904c21dee17SSøren Schmidt { 90501e0ffbaSAlexander Leidinger struct linux_recv_args linux_args; 90687d72a8fSPoul-Henning Kamp struct recvfrom_args /* { 907c21dee17SSøren Schmidt int s; 908c21dee17SSøren Schmidt caddr_t buf; 909c21dee17SSøren Schmidt int len; 910c21dee17SSøren Schmidt int flags; 91187d72a8fSPoul-Henning Kamp struct sockaddr *from; 91287d72a8fSPoul-Henning Kamp socklen_t fromlenaddr; 913ef04503dSPeter Wemm } */ bsd_args; 914c21dee17SSøren Schmidt int error; 915c21dee17SSøren Schmidt 9163f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9173f3a4815SMarcel Moolenaar return (error); 9183f3a4815SMarcel Moolenaar 919c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 9204af27623STim J. Robbins bsd_args.buf = (caddr_t)PTRIN(linux_args.msg); 921c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 922c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 92387d72a8fSPoul-Henning Kamp bsd_args.from = NULL; 92487d72a8fSPoul-Henning Kamp bsd_args.fromlenaddr = 0; 92587d72a8fSPoul-Henning Kamp return (recvfrom(td, &bsd_args)); 926c21dee17SSøren Schmidt } 927c21dee17SSøren Schmidt 928c21dee17SSøren Schmidt static int 929b40ce416SJulian Elischer linux_sendto(struct thread *td, struct linux_sendto_args *args) 930c21dee17SSøren Schmidt { 931c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 9325a8a13e0SDavid Malone struct msghdr msg; 9335a8a13e0SDavid Malone struct iovec aiov; 9345a8a13e0SDavid Malone int error; 935c21dee17SSøren Schmidt 9363f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9373f3a4815SMarcel Moolenaar return (error); 9383f3a4815SMarcel Moolenaar 939e140eb43SDavid Malone if (linux_check_hdrincl(td, linux_args.s) == 0) 940f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 941e140eb43SDavid Malone return (linux_sendto_hdrincl(td, &linux_args)); 942f2477ae1SMike Smith 9434af27623STim J. Robbins msg.msg_name = PTRIN(linux_args.to); 9445a8a13e0SDavid Malone msg.msg_namelen = linux_args.tolen; 9455a8a13e0SDavid Malone msg.msg_iov = &aiov; 9465a8a13e0SDavid Malone msg.msg_iovlen = 1; 9475a8a13e0SDavid Malone msg.msg_control = NULL; 9485a8a13e0SDavid Malone msg.msg_flags = 0; 9494af27623STim J. Robbins aiov.iov_base = PTRIN(linux_args.msg); 9505a8a13e0SDavid Malone aiov.iov_len = linux_args.len; 951a6886ef1SMaxim Sobolev error = linux_sendit(td, linux_args.s, &msg, linux_args.flags, 952a6886ef1SMaxim Sobolev UIO_USERSPACE); 9535a8a13e0SDavid Malone return (error); 954c21dee17SSøren Schmidt } 955c21dee17SSøren Schmidt 95601e0ffbaSAlexander Leidinger struct linux_recvfrom_args { 957c21dee17SSøren Schmidt int s; 9584af27623STim J. Robbins l_uintptr_t buf; 959c21dee17SSøren Schmidt int len; 960c21dee17SSøren Schmidt int flags; 9614af27623STim J. Robbins l_uintptr_t from; 9624af27623STim J. Robbins l_uintptr_t fromlen; 963c21dee17SSøren Schmidt }; 964c21dee17SSøren Schmidt 96501e0ffbaSAlexander Leidinger static int 966b40ce416SJulian Elischer linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 967c21dee17SSøren Schmidt { 96801e0ffbaSAlexander Leidinger struct linux_recvfrom_args linux_args; 969ef04503dSPeter Wemm struct recvfrom_args /* { 970c21dee17SSøren Schmidt int s; 971c21dee17SSøren Schmidt caddr_t buf; 972c21dee17SSøren Schmidt size_t len; 973c21dee17SSøren Schmidt int flags; 9743db2a843SBruce Evans struct sockaddr * __restrict from; 9753db2a843SBruce Evans socklen_t * __restrict fromlenaddr; 976ef04503dSPeter Wemm } */ bsd_args; 9775c8919adSAlexander Leidinger size_t len; 978c21dee17SSøren Schmidt int error; 979c21dee17SSøren Schmidt 9803f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9813f3a4815SMarcel Moolenaar return (error); 9823f3a4815SMarcel Moolenaar 9835c8919adSAlexander Leidinger if ((error = copyin(PTRIN(linux_args.fromlen), &len, sizeof(size_t)))) 9845c8919adSAlexander Leidinger return (error); 9855c8919adSAlexander Leidinger 986c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 9874af27623STim J. Robbins bsd_args.buf = PTRIN(linux_args.buf); 988c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 98940dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 9903db2a843SBruce Evans /* XXX: */ 9914af27623STim J. Robbins bsd_args.from = (struct sockaddr * __restrict)PTRIN(linux_args.from); 9924af27623STim J. Robbins bsd_args.fromlenaddr = PTRIN(linux_args.fromlen);/* XXX */ 9935c8919adSAlexander Leidinger 9945c8919adSAlexander Leidinger linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len); 9955c8919adSAlexander Leidinger error = recvfrom(td, &bsd_args); 9965c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from); 9975c8919adSAlexander Leidinger 998ca26842eSHajimu UMEMOTO if (error) 999ca26842eSHajimu UMEMOTO return (error); 1000ca26842eSHajimu UMEMOTO if (linux_args.from) { 10014af27623STim J. Robbins error = linux_sa_put((struct osockaddr *) 10024af27623STim J. Robbins PTRIN(linux_args.from)); 1003ca26842eSHajimu UMEMOTO if (error) 1004ca26842eSHajimu UMEMOTO return (error); 1005ca26842eSHajimu UMEMOTO } 1006ca26842eSHajimu UMEMOTO return (0); 1007ca26842eSHajimu UMEMOTO } 1008ca26842eSHajimu UMEMOTO 100901e0ffbaSAlexander Leidinger struct linux_sendmsg_args { 1010ca26842eSHajimu UMEMOTO int s; 10114af27623STim J. Robbins l_uintptr_t msg; 1012ca26842eSHajimu UMEMOTO int flags; 1013ca26842eSHajimu UMEMOTO }; 1014ca26842eSHajimu UMEMOTO 101501e0ffbaSAlexander Leidinger static int 1016ca26842eSHajimu UMEMOTO linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 1017ca26842eSHajimu UMEMOTO { 101801e0ffbaSAlexander Leidinger struct linux_sendmsg_args linux_args; 1019ca26842eSHajimu UMEMOTO struct msghdr msg; 1020552afd9cSPoul-Henning Kamp struct iovec *iov; 1021ca26842eSHajimu UMEMOTO int error; 1022ca26842eSHajimu UMEMOTO 10234af27623STim J. Robbins /* XXXTJR sendmsg is broken on amd64 */ 10244af27623STim J. Robbins 1025552afd9cSPoul-Henning Kamp error = copyin(args, &linux_args, sizeof(linux_args)); 1026552afd9cSPoul-Henning Kamp if (error) 1027ca26842eSHajimu UMEMOTO return (error); 10284af27623STim J. Robbins error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg)); 1029ca26842eSHajimu UMEMOTO if (error) 1030ca26842eSHajimu UMEMOTO return (error); 1031d72a6158SRobert Watson 1032d72a6158SRobert Watson /* 1033d72a6158SRobert Watson * Some Linux applications (ping) define a non-NULL control data 1034d72a6158SRobert Watson * pointer, but a msg_controllen of 0, which is not allowed in the 1035d72a6158SRobert Watson * FreeBSD system call interface. NULL the msg_control pointer in 1036d72a6158SRobert Watson * order to handle this case. This should be checked, but allows the 1037d72a6158SRobert Watson * Linux ping to work. 1038d72a6158SRobert Watson */ 1039d72a6158SRobert Watson if (msg.msg_control != NULL && msg.msg_controllen == 0) 1040d72a6158SRobert Watson msg.msg_control = NULL; 1041552afd9cSPoul-Henning Kamp error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 1042552afd9cSPoul-Henning Kamp if (error) 1043552afd9cSPoul-Henning Kamp return (error); 10445a8a13e0SDavid Malone msg.msg_iov = iov; 10455a8a13e0SDavid Malone msg.msg_flags = 0; 1046a6886ef1SMaxim Sobolev error = linux_sendit(td, linux_args.s, &msg, linux_args.flags, 1047a6886ef1SMaxim Sobolev UIO_USERSPACE); 1048552afd9cSPoul-Henning Kamp free(iov, M_IOV); 1049ca26842eSHajimu UMEMOTO return (error); 1050c21dee17SSøren Schmidt } 1051c21dee17SSøren Schmidt 105201e0ffbaSAlexander Leidinger struct linux_recvmsg_args { 105340dbba57SAssar Westerlund int s; 10544af27623STim J. Robbins l_uintptr_t msg; 105540dbba57SAssar Westerlund int flags; 105640dbba57SAssar Westerlund }; 105740dbba57SAssar Westerlund 105801e0ffbaSAlexander Leidinger static int 1059b40ce416SJulian Elischer linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 106040dbba57SAssar Westerlund { 106101e0ffbaSAlexander Leidinger struct linux_recvmsg_args linux_args; 106240dbba57SAssar Westerlund struct recvmsg_args /* { 106340dbba57SAssar Westerlund int s; 106440dbba57SAssar Westerlund struct msghdr *msg; 106540dbba57SAssar Westerlund int flags; 106640dbba57SAssar Westerlund } */ bsd_args; 1067ca26842eSHajimu UMEMOTO struct msghdr msg; 106884b11cd8SMitsuru IWASAKI struct cmsghdr *cmsg; 106940dbba57SAssar Westerlund int error; 107040dbba57SAssar Westerlund 10714af27623STim J. Robbins /* XXXTJR recvmsg is broken on amd64 */ 10724af27623STim J. Robbins 107340dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 107440dbba57SAssar Westerlund return (error); 107540dbba57SAssar Westerlund 1076d0b2365eSKonstantin Belousov if ((error = copyin(PTRIN(args->msg), &msg, sizeof (msg)))) 1077d0b2365eSKonstantin Belousov return (error); 1078d0b2365eSKonstantin Belousov 107940dbba57SAssar Westerlund bsd_args.s = linux_args.s; 10804af27623STim J. Robbins bsd_args.msg = PTRIN(linux_args.msg); 108140dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 10825c8919adSAlexander Leidinger if (msg.msg_name) { 10835c8919adSAlexander Leidinger linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name, 10845c8919adSAlexander Leidinger msg.msg_namelen); 10855c8919adSAlexander Leidinger error = recvmsg(td, &bsd_args); 10865c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)msg.msg_name); 10875c8919adSAlexander Leidinger } else 1088ca26842eSHajimu UMEMOTO error = recvmsg(td, &bsd_args); 1089ca26842eSHajimu UMEMOTO if (error) 1090ca26842eSHajimu UMEMOTO return (error); 1091ca26842eSHajimu UMEMOTO 109272261b9fSDag-Erling Smørgrav if (bsd_args.msg->msg_control != NULL && 109372261b9fSDag-Erling Smørgrav bsd_args.msg->msg_controllen > 0) { 109484b11cd8SMitsuru IWASAKI cmsg = (struct cmsghdr*)bsd_args.msg->msg_control; 109584b11cd8SMitsuru IWASAKI cmsg->cmsg_level = bsd_to_linux_sockopt_level(cmsg->cmsg_level); 109684b11cd8SMitsuru IWASAKI } 109784b11cd8SMitsuru IWASAKI 10984af27623STim J. Robbins error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg)); 1099ca26842eSHajimu UMEMOTO if (error) 1100ca26842eSHajimu UMEMOTO return (error); 1101ca26842eSHajimu UMEMOTO if (msg.msg_name && msg.msg_namelen > 2) 1102ca26842eSHajimu UMEMOTO error = linux_sa_put(msg.msg_name); 1103ca26842eSHajimu UMEMOTO return (error); 110440dbba57SAssar Westerlund } 110540dbba57SAssar Westerlund 1106c21dee17SSøren Schmidt struct linux_shutdown_args { 1107c21dee17SSøren Schmidt int s; 1108c21dee17SSøren Schmidt int how; 1109c21dee17SSøren Schmidt }; 1110c21dee17SSøren Schmidt 1111c21dee17SSøren Schmidt static int 1112b40ce416SJulian Elischer linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1113c21dee17SSøren Schmidt { 1114c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 1115ef04503dSPeter Wemm struct shutdown_args /* { 1116c21dee17SSøren Schmidt int s; 1117c21dee17SSøren Schmidt int how; 1118ef04503dSPeter Wemm } */ bsd_args; 1119c21dee17SSøren Schmidt int error; 1120c21dee17SSøren Schmidt 11213f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11223f3a4815SMarcel Moolenaar return (error); 11233f3a4815SMarcel Moolenaar 1124c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1125c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 1126b40ce416SJulian Elischer return (shutdown(td, &bsd_args)); 1127c21dee17SSøren Schmidt } 1128c21dee17SSøren Schmidt 1129c21dee17SSøren Schmidt struct linux_setsockopt_args { 1130c21dee17SSøren Schmidt int s; 1131c21dee17SSøren Schmidt int level; 1132c21dee17SSøren Schmidt int optname; 11334af27623STim J. Robbins l_uintptr_t optval; 1134c21dee17SSøren Schmidt int optlen; 1135c21dee17SSøren Schmidt }; 1136c21dee17SSøren Schmidt 1137c21dee17SSøren Schmidt static int 1138b40ce416SJulian Elischer linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1139c21dee17SSøren Schmidt { 1140c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 1141ef04503dSPeter Wemm struct setsockopt_args /* { 1142c21dee17SSøren Schmidt int s; 1143c21dee17SSøren Schmidt int level; 1144c21dee17SSøren Schmidt int name; 1145c21dee17SSøren Schmidt caddr_t val; 1146c21dee17SSøren Schmidt int valsize; 1147ef04503dSPeter Wemm } */ bsd_args; 1148c21dee17SSøren Schmidt int error, name; 1149c21dee17SSøren Schmidt 11503f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11513f3a4815SMarcel Moolenaar return (error); 11523f3a4815SMarcel Moolenaar 1153c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1154c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1155c21dee17SSøren Schmidt switch (bsd_args.level) { 1156c21dee17SSøren Schmidt case SOL_SOCKET: 1157c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1158c21dee17SSøren Schmidt break; 1159c21dee17SSøren Schmidt case IPPROTO_IP: 1160c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1161c21dee17SSøren Schmidt break; 1162dad3b88aSMike Smith case IPPROTO_TCP: 1163dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1164dad3b88aSMike Smith name = linux_args.optname; 1165dad3b88aSMike Smith break; 1166c21dee17SSøren Schmidt default: 11673f3a4815SMarcel Moolenaar name = -1; 11683f3a4815SMarcel Moolenaar break; 1169c21dee17SSøren Schmidt } 1170c21dee17SSøren Schmidt if (name == -1) 1171d4b7423fSAlexander Leidinger return (ENOPROTOOPT); 11723f3a4815SMarcel Moolenaar 1173c21dee17SSøren Schmidt bsd_args.name = name; 11744af27623STim J. Robbins bsd_args.val = PTRIN(linux_args.optval); 1175c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 11765c8919adSAlexander Leidinger 11775c8919adSAlexander Leidinger if (name == IPV6_NEXTHOP) { 11785c8919adSAlexander Leidinger linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val, 11795c8919adSAlexander Leidinger bsd_args.valsize); 11805c8919adSAlexander Leidinger error = setsockopt(td, &bsd_args); 11815c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val); 11825c8919adSAlexander Leidinger } else 11835c8919adSAlexander Leidinger error = setsockopt(td, &bsd_args); 11845c8919adSAlexander Leidinger 11855c8919adSAlexander Leidinger return (error); 1186c21dee17SSøren Schmidt } 1187c21dee17SSøren Schmidt 1188c21dee17SSøren Schmidt struct linux_getsockopt_args { 1189c21dee17SSøren Schmidt int s; 1190c21dee17SSøren Schmidt int level; 1191c21dee17SSøren Schmidt int optname; 11924af27623STim J. Robbins l_uintptr_t optval; 11934af27623STim J. Robbins l_uintptr_t optlen; 1194c21dee17SSøren Schmidt }; 1195c21dee17SSøren Schmidt 1196c21dee17SSøren Schmidt static int 1197b40ce416SJulian Elischer linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1198c21dee17SSøren Schmidt { 1199c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 1200ef04503dSPeter Wemm struct getsockopt_args /* { 1201c21dee17SSøren Schmidt int s; 1202c21dee17SSøren Schmidt int level; 1203c21dee17SSøren Schmidt int name; 1204c21dee17SSøren Schmidt caddr_t val; 1205c21dee17SSøren Schmidt int *avalsize; 1206ef04503dSPeter Wemm } */ bsd_args; 1207c21dee17SSøren Schmidt int error, name; 1208c21dee17SSøren Schmidt 12093f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 12103f3a4815SMarcel Moolenaar return (error); 12113f3a4815SMarcel Moolenaar 1212c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1213c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1214c21dee17SSøren Schmidt switch (bsd_args.level) { 1215c21dee17SSøren Schmidt case SOL_SOCKET: 1216c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1217c21dee17SSøren Schmidt break; 1218c21dee17SSøren Schmidt case IPPROTO_IP: 1219c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1220c21dee17SSøren Schmidt break; 1221dad3b88aSMike Smith case IPPROTO_TCP: 1222dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1223dad3b88aSMike Smith name = linux_args.optname; 1224dad3b88aSMike Smith break; 1225c21dee17SSøren Schmidt default: 12263f3a4815SMarcel Moolenaar name = -1; 12273f3a4815SMarcel Moolenaar break; 1228c21dee17SSøren Schmidt } 1229c21dee17SSøren Schmidt if (name == -1) 12303f3a4815SMarcel Moolenaar return (EINVAL); 12313f3a4815SMarcel Moolenaar 1232f2477ae1SMike Smith bsd_args.name = name; 12334af27623STim J. Robbins bsd_args.val = PTRIN(linux_args.optval); 12344af27623STim J. Robbins bsd_args.avalsize = PTRIN(linux_args.optlen); 12355c8919adSAlexander Leidinger 12365c8919adSAlexander Leidinger if (name == IPV6_NEXTHOP) { 12375c8919adSAlexander Leidinger error = getsockopt(td, &bsd_args); 12385c8919adSAlexander Leidinger bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val); 12395c8919adSAlexander Leidinger } else 12405c8919adSAlexander Leidinger error = getsockopt(td, &bsd_args); 12415c8919adSAlexander Leidinger 12425c8919adSAlexander Leidinger return (error); 1243c21dee17SSøren Schmidt } 1244c21dee17SSøren Schmidt 1245c21dee17SSøren Schmidt int 1246b40ce416SJulian Elischer linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1247c21dee17SSøren Schmidt { 12484af27623STim J. Robbins void *arg = (void *)(intptr_t)args->args; 12493f3a4815SMarcel Moolenaar 1250c21dee17SSøren Schmidt switch (args->what) { 1251c21dee17SSøren Schmidt case LINUX_SOCKET: 1252b40ce416SJulian Elischer return (linux_socket(td, arg)); 1253c21dee17SSøren Schmidt case LINUX_BIND: 1254b40ce416SJulian Elischer return (linux_bind(td, arg)); 1255c21dee17SSøren Schmidt case LINUX_CONNECT: 1256b40ce416SJulian Elischer return (linux_connect(td, arg)); 1257c21dee17SSøren Schmidt case LINUX_LISTEN: 1258b40ce416SJulian Elischer return (linux_listen(td, arg)); 1259c21dee17SSøren Schmidt case LINUX_ACCEPT: 1260b40ce416SJulian Elischer return (linux_accept(td, arg)); 1261c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 1262b40ce416SJulian Elischer return (linux_getsockname(td, arg)); 1263c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 1264b40ce416SJulian Elischer return (linux_getpeername(td, arg)); 1265c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 1266b40ce416SJulian Elischer return (linux_socketpair(td, arg)); 1267c21dee17SSøren Schmidt case LINUX_SEND: 1268b40ce416SJulian Elischer return (linux_send(td, arg)); 1269c21dee17SSøren Schmidt case LINUX_RECV: 1270b40ce416SJulian Elischer return (linux_recv(td, arg)); 1271c21dee17SSøren Schmidt case LINUX_SENDTO: 1272b40ce416SJulian Elischer return (linux_sendto(td, arg)); 1273c21dee17SSøren Schmidt case LINUX_RECVFROM: 1274b40ce416SJulian Elischer return (linux_recvfrom(td, arg)); 1275c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 1276b40ce416SJulian Elischer return (linux_shutdown(td, arg)); 1277c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 1278b40ce416SJulian Elischer return (linux_setsockopt(td, arg)); 1279c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 1280b40ce416SJulian Elischer return (linux_getsockopt(td, arg)); 1281e76bba09SSøren Schmidt case LINUX_SENDMSG: 1282ca26842eSHajimu UMEMOTO return (linux_sendmsg(td, arg)); 1283e76bba09SSøren Schmidt case LINUX_RECVMSG: 1284b40ce416SJulian Elischer return (linux_recvmsg(td, arg)); 1285c21dee17SSøren Schmidt } 12863f3a4815SMarcel Moolenaar 12873f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 12883f3a4815SMarcel Moolenaar return (ENOSYS); 1289c21dee17SSøren Schmidt } 1290