1c21dee17SSøren Schmidt /*- 2c21dee17SSøren Schmidt * Copyright (c) 1995 S�ren Schmidt 3c21dee17SSøren Schmidt * All rights reserved. 4c21dee17SSøren Schmidt * 5c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without 6c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions 7c21dee17SSøren Schmidt * are met: 8c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 9c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer 10c21dee17SSøren Schmidt * in this position and unchanged. 11c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 12c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 13c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution. 14c21dee17SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 1521dc7d4fSJens Schweikhardt * derived from this software without specific prior written permission 16c21dee17SSøren Schmidt * 17c21dee17SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18c21dee17SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19c21dee17SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20c21dee17SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21c21dee17SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22c21dee17SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23c21dee17SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24c21dee17SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25c21dee17SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26c21dee17SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27c21dee17SSøren Schmidt * 28c3aac50fSPeter Wemm * $FreeBSD$ 29c21dee17SSøren Schmidt */ 30c21dee17SSøren Schmidt 311f3dad5aSBruce Evans /* XXX we use functions that might not exist. */ 325591b823SEivind Eklund #include "opt_compat.h" 33ca26842eSHajimu UMEMOTO #include "opt_inet6.h" 345591b823SEivind Eklund 355591b823SEivind Eklund #ifndef COMPAT_43 365591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 375591b823SEivind Eklund #endif 381f3dad5aSBruce Evans 39c21dee17SSøren Schmidt #include <sys/param.h> 40f2477ae1SMike Smith #include <sys/proc.h> 41c21dee17SSøren Schmidt #include <sys/systm.h> 421f3dad5aSBruce Evans #include <sys/sysproto.h> 43dad3b88aSMike Smith #include <sys/fcntl.h> 440bf301c0SJonathan Lemon #include <sys/file.h> 45ca26842eSHajimu UMEMOTO #include <sys/malloc.h> 46c21dee17SSøren Schmidt #include <sys/socket.h> 470bf301c0SJonathan Lemon #include <sys/socketvar.h> 48ca26842eSHajimu UMEMOTO #include <sys/syscallsubr.h> 4908637435SBruce Evans #include <sys/uio.h> 50ca26842eSHajimu UMEMOTO #include <sys/syslog.h> 511f3dad5aSBruce Evans 52c21dee17SSøren Schmidt #include <netinet/in.h> 53f2477ae1SMike Smith #include <netinet/in_systm.h> 54f2477ae1SMike Smith #include <netinet/ip.h> 55ca26842eSHajimu UMEMOTO #ifdef INET6 56ca26842eSHajimu UMEMOTO #include <netinet/ip6.h> 57ca26842eSHajimu UMEMOTO #include <netinet6/ip6_var.h> 58ca26842eSHajimu UMEMOTO #endif 59c21dee17SSøren Schmidt 60ac951e62SMarcel Moolenaar #include <machine/../linux/linux.h> 61ebea8660SMarcel Moolenaar #include <machine/../linux/linux_proto.h> 6240dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 63ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 64c21dee17SSøren Schmidt 65ca26842eSHajimu UMEMOTO #include <machine/limits.h> 66ca26842eSHajimu UMEMOTO 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 117ca26842eSHajimu UMEMOTO MALLOC(kosa, struct osockaddr *, alloclen, mtype, 0); 118ca26842eSHajimu UMEMOTO 119ca26842eSHajimu UMEMOTO if ((error = copyin(osa, (caddr_t) 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 */ 368ca26842eSHajimu UMEMOTO error = copyin((caddr_t) osa, (caddr_t) &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 386b40ce416SJulian Elischer linux_check_hdrincl(struct thread *td, 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; 396f2477ae1SMike Smith caddr_t sg, val, valsize; 397f2477ae1SMike Smith int size_val = sizeof val; 398f2477ae1SMike Smith int optval; 399f2477ae1SMike Smith 400f2477ae1SMike Smith sg = stackgap_init(); 401f2477ae1SMike Smith val = stackgap_alloc(&sg, sizeof(int)); 402f2477ae1SMike Smith valsize = stackgap_alloc(&sg, sizeof(int)); 403f2477ae1SMike Smith 404f2477ae1SMike Smith if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 4053f3a4815SMarcel Moolenaar return (error); 4063f3a4815SMarcel Moolenaar 407f2477ae1SMike Smith bsd_args.s = s; 408f2477ae1SMike Smith bsd_args.level = IPPROTO_IP; 409f2477ae1SMike Smith bsd_args.name = IP_HDRINCL; 410f2477ae1SMike Smith bsd_args.val = val; 411f2477ae1SMike Smith bsd_args.avalsize = (int *)valsize; 412b40ce416SJulian Elischer if ((error = getsockopt(td, &bsd_args))) 4133f3a4815SMarcel Moolenaar return (error); 4143f3a4815SMarcel Moolenaar 415f2477ae1SMike Smith if ((error = copyin(val, &optval, sizeof(optval)))) 4163f3a4815SMarcel Moolenaar return (error); 4173f3a4815SMarcel Moolenaar 4183f3a4815SMarcel Moolenaar return (optval == 0); 419f2477ae1SMike Smith } 420f2477ae1SMike Smith 421f2477ae1SMike Smith /* 422f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 423f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 424f2477ae1SMike Smith */ 425f2477ae1SMike Smith static int 426b40ce416SJulian Elischer linux_sendto_hdrincl(struct thread *td, struct sendto_args *bsd_args) 427f2477ae1SMike Smith { 428f2477ae1SMike Smith /* 429f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 430f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 431f2477ae1SMike Smith * It should include all the fields we modify (ip_len and ip_off) 432f2477ae1SMike Smith * and be as small as possible to minimize copying overhead. 433f2477ae1SMike Smith */ 434f2477ae1SMike Smith #define linux_ip_copysize 8 435f2477ae1SMike Smith 436f2477ae1SMike Smith caddr_t sg; 437f2477ae1SMike Smith struct ip *packet; 438f2477ae1SMike Smith struct msghdr *msg; 439f2477ae1SMike Smith struct iovec *iov; 440f2477ae1SMike Smith 441f2477ae1SMike Smith int error; 442f2477ae1SMike Smith struct sendmsg_args /* { 443f2477ae1SMike Smith int s; 444f2477ae1SMike Smith caddr_t msg; 445f2477ae1SMike Smith int flags; 446f2477ae1SMike Smith } */ sendmsg_args; 447f2477ae1SMike Smith 448f2477ae1SMike Smith /* Check the packet isn't too small before we mess with it */ 449f2477ae1SMike Smith if (bsd_args->len < linux_ip_copysize) 4503f3a4815SMarcel Moolenaar return (EINVAL); 451f2477ae1SMike Smith 452f2477ae1SMike Smith /* 453f2477ae1SMike Smith * Tweaking the user buffer in place would be bad manners. 454f2477ae1SMike Smith * We create a corrected IP header with just the needed length, 455f2477ae1SMike Smith * then use an iovec to glue it to the rest of the user packet 456f2477ae1SMike Smith * when calling sendmsg(). 457f2477ae1SMike Smith */ 458f2477ae1SMike Smith sg = stackgap_init(); 459f2477ae1SMike Smith packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize); 460f2477ae1SMike Smith msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg)); 461f2477ae1SMike Smith iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2); 462f2477ae1SMike Smith 463f2477ae1SMike Smith /* Make a copy of the beginning of the packet to be sent */ 4643f3a4815SMarcel Moolenaar if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) 4653f3a4815SMarcel Moolenaar return (error); 466f2477ae1SMike Smith 467f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 468f2477ae1SMike Smith packet->ip_len = bsd_args->len; 469f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 470f2477ae1SMike Smith 471f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 472f2477ae1SMike Smith msg->msg_name = bsd_args->to; 473f2477ae1SMike Smith msg->msg_namelen = bsd_args->tolen; 474f2477ae1SMike Smith msg->msg_iov = iov; 475f2477ae1SMike Smith msg->msg_iovlen = 2; 476f2477ae1SMike Smith msg->msg_control = NULL; 477f2477ae1SMike Smith msg->msg_controllen = 0; 478f2477ae1SMike Smith msg->msg_flags = 0; 479f2477ae1SMike Smith iov[0].iov_base = (char *)packet; 480f2477ae1SMike Smith iov[0].iov_len = linux_ip_copysize; 481f2477ae1SMike Smith iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; 482f2477ae1SMike Smith iov[1].iov_len = bsd_args->len - linux_ip_copysize; 483f2477ae1SMike Smith 484f2477ae1SMike Smith sendmsg_args.s = bsd_args->s; 485f2477ae1SMike Smith sendmsg_args.msg = (caddr_t)msg; 486f2477ae1SMike Smith sendmsg_args.flags = bsd_args->flags; 487b40ce416SJulian Elischer return (sendmsg(td, &sendmsg_args)); 488f2477ae1SMike Smith } 489f2477ae1SMike Smith 490c21dee17SSøren Schmidt struct linux_socket_args { 491c21dee17SSøren Schmidt int domain; 492c21dee17SSøren Schmidt int type; 493c21dee17SSøren Schmidt int protocol; 494c21dee17SSøren Schmidt }; 495c21dee17SSøren Schmidt 496c21dee17SSøren Schmidt static int 497b40ce416SJulian Elischer linux_socket(struct thread *td, struct linux_socket_args *args) 498c21dee17SSøren Schmidt { 499c21dee17SSøren Schmidt struct linux_socket_args linux_args; 500ef04503dSPeter Wemm struct socket_args /* { 501c21dee17SSøren Schmidt int domain; 502c21dee17SSøren Schmidt int type; 503c21dee17SSøren Schmidt int protocol; 504ef04503dSPeter Wemm } */ bsd_args; 505ca26842eSHajimu UMEMOTO struct setsockopt_args /* { 506ca26842eSHajimu UMEMOTO int s; 507ca26842eSHajimu UMEMOTO int level; 508ca26842eSHajimu UMEMOTO int name; 509ca26842eSHajimu UMEMOTO caddr_t val; 510ca26842eSHajimu UMEMOTO int valsize; 511ca26842eSHajimu UMEMOTO } */ bsd_setsockopt_args; 512c21dee17SSøren Schmidt int error; 513f2477ae1SMike Smith int retval_socket; 514c21dee17SSøren Schmidt 5153f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5163f3a4815SMarcel Moolenaar return (error); 5173f3a4815SMarcel Moolenaar 518c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 519c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 520c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 521c21dee17SSøren Schmidt if (bsd_args.domain == -1) 5223f3a4815SMarcel Moolenaar return (EINVAL); 523f2477ae1SMike Smith 524b40ce416SJulian Elischer retval_socket = socket(td, &bsd_args); 525f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 526f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 527f2477ae1SMike Smith && bsd_args.domain == AF_INET 528f2477ae1SMike Smith && retval_socket >= 0) { 529f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 530f2477ae1SMike Smith caddr_t sg; 531f2477ae1SMike Smith int *hdrincl; 532f2477ae1SMike Smith 533f2477ae1SMike Smith sg = stackgap_init(); 534f2477ae1SMike Smith hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 535f2477ae1SMike Smith *hdrincl = 1; 536b40ce416SJulian Elischer bsd_setsockopt_args.s = td->td_retval[0]; 537f2477ae1SMike Smith bsd_setsockopt_args.level = IPPROTO_IP; 538f2477ae1SMike Smith bsd_setsockopt_args.name = IP_HDRINCL; 539f2477ae1SMike Smith bsd_setsockopt_args.val = (caddr_t)hdrincl; 540f2477ae1SMike Smith bsd_setsockopt_args.valsize = sizeof(*hdrincl); 541f2477ae1SMike Smith /* We ignore any error returned by setsockopt() */ 542b40ce416SJulian Elischer setsockopt(td, &bsd_setsockopt_args); 543f2477ae1SMike Smith /* Copy back the return value from socket() */ 544b40ce416SJulian Elischer td->td_retval[0] = bsd_setsockopt_args.s; 545f2477ae1SMike Smith } 546ca26842eSHajimu UMEMOTO #ifdef INET6 547ca26842eSHajimu UMEMOTO /* 548ca26842eSHajimu UMEMOTO * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 549ca26842eSHajimu UMEMOTO * default and some apps depend on this. So, set V6ONLY to 0 550ca26842eSHajimu UMEMOTO * for Linux apps if the sysctl value is set to 1. 551ca26842eSHajimu UMEMOTO */ 552ca26842eSHajimu UMEMOTO if (bsd_args.domain == PF_INET6 && retval_socket >= 0 && ip6_v6only) { 553ca26842eSHajimu UMEMOTO caddr_t sg; 554ca26842eSHajimu UMEMOTO int *v6only; 555ca26842eSHajimu UMEMOTO 556ca26842eSHajimu UMEMOTO sg = stackgap_init(); 557ca26842eSHajimu UMEMOTO v6only = (int *)stackgap_alloc(&sg, sizeof(*v6only)); 558ca26842eSHajimu UMEMOTO *v6only = 0; 559ca26842eSHajimu UMEMOTO bsd_setsockopt_args.s = td->td_retval[0]; 560ca26842eSHajimu UMEMOTO bsd_setsockopt_args.level = IPPROTO_IPV6; 561ca26842eSHajimu UMEMOTO bsd_setsockopt_args.name = IPV6_V6ONLY; 562ca26842eSHajimu UMEMOTO bsd_setsockopt_args.val = (caddr_t)v6only; 563ca26842eSHajimu UMEMOTO bsd_setsockopt_args.valsize = sizeof(*v6only); 564ca26842eSHajimu UMEMOTO /* We ignore any error returned by setsockopt() */ 565ca26842eSHajimu UMEMOTO setsockopt(td, &bsd_setsockopt_args); 566ca26842eSHajimu UMEMOTO /* Copy back the return value from socket() */ 567ca26842eSHajimu UMEMOTO td->td_retval[0] = bsd_setsockopt_args.s; 568ca26842eSHajimu UMEMOTO } 569ca26842eSHajimu UMEMOTO #endif 5703f3a4815SMarcel Moolenaar 5713f3a4815SMarcel Moolenaar return (retval_socket); 572c21dee17SSøren Schmidt } 573c21dee17SSøren Schmidt 574c21dee17SSøren Schmidt struct linux_bind_args { 575c21dee17SSøren Schmidt int s; 576ca26842eSHajimu UMEMOTO struct osockaddr *name; 577c21dee17SSøren Schmidt int namelen; 578c21dee17SSøren Schmidt }; 579c21dee17SSøren Schmidt 580c21dee17SSøren Schmidt static int 581b40ce416SJulian Elischer linux_bind(struct thread *td, struct linux_bind_args *args) 582c21dee17SSøren Schmidt { 583c21dee17SSøren Schmidt struct linux_bind_args linux_args; 584ca26842eSHajimu UMEMOTO struct sockaddr *sa; 585c21dee17SSøren Schmidt int error; 586c21dee17SSøren Schmidt 5873f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5883f3a4815SMarcel Moolenaar return (error); 5893f3a4815SMarcel Moolenaar 590ca26842eSHajimu UMEMOTO error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); 591ca26842eSHajimu UMEMOTO if (error) 592ca26842eSHajimu UMEMOTO return (error); 593ca26842eSHajimu UMEMOTO 594ca26842eSHajimu UMEMOTO return (kern_bind(td, linux_args.s, sa)); 595c21dee17SSøren Schmidt } 596c21dee17SSøren Schmidt 597c21dee17SSøren Schmidt struct linux_connect_args { 598c21dee17SSøren Schmidt int s; 599ca26842eSHajimu UMEMOTO struct osockaddr * name; 600c21dee17SSøren Schmidt int namelen; 601c21dee17SSøren Schmidt }; 602b40ce416SJulian Elischer int linux_connect(struct thread *, struct linux_connect_args *); 603930a65feSAndrew Gallatin #endif /* !__alpha__*/ 604c21dee17SSøren Schmidt 605930a65feSAndrew Gallatin int 606b40ce416SJulian Elischer linux_connect(struct thread *td, struct linux_connect_args *args) 607c21dee17SSøren Schmidt { 608c21dee17SSøren Schmidt struct linux_connect_args linux_args; 6090bf301c0SJonathan Lemon struct socket *so; 610ca26842eSHajimu UMEMOTO struct sockaddr *sa; 61139c95b83SMatthew Dillon u_int fflag; 612c21dee17SSøren Schmidt int error; 613c21dee17SSøren Schmidt 614930a65feSAndrew Gallatin #ifdef __alpha__ 615930a65feSAndrew Gallatin bcopy(args, &linux_args, sizeof(linux_args)); 616930a65feSAndrew Gallatin #else 6173f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6183f3a4815SMarcel Moolenaar return (error); 619930a65feSAndrew Gallatin #endif /* __alpha__ */ 6203f3a4815SMarcel Moolenaar 621ca26842eSHajimu UMEMOTO error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); 622ca26842eSHajimu UMEMOTO if (error) 623ca26842eSHajimu UMEMOTO return (error); 624ca26842eSHajimu UMEMOTO 625ca26842eSHajimu UMEMOTO error = kern_connect(td, linux_args.s, sa); 6260bf301c0SJonathan Lemon if (error != EISCONN) 6270bf301c0SJonathan Lemon return (error); 6280bf301c0SJonathan Lemon 629dad3b88aSMike Smith /* 630dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 631dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 632dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 633dad3b88aSMike Smith */ 63439c95b83SMatthew Dillon if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) 6353f3a4815SMarcel Moolenaar return(error); 6360bf301c0SJonathan Lemon error = EISCONN; 63739c95b83SMatthew Dillon if (fflag & FNONBLOCK) { 6385002a60fSMarcel Moolenaar if (so->so_emuldata == 0) 6390bf301c0SJonathan Lemon error = so->so_error; 6400bf301c0SJonathan Lemon so->so_emuldata = (void *)1; 641dad3b88aSMike Smith } 64239c95b83SMatthew Dillon fputsock(so); 6433f3a4815SMarcel Moolenaar return (error); 644c21dee17SSøren Schmidt } 645c21dee17SSøren Schmidt 646930a65feSAndrew Gallatin #ifndef __alpha__ 647930a65feSAndrew Gallatin 648c21dee17SSøren Schmidt struct linux_listen_args { 649c21dee17SSøren Schmidt int s; 650c21dee17SSøren Schmidt int backlog; 651c21dee17SSøren Schmidt }; 652c21dee17SSøren Schmidt 653c21dee17SSøren Schmidt static int 654b40ce416SJulian Elischer linux_listen(struct thread *td, struct linux_listen_args *args) 655c21dee17SSøren Schmidt { 656c21dee17SSøren Schmidt struct linux_listen_args linux_args; 657ef04503dSPeter Wemm struct listen_args /* { 658c21dee17SSøren Schmidt int s; 659c21dee17SSøren Schmidt int backlog; 660ef04503dSPeter Wemm } */ bsd_args; 661c21dee17SSøren Schmidt int error; 662c21dee17SSøren Schmidt 6633f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6643f3a4815SMarcel Moolenaar return (error); 6653f3a4815SMarcel Moolenaar 666c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 667c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 668b40ce416SJulian Elischer return (listen(td, &bsd_args)); 669c21dee17SSøren Schmidt } 670c21dee17SSøren Schmidt 671c21dee17SSøren Schmidt struct linux_accept_args { 672c21dee17SSøren Schmidt int s; 673ca26842eSHajimu UMEMOTO struct osockaddr *addr; 674c21dee17SSøren Schmidt int *namelen; 675c21dee17SSøren Schmidt }; 676c21dee17SSøren Schmidt 677c21dee17SSøren Schmidt static int 678b40ce416SJulian Elischer linux_accept(struct thread *td, struct linux_accept_args *args) 679c21dee17SSøren Schmidt { 680c21dee17SSøren Schmidt struct linux_accept_args linux_args; 681ef04503dSPeter Wemm struct accept_args /* { 682c21dee17SSøren Schmidt int s; 683c21dee17SSøren Schmidt caddr_t name; 684c21dee17SSøren Schmidt int *anamelen; 685ef04503dSPeter Wemm } */ bsd_args; 686ca26842eSHajimu UMEMOTO struct close_args /* { 687ca26842eSHajimu UMEMOTO int fd; 688ca26842eSHajimu UMEMOTO } */ c_args; 689dba5ab66SMarcel Moolenaar struct fcntl_args /* { 690dba5ab66SMarcel Moolenaar int fd; 691dba5ab66SMarcel Moolenaar int cmd; 692dba5ab66SMarcel Moolenaar long arg; 693dba5ab66SMarcel Moolenaar } */ f_args; 694c21dee17SSøren Schmidt int error; 695c21dee17SSøren Schmidt 6963f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6973f3a4815SMarcel Moolenaar return (error); 6983f3a4815SMarcel Moolenaar 699c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 700c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.addr; 701c21dee17SSøren Schmidt bsd_args.anamelen = linux_args.namelen; 702044af7c3SJonathan Mini error = oaccept(td, &bsd_args); 703dba5ab66SMarcel Moolenaar if (error) 704dba5ab66SMarcel Moolenaar return (error); 705ca26842eSHajimu UMEMOTO if (linux_args.addr) { 706ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 707ca26842eSHajimu UMEMOTO if (error) { 708ca26842eSHajimu UMEMOTO c_args.fd = td->td_retval[0]; 709ca26842eSHajimu UMEMOTO (void)close(td, &c_args); 710ca26842eSHajimu UMEMOTO return (error); 711ca26842eSHajimu UMEMOTO } 712ca26842eSHajimu UMEMOTO } 713dba5ab66SMarcel Moolenaar 714dba5ab66SMarcel Moolenaar /* 715dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 716dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 717dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 718dba5ab66SMarcel Moolenaar */ 719b40ce416SJulian Elischer f_args.fd = td->td_retval[0]; 720dba5ab66SMarcel Moolenaar f_args.cmd = F_SETFL; 721dba5ab66SMarcel Moolenaar f_args.arg = 0; 722b40ce416SJulian Elischer (void)fcntl(td, &f_args); 723b40ce416SJulian Elischer td->td_retval[0] = f_args.fd; 724dba5ab66SMarcel Moolenaar return (0); 725c21dee17SSøren Schmidt } 726c21dee17SSøren Schmidt 727c21dee17SSøren Schmidt struct linux_getsockname_args { 728c21dee17SSøren Schmidt int s; 729ca26842eSHajimu UMEMOTO struct osockaddr *addr; 730c21dee17SSøren Schmidt int *namelen; 731c21dee17SSøren Schmidt }; 732c21dee17SSøren Schmidt 733c21dee17SSøren Schmidt static int 734b40ce416SJulian Elischer linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 735c21dee17SSøren Schmidt { 736c21dee17SSøren Schmidt struct linux_getsockname_args linux_args; 737ef04503dSPeter Wemm struct getsockname_args /* { 738c21dee17SSøren Schmidt int fdes; 739c21dee17SSøren Schmidt caddr_t asa; 740c21dee17SSøren Schmidt int *alen; 741ef04503dSPeter Wemm } */ bsd_args; 742c21dee17SSøren Schmidt int error; 743c21dee17SSøren Schmidt 7443f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7453f3a4815SMarcel Moolenaar return (error); 7463f3a4815SMarcel Moolenaar 747c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 748c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 749c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 750ca26842eSHajimu UMEMOTO error = ogetsockname(td, &bsd_args); 751ca26842eSHajimu UMEMOTO if (error) 752ca26842eSHajimu UMEMOTO return (error); 753ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 754ca26842eSHajimu UMEMOTO if (error) 755ca26842eSHajimu UMEMOTO return (error); 756ca26842eSHajimu UMEMOTO return (0); 757c21dee17SSøren Schmidt } 758c21dee17SSøren Schmidt 759c21dee17SSøren Schmidt struct linux_getpeername_args { 760c21dee17SSøren Schmidt int s; 761ca26842eSHajimu UMEMOTO struct osockaddr *addr; 762c21dee17SSøren Schmidt int *namelen; 763c21dee17SSøren Schmidt }; 764c21dee17SSøren Schmidt 765c21dee17SSøren Schmidt static int 766b40ce416SJulian Elischer linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 767c21dee17SSøren Schmidt { 768c21dee17SSøren Schmidt struct linux_getpeername_args linux_args; 769044af7c3SJonathan Mini struct ogetpeername_args /* { 770c21dee17SSøren Schmidt int fdes; 771c21dee17SSøren Schmidt caddr_t asa; 772c21dee17SSøren Schmidt int *alen; 773ef04503dSPeter Wemm } */ bsd_args; 774c21dee17SSøren Schmidt int error; 775c21dee17SSøren Schmidt 7763f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7773f3a4815SMarcel Moolenaar return (error); 7783f3a4815SMarcel Moolenaar 779c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 780c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 781c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 782ca26842eSHajimu UMEMOTO error = ogetpeername(td, &bsd_args); 783ca26842eSHajimu UMEMOTO if (error) 784ca26842eSHajimu UMEMOTO return (error); 785ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 786ca26842eSHajimu UMEMOTO if (error) 787ca26842eSHajimu UMEMOTO return (error); 788ca26842eSHajimu UMEMOTO return (0); 789c21dee17SSøren Schmidt } 790c21dee17SSøren Schmidt 791c21dee17SSøren Schmidt struct linux_socketpair_args { 792c21dee17SSøren Schmidt int domain; 793c21dee17SSøren Schmidt int type; 794c21dee17SSøren Schmidt int protocol; 795c21dee17SSøren Schmidt int *rsv; 796c21dee17SSøren Schmidt }; 797c21dee17SSøren Schmidt 798c21dee17SSøren Schmidt static int 799b40ce416SJulian Elischer linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 800c21dee17SSøren Schmidt { 801c21dee17SSøren Schmidt struct linux_socketpair_args linux_args; 802ef04503dSPeter Wemm struct socketpair_args /* { 803c21dee17SSøren Schmidt int domain; 804c21dee17SSøren Schmidt int type; 805c21dee17SSøren Schmidt int protocol; 806c21dee17SSøren Schmidt int *rsv; 807ef04503dSPeter Wemm } */ bsd_args; 808c21dee17SSøren Schmidt int error; 809c21dee17SSøren Schmidt 8103f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8113f3a4815SMarcel Moolenaar return (error); 8123f3a4815SMarcel Moolenaar 813c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 814c21dee17SSøren Schmidt if (bsd_args.domain == -1) 8153f3a4815SMarcel Moolenaar return (EINVAL); 8163f3a4815SMarcel Moolenaar 817c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 818c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 819c21dee17SSøren Schmidt bsd_args.rsv = linux_args.rsv; 820b40ce416SJulian Elischer return (socketpair(td, &bsd_args)); 821c21dee17SSøren Schmidt } 822c21dee17SSøren Schmidt 823c21dee17SSøren Schmidt struct linux_send_args { 824c21dee17SSøren Schmidt int s; 825c21dee17SSøren Schmidt void *msg; 826c21dee17SSøren Schmidt int len; 827c21dee17SSøren Schmidt int flags; 828c21dee17SSøren Schmidt }; 829c21dee17SSøren Schmidt 830c21dee17SSøren Schmidt static int 831b40ce416SJulian Elischer linux_send(struct thread *td, struct linux_send_args *args) 832c21dee17SSøren Schmidt { 833c21dee17SSøren Schmidt struct linux_send_args linux_args; 834044af7c3SJonathan Mini struct osend_args /* { 835c21dee17SSøren Schmidt int s; 836c21dee17SSøren Schmidt caddr_t buf; 837044af7c3SJonathan Mini int len; 838c21dee17SSøren Schmidt int flags; 839ef04503dSPeter Wemm } */ bsd_args; 840c21dee17SSøren Schmidt int error; 841c21dee17SSøren Schmidt 8423f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8433f3a4815SMarcel Moolenaar return (error); 8443f3a4815SMarcel Moolenaar 845c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 846c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 847c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 848c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 849044af7c3SJonathan Mini return (osend(td, &bsd_args)); 850c21dee17SSøren Schmidt } 851c21dee17SSøren Schmidt 852c21dee17SSøren Schmidt struct linux_recv_args { 853c21dee17SSøren Schmidt int s; 854c21dee17SSøren Schmidt void *msg; 855c21dee17SSøren Schmidt int len; 856c21dee17SSøren Schmidt int flags; 857c21dee17SSøren Schmidt }; 858c21dee17SSøren Schmidt 859c21dee17SSøren Schmidt static int 860b40ce416SJulian Elischer linux_recv(struct thread *td, struct linux_recv_args *args) 861c21dee17SSøren Schmidt { 862c21dee17SSøren Schmidt struct linux_recv_args linux_args; 863044af7c3SJonathan Mini struct orecv_args /* { 864c21dee17SSøren Schmidt int s; 865c21dee17SSøren Schmidt caddr_t buf; 866c21dee17SSøren Schmidt int len; 867c21dee17SSøren Schmidt int flags; 868ef04503dSPeter Wemm } */ bsd_args; 869c21dee17SSøren Schmidt int error; 870c21dee17SSøren Schmidt 8713f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8723f3a4815SMarcel Moolenaar return (error); 8733f3a4815SMarcel Moolenaar 874c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 875c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 876c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 877c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 878044af7c3SJonathan Mini return (orecv(td, &bsd_args)); 879c21dee17SSøren Schmidt } 880c21dee17SSøren Schmidt 881c21dee17SSøren Schmidt struct linux_sendto_args { 882c21dee17SSøren Schmidt int s; 883c21dee17SSøren Schmidt void *msg; 884c21dee17SSøren Schmidt int len; 885c21dee17SSøren Schmidt int flags; 886c21dee17SSøren Schmidt caddr_t to; 887c21dee17SSøren Schmidt int tolen; 888c21dee17SSøren Schmidt }; 889c21dee17SSøren Schmidt 890c21dee17SSøren Schmidt static int 891b40ce416SJulian Elischer linux_sendto(struct thread *td, struct linux_sendto_args *args) 892c21dee17SSøren Schmidt { 893c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 894ef04503dSPeter Wemm struct sendto_args /* { 895c21dee17SSøren Schmidt int s; 896c21dee17SSøren Schmidt caddr_t buf; 897c21dee17SSøren Schmidt size_t len; 898c21dee17SSøren Schmidt int flags; 899c21dee17SSøren Schmidt caddr_t to; 900c21dee17SSøren Schmidt int tolen; 901ef04503dSPeter Wemm } */ bsd_args; 902ca26842eSHajimu UMEMOTO caddr_t sg = stackgap_init(); 903ca26842eSHajimu UMEMOTO struct sockaddr *to; 904ca26842eSHajimu UMEMOTO int tolen, error; 905c21dee17SSøren Schmidt 9063f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9073f3a4815SMarcel Moolenaar return (error); 9083f3a4815SMarcel Moolenaar 909ca26842eSHajimu UMEMOTO tolen = linux_args.tolen; 910ca26842eSHajimu UMEMOTO if (linux_args.to) { 911ca26842eSHajimu UMEMOTO error = linux_sa_get(&sg, &to, 912ca26842eSHajimu UMEMOTO (struct osockaddr *) linux_args.to, &tolen); 913ca26842eSHajimu UMEMOTO if (error) 914ca26842eSHajimu UMEMOTO return (error); 915ca26842eSHajimu UMEMOTO } else 916ca26842eSHajimu UMEMOTO to = NULL; 917ca26842eSHajimu UMEMOTO 918c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 919c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 920c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 921c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 922ca26842eSHajimu UMEMOTO bsd_args.to = (caddr_t) to; 923ca26842eSHajimu UMEMOTO bsd_args.tolen = (unsigned int) tolen; 924f2477ae1SMike Smith 925b40ce416SJulian Elischer if (linux_check_hdrincl(td, linux_args.s) == 0) 926f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 927b40ce416SJulian Elischer return (linux_sendto_hdrincl(td, &bsd_args)); 928f2477ae1SMike Smith 929b40ce416SJulian Elischer return (sendto(td, &bsd_args)); 930c21dee17SSøren Schmidt } 931c21dee17SSøren Schmidt 932c21dee17SSøren Schmidt struct linux_recvfrom_args { 933c21dee17SSøren Schmidt int s; 934c21dee17SSøren Schmidt void *buf; 935c21dee17SSøren Schmidt int len; 936c21dee17SSøren Schmidt int flags; 937c21dee17SSøren Schmidt caddr_t from; 938c21dee17SSøren Schmidt int *fromlen; 939c21dee17SSøren Schmidt }; 940c21dee17SSøren Schmidt 941c21dee17SSøren Schmidt static int 942b40ce416SJulian Elischer linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 943c21dee17SSøren Schmidt { 944c21dee17SSøren Schmidt struct linux_recvfrom_args linux_args; 945ef04503dSPeter Wemm struct recvfrom_args /* { 946c21dee17SSøren Schmidt int s; 947c21dee17SSøren Schmidt caddr_t buf; 948c21dee17SSøren Schmidt size_t len; 949c21dee17SSøren Schmidt int flags; 950c21dee17SSøren Schmidt caddr_t from; 951c21dee17SSøren Schmidt int *fromlenaddr; 952ef04503dSPeter Wemm } */ bsd_args; 953c21dee17SSøren Schmidt int error; 954c21dee17SSøren Schmidt 9553f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9563f3a4815SMarcel Moolenaar return (error); 9573f3a4815SMarcel Moolenaar 958c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 959c21dee17SSøren Schmidt bsd_args.buf = linux_args.buf; 960c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 96140dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 962c21dee17SSøren Schmidt bsd_args.from = linux_args.from; 963c21dee17SSøren Schmidt bsd_args.fromlenaddr = linux_args.fromlen; 964ca26842eSHajimu UMEMOTO error = orecvfrom(td, &bsd_args); 965ca26842eSHajimu UMEMOTO if (error) 966ca26842eSHajimu UMEMOTO return (error); 967ca26842eSHajimu UMEMOTO if (linux_args.from) { 968ca26842eSHajimu UMEMOTO error = linux_sa_put((struct osockaddr *) linux_args.from); 969ca26842eSHajimu UMEMOTO if (error) 970ca26842eSHajimu UMEMOTO return (error); 971ca26842eSHajimu UMEMOTO } 972ca26842eSHajimu UMEMOTO return (0); 973ca26842eSHajimu UMEMOTO } 974ca26842eSHajimu UMEMOTO 975ca26842eSHajimu UMEMOTO struct linux_sendmsg_args { 976ca26842eSHajimu UMEMOTO int s; 977ca26842eSHajimu UMEMOTO const struct msghdr *msg; 978ca26842eSHajimu UMEMOTO int flags; 979ca26842eSHajimu UMEMOTO }; 980ca26842eSHajimu UMEMOTO 981ca26842eSHajimu UMEMOTO static int 982ca26842eSHajimu UMEMOTO linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 983ca26842eSHajimu UMEMOTO { 984ca26842eSHajimu UMEMOTO struct linux_sendmsg_args linux_args; 985ca26842eSHajimu UMEMOTO struct sendmsg_args /* { 986ca26842eSHajimu UMEMOTO int s; 987ca26842eSHajimu UMEMOTO const struct msghdr *msg; 988ca26842eSHajimu UMEMOTO int flags; 989ca26842eSHajimu UMEMOTO } */ bsd_args; 990ca26842eSHajimu UMEMOTO struct msghdr msg; 991ca26842eSHajimu UMEMOTO struct msghdr *nmsg = NULL; 992ca26842eSHajimu UMEMOTO int error; 993ca26842eSHajimu UMEMOTO int level; 994ca26842eSHajimu UMEMOTO caddr_t control; 995ca26842eSHajimu UMEMOTO 996ca26842eSHajimu UMEMOTO if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 997ca26842eSHajimu UMEMOTO return (error); 998ca26842eSHajimu UMEMOTO 999ca26842eSHajimu UMEMOTO error = copyin(linux_args.msg, (caddr_t) &msg, sizeof(msg)); 1000ca26842eSHajimu UMEMOTO if (error) 1001ca26842eSHajimu UMEMOTO return (error); 1002ca26842eSHajimu UMEMOTO 1003ca26842eSHajimu UMEMOTO if (msg.msg_name) { 1004ca26842eSHajimu UMEMOTO struct sockaddr *sa; 1005ca26842eSHajimu UMEMOTO caddr_t sg = stackgap_init(); 1006ca26842eSHajimu UMEMOTO 1007ca26842eSHajimu UMEMOTO nmsg = (struct msghdr *) stackgap_alloc(&sg, 1008ca26842eSHajimu UMEMOTO sizeof(struct msghdr)); 1009ca26842eSHajimu UMEMOTO if (!nmsg) 1010ca26842eSHajimu UMEMOTO return (ENOMEM); 1011ca26842eSHajimu UMEMOTO 1012ca26842eSHajimu UMEMOTO error = linux_sa_get(&sg, &sa, 1013ca26842eSHajimu UMEMOTO (struct osockaddr *) msg.msg_name, &msg.msg_namelen); 1014ca26842eSHajimu UMEMOTO if (error) 1015ca26842eSHajimu UMEMOTO return (error); 1016ca26842eSHajimu UMEMOTO 1017ca26842eSHajimu UMEMOTO msg.msg_name = (struct sockaddr *) sa; 1018ca26842eSHajimu UMEMOTO error = copyout(&msg, nmsg, sizeof(struct msghdr)); 1019ca26842eSHajimu UMEMOTO if (error) 1020ca26842eSHajimu UMEMOTO return (error); 1021ca26842eSHajimu UMEMOTO } 1022ca26842eSHajimu UMEMOTO 1023ca26842eSHajimu UMEMOTO error = copyin(&linux_args.msg->msg_control, &control, 1024ca26842eSHajimu UMEMOTO sizeof(caddr_t)); 1025ca26842eSHajimu UMEMOTO if (error) 1026ca26842eSHajimu UMEMOTO return (error); 1027ca26842eSHajimu UMEMOTO 1028ca26842eSHajimu UMEMOTO if (control == NULL) 1029ca26842eSHajimu UMEMOTO goto done; 1030ca26842eSHajimu UMEMOTO 1031ca26842eSHajimu UMEMOTO error = copyin(&((struct cmsghdr*)control)->cmsg_level, &level, 1032ca26842eSHajimu UMEMOTO sizeof(int)); 1033ca26842eSHajimu UMEMOTO if (error) 1034ca26842eSHajimu UMEMOTO return (error); 1035ca26842eSHajimu UMEMOTO 1036ca26842eSHajimu UMEMOTO if (level == 1) { 1037ca26842eSHajimu UMEMOTO /* 1038ca26842eSHajimu UMEMOTO * Linux thinks that SOL_SOCKET is 1; we know 1039ca26842eSHajimu UMEMOTO * that it's really 0xffff, of course. 1040ca26842eSHajimu UMEMOTO */ 1041ca26842eSHajimu UMEMOTO level = SOL_SOCKET; 1042ca26842eSHajimu UMEMOTO error = copyout(&level, 1043ca26842eSHajimu UMEMOTO &((struct cmsghdr *)control)->cmsg_level, sizeof(int)); 1044ca26842eSHajimu UMEMOTO if (error) 1045ca26842eSHajimu UMEMOTO return (error); 1046ca26842eSHajimu UMEMOTO } 1047ca26842eSHajimu UMEMOTO done: 1048ca26842eSHajimu UMEMOTO return (sendmsg(td, &bsd_args)); 1049c21dee17SSøren Schmidt } 1050c21dee17SSøren Schmidt 105140dbba57SAssar Westerlund struct linux_recvmsg_args { 105240dbba57SAssar Westerlund int s; 105340dbba57SAssar Westerlund struct msghdr *msg; 105440dbba57SAssar Westerlund int flags; 105540dbba57SAssar Westerlund }; 105640dbba57SAssar Westerlund 105740dbba57SAssar Westerlund static int 1058b40ce416SJulian Elischer linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 105940dbba57SAssar Westerlund { 106040dbba57SAssar Westerlund struct linux_recvmsg_args linux_args; 106140dbba57SAssar Westerlund struct recvmsg_args /* { 106240dbba57SAssar Westerlund int s; 106340dbba57SAssar Westerlund struct msghdr *msg; 106440dbba57SAssar Westerlund int flags; 106540dbba57SAssar Westerlund } */ bsd_args; 1066ca26842eSHajimu UMEMOTO struct msghdr msg; 106740dbba57SAssar Westerlund int error; 106840dbba57SAssar Westerlund 106940dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 107040dbba57SAssar Westerlund return (error); 107140dbba57SAssar Westerlund 107240dbba57SAssar Westerlund bsd_args.s = linux_args.s; 107340dbba57SAssar Westerlund bsd_args.msg = linux_args.msg; 107440dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 1075ca26842eSHajimu UMEMOTO error = recvmsg(td, &bsd_args); 1076ca26842eSHajimu UMEMOTO if (error) 1077ca26842eSHajimu UMEMOTO return (error); 1078ca26842eSHajimu UMEMOTO 1079ca26842eSHajimu UMEMOTO error = copyin((caddr_t)linux_args.msg, (caddr_t)&msg, sizeof(msg)); 1080ca26842eSHajimu UMEMOTO if (error) 1081ca26842eSHajimu UMEMOTO return (error); 1082ca26842eSHajimu UMEMOTO if (msg.msg_name && msg.msg_namelen > 2) 1083ca26842eSHajimu UMEMOTO error = linux_sa_put(msg.msg_name); 1084ca26842eSHajimu UMEMOTO return (error); 108540dbba57SAssar Westerlund } 108640dbba57SAssar Westerlund 1087c21dee17SSøren Schmidt struct linux_shutdown_args { 1088c21dee17SSøren Schmidt int s; 1089c21dee17SSøren Schmidt int how; 1090c21dee17SSøren Schmidt }; 1091c21dee17SSøren Schmidt 1092c21dee17SSøren Schmidt static int 1093b40ce416SJulian Elischer linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1094c21dee17SSøren Schmidt { 1095c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 1096ef04503dSPeter Wemm struct shutdown_args /* { 1097c21dee17SSøren Schmidt int s; 1098c21dee17SSøren Schmidt int how; 1099ef04503dSPeter Wemm } */ bsd_args; 1100c21dee17SSøren Schmidt int error; 1101c21dee17SSøren Schmidt 11023f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11033f3a4815SMarcel Moolenaar return (error); 11043f3a4815SMarcel Moolenaar 1105c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1106c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 1107b40ce416SJulian Elischer return (shutdown(td, &bsd_args)); 1108c21dee17SSøren Schmidt } 1109c21dee17SSøren Schmidt 1110c21dee17SSøren Schmidt struct linux_setsockopt_args { 1111c21dee17SSøren Schmidt int s; 1112c21dee17SSøren Schmidt int level; 1113c21dee17SSøren Schmidt int optname; 1114c21dee17SSøren Schmidt void *optval; 1115c21dee17SSøren Schmidt int optlen; 1116c21dee17SSøren Schmidt }; 1117c21dee17SSøren Schmidt 1118c21dee17SSøren Schmidt static int 1119b40ce416SJulian Elischer linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1120c21dee17SSøren Schmidt { 1121c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 1122ef04503dSPeter Wemm struct setsockopt_args /* { 1123c21dee17SSøren Schmidt int s; 1124c21dee17SSøren Schmidt int level; 1125c21dee17SSøren Schmidt int name; 1126c21dee17SSøren Schmidt caddr_t val; 1127c21dee17SSøren Schmidt int valsize; 1128ef04503dSPeter Wemm } */ bsd_args; 1129c21dee17SSøren Schmidt int error, name; 1130c21dee17SSøren Schmidt 11313f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11323f3a4815SMarcel Moolenaar return (error); 11333f3a4815SMarcel Moolenaar 1134c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1135c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1136c21dee17SSøren Schmidt switch (bsd_args.level) { 1137c21dee17SSøren Schmidt case SOL_SOCKET: 1138c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1139c21dee17SSøren Schmidt break; 1140c21dee17SSøren Schmidt case IPPROTO_IP: 1141c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1142c21dee17SSøren Schmidt break; 1143dad3b88aSMike Smith case IPPROTO_TCP: 1144dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1145dad3b88aSMike Smith name = linux_args.optname; 1146dad3b88aSMike Smith break; 1147c21dee17SSøren Schmidt default: 11483f3a4815SMarcel Moolenaar name = -1; 11493f3a4815SMarcel Moolenaar break; 1150c21dee17SSøren Schmidt } 1151c21dee17SSøren Schmidt if (name == -1) 11523f3a4815SMarcel Moolenaar return (EINVAL); 11533f3a4815SMarcel Moolenaar 1154c21dee17SSøren Schmidt bsd_args.name = name; 1155c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1156c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 1157b40ce416SJulian Elischer return (setsockopt(td, &bsd_args)); 1158c21dee17SSøren Schmidt } 1159c21dee17SSøren Schmidt 1160c21dee17SSøren Schmidt struct linux_getsockopt_args { 1161c21dee17SSøren Schmidt int s; 1162c21dee17SSøren Schmidt int level; 1163c21dee17SSøren Schmidt int optname; 1164c21dee17SSøren Schmidt void *optval; 1165c21dee17SSøren Schmidt int *optlen; 1166c21dee17SSøren Schmidt }; 1167c21dee17SSøren Schmidt 1168c21dee17SSøren Schmidt static int 1169b40ce416SJulian Elischer linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1170c21dee17SSøren Schmidt { 1171c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 1172ef04503dSPeter Wemm struct getsockopt_args /* { 1173c21dee17SSøren Schmidt int s; 1174c21dee17SSøren Schmidt int level; 1175c21dee17SSøren Schmidt int name; 1176c21dee17SSøren Schmidt caddr_t val; 1177c21dee17SSøren Schmidt int *avalsize; 1178ef04503dSPeter Wemm } */ bsd_args; 1179c21dee17SSøren Schmidt int error, name; 1180c21dee17SSøren Schmidt 11813f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11823f3a4815SMarcel Moolenaar return (error); 11833f3a4815SMarcel Moolenaar 1184c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1185c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1186c21dee17SSøren Schmidt switch (bsd_args.level) { 1187c21dee17SSøren Schmidt case SOL_SOCKET: 1188c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1189c21dee17SSøren Schmidt break; 1190c21dee17SSøren Schmidt case IPPROTO_IP: 1191c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1192c21dee17SSøren Schmidt break; 1193dad3b88aSMike Smith case IPPROTO_TCP: 1194dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1195dad3b88aSMike Smith name = linux_args.optname; 1196dad3b88aSMike Smith break; 1197c21dee17SSøren Schmidt default: 11983f3a4815SMarcel Moolenaar name = -1; 11993f3a4815SMarcel Moolenaar break; 1200c21dee17SSøren Schmidt } 1201c21dee17SSøren Schmidt if (name == -1) 12023f3a4815SMarcel Moolenaar return (EINVAL); 12033f3a4815SMarcel Moolenaar 1204f2477ae1SMike Smith bsd_args.name = name; 1205c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1206c21dee17SSøren Schmidt bsd_args.avalsize = linux_args.optlen; 1207b40ce416SJulian Elischer return (getsockopt(td, &bsd_args)); 1208c21dee17SSøren Schmidt } 1209c21dee17SSøren Schmidt 1210c21dee17SSøren Schmidt int 1211b40ce416SJulian Elischer linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1212c21dee17SSøren Schmidt { 12135002a60fSMarcel Moolenaar void *arg = (void *)args->args; 12143f3a4815SMarcel Moolenaar 1215c21dee17SSøren Schmidt switch (args->what) { 1216c21dee17SSøren Schmidt case LINUX_SOCKET: 1217b40ce416SJulian Elischer return (linux_socket(td, arg)); 1218c21dee17SSøren Schmidt case LINUX_BIND: 1219b40ce416SJulian Elischer return (linux_bind(td, arg)); 1220c21dee17SSøren Schmidt case LINUX_CONNECT: 1221b40ce416SJulian Elischer return (linux_connect(td, arg)); 1222c21dee17SSøren Schmidt case LINUX_LISTEN: 1223b40ce416SJulian Elischer return (linux_listen(td, arg)); 1224c21dee17SSøren Schmidt case LINUX_ACCEPT: 1225b40ce416SJulian Elischer return (linux_accept(td, arg)); 1226c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 1227b40ce416SJulian Elischer return (linux_getsockname(td, arg)); 1228c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 1229b40ce416SJulian Elischer return (linux_getpeername(td, arg)); 1230c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 1231b40ce416SJulian Elischer return (linux_socketpair(td, arg)); 1232c21dee17SSøren Schmidt case LINUX_SEND: 1233b40ce416SJulian Elischer return (linux_send(td, arg)); 1234c21dee17SSøren Schmidt case LINUX_RECV: 1235b40ce416SJulian Elischer return (linux_recv(td, arg)); 1236c21dee17SSøren Schmidt case LINUX_SENDTO: 1237b40ce416SJulian Elischer return (linux_sendto(td, arg)); 1238c21dee17SSøren Schmidt case LINUX_RECVFROM: 1239b40ce416SJulian Elischer return (linux_recvfrom(td, arg)); 1240c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 1241b40ce416SJulian Elischer return (linux_shutdown(td, arg)); 1242c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 1243b40ce416SJulian Elischer return (linux_setsockopt(td, arg)); 1244c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 1245b40ce416SJulian Elischer return (linux_getsockopt(td, arg)); 1246e76bba09SSøren Schmidt case LINUX_SENDMSG: 1247ca26842eSHajimu UMEMOTO return (linux_sendmsg(td, arg)); 1248e76bba09SSøren Schmidt case LINUX_RECVMSG: 1249b40ce416SJulian Elischer return (linux_recvmsg(td, arg)); 1250c21dee17SSøren Schmidt } 12513f3a4815SMarcel Moolenaar 12523f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 12533f3a4815SMarcel Moolenaar return (ENOSYS); 1254c21dee17SSøren Schmidt } 12555231fb20SDavid E. O'Brien #endif /*!__alpha__*/ 1256