1c21dee17SSøren Schmidt /*- 2c21dee17SSøren Schmidt * Copyright (c) 1995 S�ren Schmidt 3c21dee17SSøren Schmidt * All rights reserved. 4c21dee17SSøren Schmidt * 5c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without 6c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions 7c21dee17SSøren Schmidt * are met: 8c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 9c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer 10c21dee17SSøren Schmidt * in this position and unchanged. 11c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 12c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 13c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution. 14c21dee17SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 1521dc7d4fSJens Schweikhardt * derived from this software without specific prior written permission 16c21dee17SSøren Schmidt * 17c21dee17SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18c21dee17SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19c21dee17SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20c21dee17SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21c21dee17SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22c21dee17SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23c21dee17SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24c21dee17SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25c21dee17SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26c21dee17SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27c21dee17SSøren Schmidt */ 28c21dee17SSøren Schmidt 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3016dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 321f3dad5aSBruce Evans /* XXX we use functions that might not exist. */ 335591b823SEivind Eklund #include "opt_compat.h" 34ca26842eSHajimu UMEMOTO #include "opt_inet6.h" 355591b823SEivind Eklund 365591b823SEivind Eklund #ifndef COMPAT_43 375591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 385591b823SEivind Eklund #endif 391f3dad5aSBruce Evans 40c21dee17SSøren Schmidt #include <sys/param.h> 41f2477ae1SMike Smith #include <sys/proc.h> 42c21dee17SSøren Schmidt #include <sys/systm.h> 431f3dad5aSBruce Evans #include <sys/sysproto.h> 44dad3b88aSMike Smith #include <sys/fcntl.h> 450bf301c0SJonathan Lemon #include <sys/file.h> 46104a9b7eSAlexander Kabaev #include <sys/limits.h> 47ca26842eSHajimu UMEMOTO #include <sys/malloc.h> 485a8a13e0SDavid Malone #include <sys/mbuf.h> 49c21dee17SSøren Schmidt #include <sys/socket.h> 500bf301c0SJonathan Lemon #include <sys/socketvar.h> 51ca26842eSHajimu UMEMOTO #include <sys/syscallsubr.h> 5208637435SBruce Evans #include <sys/uio.h> 53ca26842eSHajimu UMEMOTO #include <sys/syslog.h> 541f3dad5aSBruce Evans 55c21dee17SSøren Schmidt #include <netinet/in.h> 56f2477ae1SMike Smith #include <netinet/in_systm.h> 57f2477ae1SMike Smith #include <netinet/ip.h> 58ca26842eSHajimu UMEMOTO #ifdef INET6 59ca26842eSHajimu UMEMOTO #include <netinet/ip6.h> 60ca26842eSHajimu UMEMOTO #include <netinet6/ip6_var.h> 61ca26842eSHajimu UMEMOTO #endif 62c21dee17SSøren Schmidt 63ac951e62SMarcel Moolenaar #include <machine/../linux/linux.h> 64ebea8660SMarcel Moolenaar #include <machine/../linux/linux_proto.h> 6540dbba57SAssar Westerlund #include <compat/linux/linux_socket.h> 66ac951e62SMarcel Moolenaar #include <compat/linux/linux_util.h> 67c21dee17SSøren Schmidt 68ca26842eSHajimu UMEMOTO static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *, 69ca26842eSHajimu UMEMOTO struct malloc_type *); 70ca26842eSHajimu UMEMOTO static int linux_to_bsd_domain(int); 71ca26842eSHajimu UMEMOTO 724730796cSBill Fenner /* 73ca26842eSHajimu UMEMOTO * Reads a linux sockaddr and does any necessary translation. 74ca26842eSHajimu UMEMOTO * Linux sockaddrs don't have a length field, only a family. 754730796cSBill Fenner */ 764730796cSBill Fenner static int 77ca26842eSHajimu UMEMOTO linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int len) 784730796cSBill Fenner { 79ca26842eSHajimu UMEMOTO int osalen = len; 804730796cSBill Fenner 81ca26842eSHajimu UMEMOTO return (do_sa_get(sap, osa, &osalen, M_SONAME)); 824730796cSBill Fenner } 834730796cSBill Fenner 84ca26842eSHajimu UMEMOTO /* 85ca26842eSHajimu UMEMOTO * Copy the osockaddr structure pointed to by osa to kernel, adjust 86ca26842eSHajimu UMEMOTO * family and convert to sockaddr. 87ca26842eSHajimu UMEMOTO */ 88ca26842eSHajimu UMEMOTO static int 89ca26842eSHajimu UMEMOTO do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, 90ca26842eSHajimu UMEMOTO struct malloc_type *mtype) 91ca26842eSHajimu UMEMOTO { 92ca26842eSHajimu UMEMOTO int error=0, bdom; 93ca26842eSHajimu UMEMOTO struct sockaddr *sa; 94ca26842eSHajimu UMEMOTO struct osockaddr *kosa; 95ca26842eSHajimu UMEMOTO int alloclen; 96ca26842eSHajimu UMEMOTO #ifdef INET6 97ca26842eSHajimu UMEMOTO int oldv6size; 98ca26842eSHajimu UMEMOTO struct sockaddr_in6 *sin6; 99ca26842eSHajimu UMEMOTO #endif 100ca26842eSHajimu UMEMOTO 101ca26842eSHajimu UMEMOTO if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) 102ca26842eSHajimu UMEMOTO return (EINVAL); 103ca26842eSHajimu UMEMOTO 104ca26842eSHajimu UMEMOTO alloclen = *osalen; 105ca26842eSHajimu UMEMOTO #ifdef INET6 106ca26842eSHajimu UMEMOTO oldv6size = 0; 107ca26842eSHajimu UMEMOTO /* 108ca26842eSHajimu UMEMOTO * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 109ca26842eSHajimu UMEMOTO * if it's a v4-mapped address, so reserve the proper space 110ca26842eSHajimu UMEMOTO * for it. 111ca26842eSHajimu UMEMOTO */ 112ca26842eSHajimu UMEMOTO if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { 113ca26842eSHajimu UMEMOTO alloclen = sizeof (struct sockaddr_in6); 114ca26842eSHajimu UMEMOTO oldv6size = 1; 115ca26842eSHajimu UMEMOTO } 116ca26842eSHajimu UMEMOTO #endif 117ca26842eSHajimu UMEMOTO 1185b13e781SHajimu UMEMOTO MALLOC(kosa, struct osockaddr *, alloclen, mtype, M_WAITOK); 119ca26842eSHajimu UMEMOTO 1204b7ef73dSDag-Erling Smørgrav if ((error = copyin(osa, kosa, *osalen))) 121ca26842eSHajimu UMEMOTO goto out; 122ca26842eSHajimu UMEMOTO 123ca26842eSHajimu UMEMOTO bdom = linux_to_bsd_domain(kosa->sa_family); 124ca26842eSHajimu UMEMOTO if (bdom == -1) { 125ca26842eSHajimu UMEMOTO error = EINVAL; 126ca26842eSHajimu UMEMOTO goto out; 127ca26842eSHajimu UMEMOTO } 128ca26842eSHajimu UMEMOTO 129ca26842eSHajimu UMEMOTO #ifdef INET6 130ca26842eSHajimu UMEMOTO /* 131ca26842eSHajimu UMEMOTO * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 132ca26842eSHajimu UMEMOTO * which lacks the scope id compared with RFC2553 one. If we detect 133ca26842eSHajimu UMEMOTO * the situation, reject the address and write a message to system log. 134ca26842eSHajimu UMEMOTO * 135ca26842eSHajimu UMEMOTO * Still accept addresses for which the scope id is not used. 136ca26842eSHajimu UMEMOTO */ 137ca26842eSHajimu UMEMOTO if (oldv6size && bdom == AF_INET6) { 138ca26842eSHajimu UMEMOTO sin6 = (struct sockaddr_in6 *)kosa; 139ca26842eSHajimu UMEMOTO if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 140ca26842eSHajimu UMEMOTO (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 141ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 142ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 143ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 144ca26842eSHajimu UMEMOTO !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 145ca26842eSHajimu UMEMOTO sin6->sin6_scope_id = 0; 146ca26842eSHajimu UMEMOTO } else { 147ca26842eSHajimu UMEMOTO log(LOG_DEBUG, 148ca26842eSHajimu UMEMOTO "obsolete pre-RFC2553 sockaddr_in6 rejected"); 149ca26842eSHajimu UMEMOTO error = EINVAL; 150ca26842eSHajimu UMEMOTO goto out; 151ca26842eSHajimu UMEMOTO } 152ca26842eSHajimu UMEMOTO } else 153ca26842eSHajimu UMEMOTO #endif 154ca26842eSHajimu UMEMOTO if (bdom == AF_INET) 155ca26842eSHajimu UMEMOTO alloclen = sizeof(struct sockaddr_in); 156ca26842eSHajimu UMEMOTO 157ca26842eSHajimu UMEMOTO sa = (struct sockaddr *) kosa; 158ca26842eSHajimu UMEMOTO sa->sa_family = bdom; 159ca26842eSHajimu UMEMOTO sa->sa_len = alloclen; 160ca26842eSHajimu UMEMOTO 161ca26842eSHajimu UMEMOTO *sap = sa; 162ca26842eSHajimu UMEMOTO *osalen = alloclen; 163ca26842eSHajimu UMEMOTO return (0); 164ca26842eSHajimu UMEMOTO 165ca26842eSHajimu UMEMOTO out: 166ca26842eSHajimu UMEMOTO FREE(kosa, mtype); 167ca26842eSHajimu UMEMOTO return (error); 168ca26842eSHajimu UMEMOTO } 169ca26842eSHajimu UMEMOTO 170c21dee17SSøren Schmidt static int 171c21dee17SSøren Schmidt linux_to_bsd_domain(int domain) 172c21dee17SSøren Schmidt { 1733f3a4815SMarcel Moolenaar 174c21dee17SSøren Schmidt switch (domain) { 175c21dee17SSøren Schmidt case LINUX_AF_UNSPEC: 1763f3a4815SMarcel Moolenaar return (AF_UNSPEC); 177c21dee17SSøren Schmidt case LINUX_AF_UNIX: 1783f3a4815SMarcel Moolenaar return (AF_LOCAL); 179c21dee17SSøren Schmidt case LINUX_AF_INET: 1803f3a4815SMarcel Moolenaar return (AF_INET); 181ca26842eSHajimu UMEMOTO case LINUX_AF_INET6: 182ca26842eSHajimu UMEMOTO return (AF_INET6); 183c21dee17SSøren Schmidt case LINUX_AF_AX25: 1843f3a4815SMarcel Moolenaar return (AF_CCITT); 185c21dee17SSøren Schmidt case LINUX_AF_IPX: 1863f3a4815SMarcel Moolenaar return (AF_IPX); 187c21dee17SSøren Schmidt case LINUX_AF_APPLETALK: 1883f3a4815SMarcel Moolenaar return (AF_APPLETALK); 189c21dee17SSøren Schmidt } 1903f3a4815SMarcel Moolenaar return (-1); 191c21dee17SSøren Schmidt } 192c21dee17SSøren Schmidt 193ca26842eSHajimu UMEMOTO #ifndef __alpha__ 194ca26842eSHajimu UMEMOTO static int 195ca26842eSHajimu UMEMOTO bsd_to_linux_domain(int domain) 196ca26842eSHajimu UMEMOTO { 197ca26842eSHajimu UMEMOTO 198ca26842eSHajimu UMEMOTO switch (domain) { 199ca26842eSHajimu UMEMOTO case AF_UNSPEC: 200ca26842eSHajimu UMEMOTO return (LINUX_AF_UNSPEC); 201ca26842eSHajimu UMEMOTO case AF_LOCAL: 202ca26842eSHajimu UMEMOTO return (LINUX_AF_UNIX); 203ca26842eSHajimu UMEMOTO case AF_INET: 204ca26842eSHajimu UMEMOTO return (LINUX_AF_INET); 205ca26842eSHajimu UMEMOTO case AF_INET6: 206ca26842eSHajimu UMEMOTO return (LINUX_AF_INET6); 207ca26842eSHajimu UMEMOTO case AF_CCITT: 208ca26842eSHajimu UMEMOTO return (LINUX_AF_AX25); 209ca26842eSHajimu UMEMOTO case AF_IPX: 210ca26842eSHajimu UMEMOTO return (LINUX_AF_IPX); 211ca26842eSHajimu UMEMOTO case AF_APPLETALK: 212ca26842eSHajimu UMEMOTO return (LINUX_AF_APPLETALK); 213ca26842eSHajimu UMEMOTO } 214ca26842eSHajimu UMEMOTO return (-1); 215ca26842eSHajimu UMEMOTO } 216ca26842eSHajimu UMEMOTO 217c21dee17SSøren Schmidt static int 218c21dee17SSøren Schmidt linux_to_bsd_sockopt_level(int level) 219c21dee17SSøren Schmidt { 2203f3a4815SMarcel Moolenaar 221c21dee17SSøren Schmidt switch (level) { 222c21dee17SSøren Schmidt case LINUX_SOL_SOCKET: 2233f3a4815SMarcel Moolenaar return (SOL_SOCKET); 224c21dee17SSøren Schmidt } 2253f3a4815SMarcel Moolenaar return (level); 226c21dee17SSøren Schmidt } 227c21dee17SSøren Schmidt 2283f3a4815SMarcel Moolenaar static int 22984b11cd8SMitsuru IWASAKI bsd_to_linux_sockopt_level(int level) 23084b11cd8SMitsuru IWASAKI { 23184b11cd8SMitsuru IWASAKI 23284b11cd8SMitsuru IWASAKI switch (level) { 23384b11cd8SMitsuru IWASAKI case SOL_SOCKET: 23484b11cd8SMitsuru IWASAKI return (LINUX_SOL_SOCKET); 23584b11cd8SMitsuru IWASAKI } 23684b11cd8SMitsuru IWASAKI return (level); 23784b11cd8SMitsuru IWASAKI } 23884b11cd8SMitsuru IWASAKI 23984b11cd8SMitsuru IWASAKI static int 2403f3a4815SMarcel Moolenaar linux_to_bsd_ip_sockopt(int opt) 241c21dee17SSøren Schmidt { 2423f3a4815SMarcel Moolenaar 243c21dee17SSøren Schmidt switch (opt) { 244c21dee17SSøren Schmidt case LINUX_IP_TOS: 2453f3a4815SMarcel Moolenaar return (IP_TOS); 246c21dee17SSøren Schmidt case LINUX_IP_TTL: 2473f3a4815SMarcel Moolenaar return (IP_TTL); 24866ff6a3cSBill Fenner case LINUX_IP_OPTIONS: 2493f3a4815SMarcel Moolenaar return (IP_OPTIONS); 25066ff6a3cSBill Fenner case LINUX_IP_MULTICAST_IF: 2513f3a4815SMarcel Moolenaar return (IP_MULTICAST_IF); 25266ff6a3cSBill Fenner case LINUX_IP_MULTICAST_TTL: 2533f3a4815SMarcel Moolenaar return (IP_MULTICAST_TTL); 25466ff6a3cSBill Fenner case LINUX_IP_MULTICAST_LOOP: 2553f3a4815SMarcel Moolenaar return (IP_MULTICAST_LOOP); 25666ff6a3cSBill Fenner case LINUX_IP_ADD_MEMBERSHIP: 2573f3a4815SMarcel Moolenaar return (IP_ADD_MEMBERSHIP); 25866ff6a3cSBill Fenner case LINUX_IP_DROP_MEMBERSHIP: 2593f3a4815SMarcel Moolenaar return (IP_DROP_MEMBERSHIP); 26066ff6a3cSBill Fenner case LINUX_IP_HDRINCL: 2613f3a4815SMarcel Moolenaar return (IP_HDRINCL); 262c21dee17SSøren Schmidt } 2633f3a4815SMarcel Moolenaar return (-1); 264c21dee17SSøren Schmidt } 265c21dee17SSøren Schmidt 266c21dee17SSøren Schmidt static int 267c21dee17SSøren Schmidt linux_to_bsd_so_sockopt(int opt) 268c21dee17SSøren Schmidt { 2693f3a4815SMarcel Moolenaar 270c21dee17SSøren Schmidt switch (opt) { 271c21dee17SSøren Schmidt case LINUX_SO_DEBUG: 2723f3a4815SMarcel Moolenaar return (SO_DEBUG); 273c21dee17SSøren Schmidt case LINUX_SO_REUSEADDR: 2743f3a4815SMarcel Moolenaar return (SO_REUSEADDR); 275c21dee17SSøren Schmidt case LINUX_SO_TYPE: 2763f3a4815SMarcel Moolenaar return (SO_TYPE); 277c21dee17SSøren Schmidt case LINUX_SO_ERROR: 2783f3a4815SMarcel Moolenaar return (SO_ERROR); 279c21dee17SSøren Schmidt case LINUX_SO_DONTROUTE: 2803f3a4815SMarcel Moolenaar return (SO_DONTROUTE); 281c21dee17SSøren Schmidt case LINUX_SO_BROADCAST: 2823f3a4815SMarcel Moolenaar return (SO_BROADCAST); 283c21dee17SSøren Schmidt case LINUX_SO_SNDBUF: 2843f3a4815SMarcel Moolenaar return (SO_SNDBUF); 285c21dee17SSøren Schmidt case LINUX_SO_RCVBUF: 2863f3a4815SMarcel Moolenaar return (SO_RCVBUF); 287c21dee17SSøren Schmidt case LINUX_SO_KEEPALIVE: 2883f3a4815SMarcel Moolenaar return (SO_KEEPALIVE); 289c21dee17SSøren Schmidt case LINUX_SO_OOBINLINE: 2903f3a4815SMarcel Moolenaar return (SO_OOBINLINE); 291c21dee17SSøren Schmidt case LINUX_SO_LINGER: 2923f3a4815SMarcel Moolenaar return (SO_LINGER); 293c21dee17SSøren Schmidt } 2943f3a4815SMarcel Moolenaar return (-1); 295c21dee17SSøren Schmidt } 296c21dee17SSøren Schmidt 29740dbba57SAssar Westerlund static int 29840dbba57SAssar Westerlund linux_to_bsd_msg_flags(int flags) 29940dbba57SAssar Westerlund { 30040dbba57SAssar Westerlund int ret_flags = 0; 30140dbba57SAssar Westerlund 30240dbba57SAssar Westerlund if (flags & LINUX_MSG_OOB) 30340dbba57SAssar Westerlund ret_flags |= MSG_OOB; 30440dbba57SAssar Westerlund if (flags & LINUX_MSG_PEEK) 30540dbba57SAssar Westerlund ret_flags |= MSG_PEEK; 30640dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTROUTE) 30740dbba57SAssar Westerlund ret_flags |= MSG_DONTROUTE; 30840dbba57SAssar Westerlund if (flags & LINUX_MSG_CTRUNC) 30940dbba57SAssar Westerlund ret_flags |= MSG_CTRUNC; 31040dbba57SAssar Westerlund if (flags & LINUX_MSG_TRUNC) 31140dbba57SAssar Westerlund ret_flags |= MSG_TRUNC; 31240dbba57SAssar Westerlund if (flags & LINUX_MSG_DONTWAIT) 31340dbba57SAssar Westerlund ret_flags |= MSG_DONTWAIT; 31440dbba57SAssar Westerlund if (flags & LINUX_MSG_EOR) 31540dbba57SAssar Westerlund ret_flags |= MSG_EOR; 31640dbba57SAssar Westerlund if (flags & LINUX_MSG_WAITALL) 31740dbba57SAssar Westerlund ret_flags |= MSG_WAITALL; 31840dbba57SAssar Westerlund #if 0 /* not handled */ 31940dbba57SAssar Westerlund if (flags & LINUX_MSG_PROXY) 32040dbba57SAssar Westerlund ; 32140dbba57SAssar Westerlund if (flags & LINUX_MSG_FIN) 32240dbba57SAssar Westerlund ; 32340dbba57SAssar Westerlund if (flags & LINUX_MSG_SYN) 32440dbba57SAssar Westerlund ; 32540dbba57SAssar Westerlund if (flags & LINUX_MSG_CONFIRM) 32640dbba57SAssar Westerlund ; 32740dbba57SAssar Westerlund if (flags & LINUX_MSG_RST) 32840dbba57SAssar Westerlund ; 32940dbba57SAssar Westerlund if (flags & LINUX_MSG_ERRQUEUE) 33040dbba57SAssar Westerlund ; 33140dbba57SAssar Westerlund if (flags & LINUX_MSG_NOSIGNAL) 33240dbba57SAssar Westerlund ; 33340dbba57SAssar Westerlund #endif 33440dbba57SAssar Westerlund return ret_flags; 33540dbba57SAssar Westerlund } 33640dbba57SAssar Westerlund 337ca26842eSHajimu UMEMOTO static int 338ca26842eSHajimu UMEMOTO linux_sa_put(struct osockaddr *osa) 339ca26842eSHajimu UMEMOTO { 340ca26842eSHajimu UMEMOTO struct osockaddr sa; 341ca26842eSHajimu UMEMOTO int error, bdom; 342ca26842eSHajimu UMEMOTO 343ca26842eSHajimu UMEMOTO /* 344ca26842eSHajimu UMEMOTO * Only read/write the osockaddr family part, the rest is 345ca26842eSHajimu UMEMOTO * not changed. 346ca26842eSHajimu UMEMOTO */ 3474b7ef73dSDag-Erling Smørgrav error = copyin(osa, &sa, sizeof(sa.sa_family)); 348ca26842eSHajimu UMEMOTO if (error) 349ca26842eSHajimu UMEMOTO return (error); 350ca26842eSHajimu UMEMOTO 351ca26842eSHajimu UMEMOTO bdom = bsd_to_linux_domain(sa.sa_family); 352ca26842eSHajimu UMEMOTO if (bdom == -1) 353ca26842eSHajimu UMEMOTO return (EINVAL); 354ca26842eSHajimu UMEMOTO 355ca26842eSHajimu UMEMOTO sa.sa_family = bdom; 356ca26842eSHajimu UMEMOTO error = copyout(&sa, osa, sizeof(sa.sa_family)); 357ca26842eSHajimu UMEMOTO if (error) 358ca26842eSHajimu UMEMOTO return (error); 359ca26842eSHajimu UMEMOTO 360ca26842eSHajimu UMEMOTO return (0); 361ca26842eSHajimu UMEMOTO } 362ca26842eSHajimu UMEMOTO 3635a8a13e0SDavid Malone static int 3645a8a13e0SDavid Malone linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags) 3655a8a13e0SDavid Malone { 3665a8a13e0SDavid Malone struct mbuf *control; 3675a8a13e0SDavid Malone struct sockaddr *to; 3685a8a13e0SDavid Malone int error; 3695a8a13e0SDavid Malone 3705a8a13e0SDavid Malone if (mp->msg_name != NULL) { 3715a8a13e0SDavid Malone error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen); 3725a8a13e0SDavid Malone if (error) 3735a8a13e0SDavid Malone return (error); 3745a8a13e0SDavid Malone mp->msg_name = to; 3755a8a13e0SDavid Malone } else 3765a8a13e0SDavid Malone to = NULL; 3775a8a13e0SDavid Malone 3785a8a13e0SDavid Malone if (mp->msg_control != NULL) { 3795a8a13e0SDavid Malone struct cmsghdr *cmsg; 3805a8a13e0SDavid Malone 3815a8a13e0SDavid Malone if (mp->msg_controllen < sizeof(struct cmsghdr)) { 3825a8a13e0SDavid Malone error = EINVAL; 3835a8a13e0SDavid Malone goto bad; 3845a8a13e0SDavid Malone } 3855a8a13e0SDavid Malone error = sockargs(&control, mp->msg_control, 3865a8a13e0SDavid Malone mp->msg_controllen, MT_CONTROL); 3875a8a13e0SDavid Malone if (error) 3885a8a13e0SDavid Malone goto bad; 3895a8a13e0SDavid Malone 3905a8a13e0SDavid Malone cmsg = mtod(control, struct cmsghdr *); 3915a8a13e0SDavid Malone cmsg->cmsg_level = linux_to_bsd_sockopt_level(cmsg->cmsg_level); 3925a8a13e0SDavid Malone } else 3935a8a13e0SDavid Malone control = NULL; 3945a8a13e0SDavid Malone 3955a8a13e0SDavid Malone error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control); 3965a8a13e0SDavid Malone 3975a8a13e0SDavid Malone bad: 3985a8a13e0SDavid Malone if (to) 3995a8a13e0SDavid Malone FREE(to, M_SONAME); 4005a8a13e0SDavid Malone return (error); 4015a8a13e0SDavid Malone } 4025a8a13e0SDavid Malone 4033f3a4815SMarcel Moolenaar /* Return 0 if IP_HDRINCL is set for the given socket. */ 404f2477ae1SMike Smith static int 4054d45de74SDavid Malone linux_check_hdrincl(struct thread *td, caddr_t *sg, int s) 406f2477ae1SMike Smith { 407f2477ae1SMike Smith struct getsockopt_args /* { 408f2477ae1SMike Smith int s; 409f2477ae1SMike Smith int level; 410f2477ae1SMike Smith int name; 411f2477ae1SMike Smith caddr_t val; 412f2477ae1SMike Smith int *avalsize; 413f2477ae1SMike Smith } */ bsd_args; 414f2477ae1SMike Smith int error; 4154d45de74SDavid Malone caddr_t val, valsize; 416f2477ae1SMike Smith int size_val = sizeof val; 417f2477ae1SMike Smith int optval; 418f2477ae1SMike Smith 4194d45de74SDavid Malone val = stackgap_alloc(sg, sizeof(int)); 4204d45de74SDavid Malone valsize = stackgap_alloc(sg, sizeof(int)); 421f2477ae1SMike Smith 422f2477ae1SMike Smith if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 4233f3a4815SMarcel Moolenaar return (error); 4243f3a4815SMarcel Moolenaar 425f2477ae1SMike Smith bsd_args.s = s; 426f2477ae1SMike Smith bsd_args.level = IPPROTO_IP; 427f2477ae1SMike Smith bsd_args.name = IP_HDRINCL; 428f2477ae1SMike Smith bsd_args.val = val; 429f2477ae1SMike Smith bsd_args.avalsize = (int *)valsize; 430b40ce416SJulian Elischer if ((error = getsockopt(td, &bsd_args))) 4313f3a4815SMarcel Moolenaar return (error); 4323f3a4815SMarcel Moolenaar 433f2477ae1SMike Smith if ((error = copyin(val, &optval, sizeof(optval)))) 4343f3a4815SMarcel Moolenaar return (error); 4353f3a4815SMarcel Moolenaar 4363f3a4815SMarcel Moolenaar return (optval == 0); 437f2477ae1SMike Smith } 438f2477ae1SMike Smith 4395a8a13e0SDavid Malone struct linux_sendto_args { 4405a8a13e0SDavid Malone int s; 4415a8a13e0SDavid Malone void *msg; 4425a8a13e0SDavid Malone int len; 4435a8a13e0SDavid Malone int flags; 4445a8a13e0SDavid Malone caddr_t to; 4455a8a13e0SDavid Malone int tolen; 4465a8a13e0SDavid Malone }; 4475a8a13e0SDavid Malone 448f2477ae1SMike Smith /* 449f2477ae1SMike Smith * Updated sendto() when IP_HDRINCL is set: 450f2477ae1SMike Smith * tweak endian-dependent fields in the IP packet. 451f2477ae1SMike Smith */ 452f2477ae1SMike Smith static int 4535a8a13e0SDavid Malone linux_sendto_hdrincl(struct thread *td, caddr_t *sg, struct linux_sendto_args *linux_args) 454f2477ae1SMike Smith { 455f2477ae1SMike Smith /* 456f2477ae1SMike Smith * linux_ip_copysize defines how many bytes we should copy 457f2477ae1SMike Smith * from the beginning of the IP packet before we customize it for BSD. 458f2477ae1SMike Smith * It should include all the fields we modify (ip_len and ip_off) 459f2477ae1SMike Smith * and be as small as possible to minimize copying overhead. 460f2477ae1SMike Smith */ 461f2477ae1SMike Smith #define linux_ip_copysize 8 462f2477ae1SMike Smith 463f2477ae1SMike Smith struct ip *packet; 4645a8a13e0SDavid Malone struct msghdr msg; 4655a8a13e0SDavid Malone struct iovec aiov[2]; 466f2477ae1SMike Smith int error; 467f2477ae1SMike Smith 468f2477ae1SMike Smith /* Check the packet isn't too small before we mess with it */ 4695a8a13e0SDavid Malone if (linux_args->len < linux_ip_copysize) 4703f3a4815SMarcel Moolenaar return (EINVAL); 471f2477ae1SMike Smith 472f2477ae1SMike Smith /* 473f2477ae1SMike Smith * Tweaking the user buffer in place would be bad manners. 474f2477ae1SMike Smith * We create a corrected IP header with just the needed length, 475f2477ae1SMike Smith * then use an iovec to glue it to the rest of the user packet 4765a8a13e0SDavid Malone * when calling sendit(). 477f2477ae1SMike Smith */ 4784d45de74SDavid Malone packet = (struct ip *)stackgap_alloc(sg, linux_ip_copysize); 479f2477ae1SMike Smith 480f2477ae1SMike Smith /* Make a copy of the beginning of the packet to be sent */ 4815a8a13e0SDavid Malone if ((error = copyin(linux_args->msg, packet, linux_ip_copysize))) 4823f3a4815SMarcel Moolenaar return (error); 483f2477ae1SMike Smith 484f2477ae1SMike Smith /* Convert fields from Linux to BSD raw IP socket format */ 4855a8a13e0SDavid Malone packet->ip_len = linux_args->len; 486f2477ae1SMike Smith packet->ip_off = ntohs(packet->ip_off); 487f2477ae1SMike Smith 488f2477ae1SMike Smith /* Prepare the msghdr and iovec structures describing the new packet */ 4895a8a13e0SDavid Malone msg.msg_name = linux_args->to; 4905a8a13e0SDavid Malone msg.msg_namelen = linux_args->tolen; 4915a8a13e0SDavid Malone msg.msg_iov = aiov; 4925a8a13e0SDavid Malone msg.msg_iovlen = 2; 4935a8a13e0SDavid Malone msg.msg_control = NULL; 4945a8a13e0SDavid Malone msg.msg_flags = 0; 4955a8a13e0SDavid Malone aiov[0].iov_base = (char *)packet; 4965a8a13e0SDavid Malone aiov[0].iov_len = linux_ip_copysize; 4975a8a13e0SDavid Malone aiov[1].iov_base = (char *)(linux_args->msg) + linux_ip_copysize; 4985a8a13e0SDavid Malone aiov[1].iov_len = linux_args->len - linux_ip_copysize; 4995a8a13e0SDavid Malone error = linux_sendit(td, linux_args->s, &msg, linux_args->flags); 5005a8a13e0SDavid Malone return (error); 501f2477ae1SMike Smith } 502f2477ae1SMike Smith 503c21dee17SSøren Schmidt struct linux_socket_args { 504c21dee17SSøren Schmidt int domain; 505c21dee17SSøren Schmidt int type; 506c21dee17SSøren Schmidt int protocol; 507c21dee17SSøren Schmidt }; 508c21dee17SSøren Schmidt 509c21dee17SSøren Schmidt static int 510b40ce416SJulian Elischer linux_socket(struct thread *td, struct linux_socket_args *args) 511c21dee17SSøren Schmidt { 512c21dee17SSøren Schmidt struct linux_socket_args linux_args; 513ef04503dSPeter Wemm struct socket_args /* { 514c21dee17SSøren Schmidt int domain; 515c21dee17SSøren Schmidt int type; 516c21dee17SSøren Schmidt int protocol; 517ef04503dSPeter Wemm } */ bsd_args; 518ca26842eSHajimu UMEMOTO struct setsockopt_args /* { 519ca26842eSHajimu UMEMOTO int s; 520ca26842eSHajimu UMEMOTO int level; 521ca26842eSHajimu UMEMOTO int name; 522ca26842eSHajimu UMEMOTO caddr_t val; 523ca26842eSHajimu UMEMOTO int valsize; 524ca26842eSHajimu UMEMOTO } */ bsd_setsockopt_args; 525c21dee17SSøren Schmidt int error; 526f2477ae1SMike Smith int retval_socket; 527c21dee17SSøren Schmidt 5283f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 5293f3a4815SMarcel Moolenaar return (error); 5303f3a4815SMarcel Moolenaar 531c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 532c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 533c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 534c21dee17SSøren Schmidt if (bsd_args.domain == -1) 5353f3a4815SMarcel Moolenaar return (EINVAL); 536f2477ae1SMike Smith 537b40ce416SJulian Elischer retval_socket = socket(td, &bsd_args); 538f2477ae1SMike Smith if (bsd_args.type == SOCK_RAW 539f2477ae1SMike Smith && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 540f2477ae1SMike Smith && bsd_args.domain == AF_INET 541f2477ae1SMike Smith && retval_socket >= 0) { 542f2477ae1SMike Smith /* It's a raw IP socket: set the IP_HDRINCL option. */ 543f2477ae1SMike Smith caddr_t sg; 544f2477ae1SMike Smith int *hdrincl; 545f2477ae1SMike Smith 546f2477ae1SMike Smith sg = stackgap_init(); 547f2477ae1SMike Smith hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 548f2477ae1SMike Smith *hdrincl = 1; 549b40ce416SJulian Elischer bsd_setsockopt_args.s = td->td_retval[0]; 550f2477ae1SMike Smith bsd_setsockopt_args.level = IPPROTO_IP; 551f2477ae1SMike Smith bsd_setsockopt_args.name = IP_HDRINCL; 552f2477ae1SMike Smith bsd_setsockopt_args.val = (caddr_t)hdrincl; 553f2477ae1SMike Smith bsd_setsockopt_args.valsize = sizeof(*hdrincl); 554f2477ae1SMike Smith /* We ignore any error returned by setsockopt() */ 555b40ce416SJulian Elischer setsockopt(td, &bsd_setsockopt_args); 556f2477ae1SMike Smith /* Copy back the return value from socket() */ 557b40ce416SJulian Elischer td->td_retval[0] = bsd_setsockopt_args.s; 558f2477ae1SMike Smith } 559ca26842eSHajimu UMEMOTO #ifdef INET6 560ca26842eSHajimu UMEMOTO /* 561ca26842eSHajimu UMEMOTO * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 562ca26842eSHajimu UMEMOTO * default and some apps depend on this. So, set V6ONLY to 0 563ca26842eSHajimu UMEMOTO * for Linux apps if the sysctl value is set to 1. 564ca26842eSHajimu UMEMOTO */ 56537e7a5a2SHajimu UMEMOTO if (bsd_args.domain == PF_INET6 && retval_socket >= 0 56637e7a5a2SHajimu UMEMOTO #ifndef KLD_MODULE 56737e7a5a2SHajimu UMEMOTO /* 56837e7a5a2SHajimu UMEMOTO * XXX: Avoid undefined symbol error with an IPv4 only 56937e7a5a2SHajimu UMEMOTO * kernel. 57037e7a5a2SHajimu UMEMOTO */ 57137e7a5a2SHajimu UMEMOTO && ip6_v6only 57237e7a5a2SHajimu UMEMOTO #endif 57337e7a5a2SHajimu UMEMOTO ) { 574ca26842eSHajimu UMEMOTO caddr_t sg; 575ca26842eSHajimu UMEMOTO int *v6only; 576ca26842eSHajimu UMEMOTO 577ca26842eSHajimu UMEMOTO sg = stackgap_init(); 578ca26842eSHajimu UMEMOTO v6only = (int *)stackgap_alloc(&sg, sizeof(*v6only)); 579ca26842eSHajimu UMEMOTO *v6only = 0; 580ca26842eSHajimu UMEMOTO bsd_setsockopt_args.s = td->td_retval[0]; 581ca26842eSHajimu UMEMOTO bsd_setsockopt_args.level = IPPROTO_IPV6; 582ca26842eSHajimu UMEMOTO bsd_setsockopt_args.name = IPV6_V6ONLY; 583ca26842eSHajimu UMEMOTO bsd_setsockopt_args.val = (caddr_t)v6only; 584ca26842eSHajimu UMEMOTO bsd_setsockopt_args.valsize = sizeof(*v6only); 585ca26842eSHajimu UMEMOTO /* We ignore any error returned by setsockopt() */ 586ca26842eSHajimu UMEMOTO setsockopt(td, &bsd_setsockopt_args); 587ca26842eSHajimu UMEMOTO /* Copy back the return value from socket() */ 588ca26842eSHajimu UMEMOTO td->td_retval[0] = bsd_setsockopt_args.s; 589ca26842eSHajimu UMEMOTO } 590ca26842eSHajimu UMEMOTO #endif 5913f3a4815SMarcel Moolenaar 5923f3a4815SMarcel Moolenaar return (retval_socket); 593c21dee17SSøren Schmidt } 594c21dee17SSøren Schmidt 595c21dee17SSøren Schmidt struct linux_bind_args { 596c21dee17SSøren Schmidt int s; 597ca26842eSHajimu UMEMOTO struct osockaddr *name; 598c21dee17SSøren Schmidt int namelen; 599c21dee17SSøren Schmidt }; 600c21dee17SSøren Schmidt 601c21dee17SSøren Schmidt static int 602b40ce416SJulian Elischer linux_bind(struct thread *td, struct linux_bind_args *args) 603c21dee17SSøren Schmidt { 604c21dee17SSøren Schmidt struct linux_bind_args linux_args; 605ca26842eSHajimu UMEMOTO struct sockaddr *sa; 606c21dee17SSøren Schmidt int error; 607c21dee17SSøren Schmidt 6083f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6093f3a4815SMarcel Moolenaar return (error); 6103f3a4815SMarcel Moolenaar 611ca26842eSHajimu UMEMOTO error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); 612ca26842eSHajimu UMEMOTO if (error) 613ca26842eSHajimu UMEMOTO return (error); 614ca26842eSHajimu UMEMOTO 615ca26842eSHajimu UMEMOTO return (kern_bind(td, linux_args.s, sa)); 616c21dee17SSøren Schmidt } 617c21dee17SSøren Schmidt 618c21dee17SSøren Schmidt struct linux_connect_args { 619c21dee17SSøren Schmidt int s; 620ca26842eSHajimu UMEMOTO struct osockaddr * name; 621c21dee17SSøren Schmidt int namelen; 622c21dee17SSøren Schmidt }; 623b40ce416SJulian Elischer int linux_connect(struct thread *, struct linux_connect_args *); 624930a65feSAndrew Gallatin #endif /* !__alpha__*/ 625c21dee17SSøren Schmidt 626930a65feSAndrew Gallatin int 627b40ce416SJulian Elischer linux_connect(struct thread *td, struct linux_connect_args *args) 628c21dee17SSøren Schmidt { 629c21dee17SSøren Schmidt struct linux_connect_args linux_args; 6300bf301c0SJonathan Lemon struct socket *so; 631ca26842eSHajimu UMEMOTO struct sockaddr *sa; 63239c95b83SMatthew Dillon u_int fflag; 633c21dee17SSøren Schmidt int error; 634c21dee17SSøren Schmidt 635930a65feSAndrew Gallatin #ifdef __alpha__ 636930a65feSAndrew Gallatin bcopy(args, &linux_args, sizeof(linux_args)); 637930a65feSAndrew Gallatin #else 6383f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6393f3a4815SMarcel Moolenaar return (error); 640930a65feSAndrew Gallatin #endif /* __alpha__ */ 6413f3a4815SMarcel Moolenaar 6424d45de74SDavid Malone error = linux_getsockaddr(&sa, (struct osockaddr *)linux_args.name, 6434d45de74SDavid Malone linux_args.namelen); 644ca26842eSHajimu UMEMOTO if (error) 645ca26842eSHajimu UMEMOTO return (error); 646ca26842eSHajimu UMEMOTO 647ca26842eSHajimu UMEMOTO error = kern_connect(td, linux_args.s, sa); 6480bf301c0SJonathan Lemon if (error != EISCONN) 6490bf301c0SJonathan Lemon return (error); 6500bf301c0SJonathan Lemon 651dad3b88aSMike Smith /* 652dad3b88aSMike Smith * Linux doesn't return EISCONN the first time it occurs, 653dad3b88aSMike Smith * when on a non-blocking socket. Instead it returns the 654dad3b88aSMike Smith * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 655dad3b88aSMike Smith */ 65639c95b83SMatthew Dillon if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) 6573f3a4815SMarcel Moolenaar return(error); 6580bf301c0SJonathan Lemon error = EISCONN; 65939c95b83SMatthew Dillon if (fflag & FNONBLOCK) { 6605002a60fSMarcel Moolenaar if (so->so_emuldata == 0) 6610bf301c0SJonathan Lemon error = so->so_error; 6620bf301c0SJonathan Lemon so->so_emuldata = (void *)1; 663dad3b88aSMike Smith } 66439c95b83SMatthew Dillon fputsock(so); 6653f3a4815SMarcel Moolenaar return (error); 666c21dee17SSøren Schmidt } 667c21dee17SSøren Schmidt 668930a65feSAndrew Gallatin #ifndef __alpha__ 669930a65feSAndrew Gallatin 670c21dee17SSøren Schmidt struct linux_listen_args { 671c21dee17SSøren Schmidt int s; 672c21dee17SSøren Schmidt int backlog; 673c21dee17SSøren Schmidt }; 674c21dee17SSøren Schmidt 675c21dee17SSøren Schmidt static int 676b40ce416SJulian Elischer linux_listen(struct thread *td, struct linux_listen_args *args) 677c21dee17SSøren Schmidt { 678c21dee17SSøren Schmidt struct linux_listen_args linux_args; 679ef04503dSPeter Wemm struct listen_args /* { 680c21dee17SSøren Schmidt int s; 681c21dee17SSøren Schmidt int backlog; 682ef04503dSPeter Wemm } */ bsd_args; 683c21dee17SSøren Schmidt int error; 684c21dee17SSøren Schmidt 6853f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 6863f3a4815SMarcel Moolenaar return (error); 6873f3a4815SMarcel Moolenaar 688c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 689c21dee17SSøren Schmidt bsd_args.backlog = linux_args.backlog; 690b40ce416SJulian Elischer return (listen(td, &bsd_args)); 691c21dee17SSøren Schmidt } 692c21dee17SSøren Schmidt 693c21dee17SSøren Schmidt struct linux_accept_args { 694c21dee17SSøren Schmidt int s; 695ca26842eSHajimu UMEMOTO struct osockaddr *addr; 696c21dee17SSøren Schmidt int *namelen; 697c21dee17SSøren Schmidt }; 698c21dee17SSøren Schmidt 699c21dee17SSøren Schmidt static int 700b40ce416SJulian Elischer linux_accept(struct thread *td, struct linux_accept_args *args) 701c21dee17SSøren Schmidt { 702c21dee17SSøren Schmidt struct linux_accept_args linux_args; 703ef04503dSPeter Wemm struct accept_args /* { 704c21dee17SSøren Schmidt int s; 705c21dee17SSøren Schmidt caddr_t name; 706c21dee17SSøren Schmidt int *anamelen; 707ef04503dSPeter Wemm } */ bsd_args; 708ca26842eSHajimu UMEMOTO struct close_args /* { 709ca26842eSHajimu UMEMOTO int fd; 710ca26842eSHajimu UMEMOTO } */ c_args; 711dba5ab66SMarcel Moolenaar struct fcntl_args /* { 712dba5ab66SMarcel Moolenaar int fd; 713dba5ab66SMarcel Moolenaar int cmd; 714dba5ab66SMarcel Moolenaar long arg; 715dba5ab66SMarcel Moolenaar } */ f_args; 716c21dee17SSøren Schmidt int error; 717c21dee17SSøren Schmidt 7183f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7193f3a4815SMarcel Moolenaar return (error); 7203f3a4815SMarcel Moolenaar 721c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 722c21dee17SSøren Schmidt bsd_args.name = (caddr_t)linux_args.addr; 723c21dee17SSøren Schmidt bsd_args.anamelen = linux_args.namelen; 724044af7c3SJonathan Mini error = oaccept(td, &bsd_args); 725dba5ab66SMarcel Moolenaar if (error) 726dba5ab66SMarcel Moolenaar return (error); 727ca26842eSHajimu UMEMOTO if (linux_args.addr) { 728ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 729ca26842eSHajimu UMEMOTO if (error) { 730ca26842eSHajimu UMEMOTO c_args.fd = td->td_retval[0]; 731ca26842eSHajimu UMEMOTO (void)close(td, &c_args); 732ca26842eSHajimu UMEMOTO return (error); 733ca26842eSHajimu UMEMOTO } 734ca26842eSHajimu UMEMOTO } 735dba5ab66SMarcel Moolenaar 736dba5ab66SMarcel Moolenaar /* 737dba5ab66SMarcel Moolenaar * linux appears not to copy flags from the parent socket to the 738dba5ab66SMarcel Moolenaar * accepted one, so we must clear the flags in the new descriptor. 739dba5ab66SMarcel Moolenaar * Ignore any errors, because we already have an open fd. 740dba5ab66SMarcel Moolenaar */ 741b40ce416SJulian Elischer f_args.fd = td->td_retval[0]; 742dba5ab66SMarcel Moolenaar f_args.cmd = F_SETFL; 743dba5ab66SMarcel Moolenaar f_args.arg = 0; 744b40ce416SJulian Elischer (void)fcntl(td, &f_args); 745b40ce416SJulian Elischer td->td_retval[0] = f_args.fd; 746dba5ab66SMarcel Moolenaar return (0); 747c21dee17SSøren Schmidt } 748c21dee17SSøren Schmidt 749c21dee17SSøren Schmidt struct linux_getsockname_args { 750c21dee17SSøren Schmidt int s; 751ca26842eSHajimu UMEMOTO struct osockaddr *addr; 752c21dee17SSøren Schmidt int *namelen; 753c21dee17SSøren Schmidt }; 754c21dee17SSøren Schmidt 755c21dee17SSøren Schmidt static int 756b40ce416SJulian Elischer linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 757c21dee17SSøren Schmidt { 758c21dee17SSøren Schmidt struct linux_getsockname_args linux_args; 759ef04503dSPeter Wemm struct getsockname_args /* { 760c21dee17SSøren Schmidt int fdes; 761c21dee17SSøren Schmidt caddr_t asa; 762c21dee17SSøren Schmidt int *alen; 763ef04503dSPeter Wemm } */ bsd_args; 764c21dee17SSøren Schmidt int error; 765c21dee17SSøren Schmidt 7663f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7673f3a4815SMarcel Moolenaar return (error); 7683f3a4815SMarcel Moolenaar 769c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 770c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 771c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 772ca26842eSHajimu UMEMOTO error = ogetsockname(td, &bsd_args); 773ca26842eSHajimu UMEMOTO if (error) 774ca26842eSHajimu UMEMOTO return (error); 775ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 776ca26842eSHajimu UMEMOTO if (error) 777ca26842eSHajimu UMEMOTO return (error); 778ca26842eSHajimu UMEMOTO return (0); 779c21dee17SSøren Schmidt } 780c21dee17SSøren Schmidt 781c21dee17SSøren Schmidt struct linux_getpeername_args { 782c21dee17SSøren Schmidt int s; 783ca26842eSHajimu UMEMOTO struct osockaddr *addr; 784c21dee17SSøren Schmidt int *namelen; 785c21dee17SSøren Schmidt }; 786c21dee17SSøren Schmidt 787c21dee17SSøren Schmidt static int 788b40ce416SJulian Elischer linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 789c21dee17SSøren Schmidt { 790c21dee17SSøren Schmidt struct linux_getpeername_args linux_args; 791044af7c3SJonathan Mini struct ogetpeername_args /* { 792c21dee17SSøren Schmidt int fdes; 793c21dee17SSøren Schmidt caddr_t asa; 794c21dee17SSøren Schmidt int *alen; 795ef04503dSPeter Wemm } */ bsd_args; 796c21dee17SSøren Schmidt int error; 797c21dee17SSøren Schmidt 7983f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 7993f3a4815SMarcel Moolenaar return (error); 8003f3a4815SMarcel Moolenaar 801c21dee17SSøren Schmidt bsd_args.fdes = linux_args.s; 802c21dee17SSøren Schmidt bsd_args.asa = (caddr_t) linux_args.addr; 803c21dee17SSøren Schmidt bsd_args.alen = linux_args.namelen; 804ca26842eSHajimu UMEMOTO error = ogetpeername(td, &bsd_args); 805ca26842eSHajimu UMEMOTO if (error) 806ca26842eSHajimu UMEMOTO return (error); 807ca26842eSHajimu UMEMOTO error = linux_sa_put(linux_args.addr); 808ca26842eSHajimu UMEMOTO if (error) 809ca26842eSHajimu UMEMOTO return (error); 810ca26842eSHajimu UMEMOTO return (0); 811c21dee17SSøren Schmidt } 812c21dee17SSøren Schmidt 813c21dee17SSøren Schmidt struct linux_socketpair_args { 814c21dee17SSøren Schmidt int domain; 815c21dee17SSøren Schmidt int type; 816c21dee17SSøren Schmidt int protocol; 817c21dee17SSøren Schmidt int *rsv; 818c21dee17SSøren Schmidt }; 819c21dee17SSøren Schmidt 820c21dee17SSøren Schmidt static int 821b40ce416SJulian Elischer linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 822c21dee17SSøren Schmidt { 823c21dee17SSøren Schmidt struct linux_socketpair_args linux_args; 824ef04503dSPeter Wemm struct socketpair_args /* { 825c21dee17SSøren Schmidt int domain; 826c21dee17SSøren Schmidt int type; 827c21dee17SSøren Schmidt int protocol; 828c21dee17SSøren Schmidt int *rsv; 829ef04503dSPeter Wemm } */ bsd_args; 830c21dee17SSøren Schmidt int error; 831c21dee17SSøren Schmidt 8323f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8333f3a4815SMarcel Moolenaar return (error); 8343f3a4815SMarcel Moolenaar 835c21dee17SSøren Schmidt bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 836c21dee17SSøren Schmidt if (bsd_args.domain == -1) 8373f3a4815SMarcel Moolenaar return (EINVAL); 8383f3a4815SMarcel Moolenaar 839c21dee17SSøren Schmidt bsd_args.type = linux_args.type; 840c21dee17SSøren Schmidt bsd_args.protocol = linux_args.protocol; 841c21dee17SSøren Schmidt bsd_args.rsv = linux_args.rsv; 842b40ce416SJulian Elischer return (socketpair(td, &bsd_args)); 843c21dee17SSøren Schmidt } 844c21dee17SSøren Schmidt 845c21dee17SSøren Schmidt struct linux_send_args { 846c21dee17SSøren Schmidt int s; 847c21dee17SSøren Schmidt void *msg; 848c21dee17SSøren Schmidt int len; 849c21dee17SSøren Schmidt int flags; 850c21dee17SSøren Schmidt }; 851c21dee17SSøren Schmidt 852c21dee17SSøren Schmidt static int 853b40ce416SJulian Elischer linux_send(struct thread *td, struct linux_send_args *args) 854c21dee17SSøren Schmidt { 855c21dee17SSøren Schmidt struct linux_send_args linux_args; 856044af7c3SJonathan Mini struct osend_args /* { 857c21dee17SSøren Schmidt int s; 858c21dee17SSøren Schmidt caddr_t buf; 859044af7c3SJonathan Mini int len; 860c21dee17SSøren Schmidt int flags; 861ef04503dSPeter Wemm } */ bsd_args; 862c21dee17SSøren Schmidt int error; 863c21dee17SSøren Schmidt 8643f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8653f3a4815SMarcel Moolenaar return (error); 8663f3a4815SMarcel Moolenaar 867c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 868c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 869c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 870c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 871044af7c3SJonathan Mini return (osend(td, &bsd_args)); 872c21dee17SSøren Schmidt } 873c21dee17SSøren Schmidt 874c21dee17SSøren Schmidt struct linux_recv_args { 875c21dee17SSøren Schmidt int s; 876c21dee17SSøren Schmidt void *msg; 877c21dee17SSøren Schmidt int len; 878c21dee17SSøren Schmidt int flags; 879c21dee17SSøren Schmidt }; 880c21dee17SSøren Schmidt 881c21dee17SSøren Schmidt static int 882b40ce416SJulian Elischer linux_recv(struct thread *td, struct linux_recv_args *args) 883c21dee17SSøren Schmidt { 884c21dee17SSøren Schmidt struct linux_recv_args linux_args; 885044af7c3SJonathan Mini struct orecv_args /* { 886c21dee17SSøren Schmidt int s; 887c21dee17SSøren Schmidt caddr_t buf; 888c21dee17SSøren Schmidt int len; 889c21dee17SSøren Schmidt int flags; 890ef04503dSPeter Wemm } */ bsd_args; 891c21dee17SSøren Schmidt int error; 892c21dee17SSøren Schmidt 8933f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 8943f3a4815SMarcel Moolenaar return (error); 8953f3a4815SMarcel Moolenaar 896c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 897c21dee17SSøren Schmidt bsd_args.buf = linux_args.msg; 898c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 899c21dee17SSøren Schmidt bsd_args.flags = linux_args.flags; 900044af7c3SJonathan Mini return (orecv(td, &bsd_args)); 901c21dee17SSøren Schmidt } 902c21dee17SSøren Schmidt 903c21dee17SSøren Schmidt static int 904b40ce416SJulian Elischer linux_sendto(struct thread *td, struct linux_sendto_args *args) 905c21dee17SSøren Schmidt { 906c21dee17SSøren Schmidt struct linux_sendto_args linux_args; 9075a8a13e0SDavid Malone struct msghdr msg; 9085a8a13e0SDavid Malone struct iovec aiov; 909ca26842eSHajimu UMEMOTO caddr_t sg = stackgap_init(); 9105a8a13e0SDavid Malone int error; 911c21dee17SSøren Schmidt 9123f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9133f3a4815SMarcel Moolenaar return (error); 9143f3a4815SMarcel Moolenaar 9154d45de74SDavid Malone if (linux_check_hdrincl(td, &sg, linux_args.s) == 0) 916f2477ae1SMike Smith /* IP_HDRINCL set, tweak the packet before sending */ 9175a8a13e0SDavid Malone return (linux_sendto_hdrincl(td, &sg, &linux_args)); 918f2477ae1SMike Smith 9195a8a13e0SDavid Malone msg.msg_name = linux_args.to; 9205a8a13e0SDavid Malone msg.msg_namelen = linux_args.tolen; 9215a8a13e0SDavid Malone msg.msg_iov = &aiov; 9225a8a13e0SDavid Malone msg.msg_iovlen = 1; 9235a8a13e0SDavid Malone msg.msg_control = NULL; 9245a8a13e0SDavid Malone msg.msg_flags = 0; 9255a8a13e0SDavid Malone aiov.iov_base = linux_args.msg; 9265a8a13e0SDavid Malone aiov.iov_len = linux_args.len; 9275a8a13e0SDavid Malone error = linux_sendit(td, linux_args.s, &msg, linux_args.flags); 9285a8a13e0SDavid Malone return (error); 929c21dee17SSøren Schmidt } 930c21dee17SSøren Schmidt 931c21dee17SSøren Schmidt struct linux_recvfrom_args { 932c21dee17SSøren Schmidt int s; 933c21dee17SSøren Schmidt void *buf; 934c21dee17SSøren Schmidt int len; 935c21dee17SSøren Schmidt int flags; 936c21dee17SSøren Schmidt caddr_t from; 937c21dee17SSøren Schmidt int *fromlen; 938c21dee17SSøren Schmidt }; 939c21dee17SSøren Schmidt 940c21dee17SSøren Schmidt static int 941b40ce416SJulian Elischer linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 942c21dee17SSøren Schmidt { 943c21dee17SSøren Schmidt struct linux_recvfrom_args linux_args; 944ef04503dSPeter Wemm struct recvfrom_args /* { 945c21dee17SSøren Schmidt int s; 946c21dee17SSøren Schmidt caddr_t buf; 947c21dee17SSøren Schmidt size_t len; 948c21dee17SSøren Schmidt int flags; 949c21dee17SSøren Schmidt caddr_t from; 950c21dee17SSøren Schmidt int *fromlenaddr; 951ef04503dSPeter Wemm } */ bsd_args; 952c21dee17SSøren Schmidt int error; 953c21dee17SSøren Schmidt 9543f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 9553f3a4815SMarcel Moolenaar return (error); 9563f3a4815SMarcel Moolenaar 957c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 958c21dee17SSøren Schmidt bsd_args.buf = linux_args.buf; 959c21dee17SSøren Schmidt bsd_args.len = linux_args.len; 96040dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 961c21dee17SSøren Schmidt bsd_args.from = linux_args.from; 962c21dee17SSøren Schmidt bsd_args.fromlenaddr = linux_args.fromlen; 963ca26842eSHajimu UMEMOTO error = orecvfrom(td, &bsd_args); 964ca26842eSHajimu UMEMOTO if (error) 965ca26842eSHajimu UMEMOTO return (error); 966ca26842eSHajimu UMEMOTO if (linux_args.from) { 967ca26842eSHajimu UMEMOTO error = linux_sa_put((struct osockaddr *) linux_args.from); 968ca26842eSHajimu UMEMOTO if (error) 969ca26842eSHajimu UMEMOTO return (error); 970ca26842eSHajimu UMEMOTO } 971ca26842eSHajimu UMEMOTO return (0); 972ca26842eSHajimu UMEMOTO } 973ca26842eSHajimu UMEMOTO 974ca26842eSHajimu UMEMOTO struct linux_sendmsg_args { 975ca26842eSHajimu UMEMOTO int s; 976ca26842eSHajimu UMEMOTO const struct msghdr *msg; 977ca26842eSHajimu UMEMOTO int flags; 978ca26842eSHajimu UMEMOTO }; 979ca26842eSHajimu UMEMOTO 980ca26842eSHajimu UMEMOTO static int 981ca26842eSHajimu UMEMOTO linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 982ca26842eSHajimu UMEMOTO { 983ca26842eSHajimu UMEMOTO struct linux_sendmsg_args linux_args; 984ca26842eSHajimu UMEMOTO struct msghdr msg; 9855a8a13e0SDavid Malone struct iovec aiov[UIO_SMALLIOV], *iov; 986ca26842eSHajimu UMEMOTO int error; 987ca26842eSHajimu UMEMOTO 988ca26842eSHajimu UMEMOTO if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 989ca26842eSHajimu UMEMOTO return (error); 990ca26842eSHajimu UMEMOTO 9914b7ef73dSDag-Erling Smørgrav error = copyin(linux_args.msg, &msg, sizeof(msg)); 992ca26842eSHajimu UMEMOTO if (error) 993ca26842eSHajimu UMEMOTO return (error); 9945a8a13e0SDavid Malone if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 9955a8a13e0SDavid Malone if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 9965a8a13e0SDavid Malone return (EMSGSIZE); 9975a8a13e0SDavid Malone MALLOC(iov, struct iovec *, 9985a8a13e0SDavid Malone sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 9995a8a13e0SDavid Malone M_WAITOK); 10005a8a13e0SDavid Malone } else { 10015a8a13e0SDavid Malone iov = aiov; 10025a8a13e0SDavid Malone } 10035a8a13e0SDavid Malone if (msg.msg_iovlen && 10045a8a13e0SDavid Malone (error = copyin(msg.msg_iov, iov, 10055a8a13e0SDavid Malone (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 10065a8a13e0SDavid Malone goto done; 10075a8a13e0SDavid Malone msg.msg_iov = iov; 10085a8a13e0SDavid Malone msg.msg_flags = 0; 1009ca26842eSHajimu UMEMOTO 10105a8a13e0SDavid Malone error = linux_sendit(td, linux_args.s, &msg, linux_args.flags); 10115a8a13e0SDavid Malone done: 10125a8a13e0SDavid Malone if (iov != aiov) 10135a8a13e0SDavid Malone FREE(iov, M_IOV); 1014ca26842eSHajimu UMEMOTO return (error); 1015c21dee17SSøren Schmidt } 1016c21dee17SSøren Schmidt 101740dbba57SAssar Westerlund struct linux_recvmsg_args { 101840dbba57SAssar Westerlund int s; 101940dbba57SAssar Westerlund struct msghdr *msg; 102040dbba57SAssar Westerlund int flags; 102140dbba57SAssar Westerlund }; 102240dbba57SAssar Westerlund 102340dbba57SAssar Westerlund static int 1024b40ce416SJulian Elischer linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 102540dbba57SAssar Westerlund { 102640dbba57SAssar Westerlund struct linux_recvmsg_args linux_args; 102740dbba57SAssar Westerlund struct recvmsg_args /* { 102840dbba57SAssar Westerlund int s; 102940dbba57SAssar Westerlund struct msghdr *msg; 103040dbba57SAssar Westerlund int flags; 103140dbba57SAssar Westerlund } */ bsd_args; 1032ca26842eSHajimu UMEMOTO struct msghdr msg; 103384b11cd8SMitsuru IWASAKI struct cmsghdr *cmsg; 103440dbba57SAssar Westerlund int error; 103540dbba57SAssar Westerlund 103640dbba57SAssar Westerlund if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 103740dbba57SAssar Westerlund return (error); 103840dbba57SAssar Westerlund 103940dbba57SAssar Westerlund bsd_args.s = linux_args.s; 104040dbba57SAssar Westerlund bsd_args.msg = linux_args.msg; 104140dbba57SAssar Westerlund bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 1042ca26842eSHajimu UMEMOTO error = recvmsg(td, &bsd_args); 1043ca26842eSHajimu UMEMOTO if (error) 1044ca26842eSHajimu UMEMOTO return (error); 1045ca26842eSHajimu UMEMOTO 104684b11cd8SMitsuru IWASAKI if (bsd_args.msg->msg_control != NULL) { 104784b11cd8SMitsuru IWASAKI cmsg = (struct cmsghdr*)bsd_args.msg->msg_control; 104884b11cd8SMitsuru IWASAKI cmsg->cmsg_level = bsd_to_linux_sockopt_level(cmsg->cmsg_level); 104984b11cd8SMitsuru IWASAKI } 105084b11cd8SMitsuru IWASAKI 10514b7ef73dSDag-Erling Smørgrav error = copyin(linux_args.msg, &msg, sizeof(msg)); 1052ca26842eSHajimu UMEMOTO if (error) 1053ca26842eSHajimu UMEMOTO return (error); 1054ca26842eSHajimu UMEMOTO if (msg.msg_name && msg.msg_namelen > 2) 1055ca26842eSHajimu UMEMOTO error = linux_sa_put(msg.msg_name); 1056ca26842eSHajimu UMEMOTO return (error); 105740dbba57SAssar Westerlund } 105840dbba57SAssar Westerlund 1059c21dee17SSøren Schmidt struct linux_shutdown_args { 1060c21dee17SSøren Schmidt int s; 1061c21dee17SSøren Schmidt int how; 1062c21dee17SSøren Schmidt }; 1063c21dee17SSøren Schmidt 1064c21dee17SSøren Schmidt static int 1065b40ce416SJulian Elischer linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1066c21dee17SSøren Schmidt { 1067c21dee17SSøren Schmidt struct linux_shutdown_args linux_args; 1068ef04503dSPeter Wemm struct shutdown_args /* { 1069c21dee17SSøren Schmidt int s; 1070c21dee17SSøren Schmidt int how; 1071ef04503dSPeter Wemm } */ bsd_args; 1072c21dee17SSøren Schmidt int error; 1073c21dee17SSøren Schmidt 10743f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 10753f3a4815SMarcel Moolenaar return (error); 10763f3a4815SMarcel Moolenaar 1077c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1078c21dee17SSøren Schmidt bsd_args.how = linux_args.how; 1079b40ce416SJulian Elischer return (shutdown(td, &bsd_args)); 1080c21dee17SSøren Schmidt } 1081c21dee17SSøren Schmidt 1082c21dee17SSøren Schmidt struct linux_setsockopt_args { 1083c21dee17SSøren Schmidt int s; 1084c21dee17SSøren Schmidt int level; 1085c21dee17SSøren Schmidt int optname; 1086c21dee17SSøren Schmidt void *optval; 1087c21dee17SSøren Schmidt int optlen; 1088c21dee17SSøren Schmidt }; 1089c21dee17SSøren Schmidt 1090c21dee17SSøren Schmidt static int 1091b40ce416SJulian Elischer linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1092c21dee17SSøren Schmidt { 1093c21dee17SSøren Schmidt struct linux_setsockopt_args linux_args; 1094ef04503dSPeter Wemm struct setsockopt_args /* { 1095c21dee17SSøren Schmidt int s; 1096c21dee17SSøren Schmidt int level; 1097c21dee17SSøren Schmidt int name; 1098c21dee17SSøren Schmidt caddr_t val; 1099c21dee17SSøren Schmidt int valsize; 1100ef04503dSPeter Wemm } */ bsd_args; 1101c21dee17SSøren Schmidt int error, name; 1102c21dee17SSøren Schmidt 11033f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11043f3a4815SMarcel Moolenaar return (error); 11053f3a4815SMarcel Moolenaar 1106c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1107c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1108c21dee17SSøren Schmidt switch (bsd_args.level) { 1109c21dee17SSøren Schmidt case SOL_SOCKET: 1110c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1111c21dee17SSøren Schmidt break; 1112c21dee17SSøren Schmidt case IPPROTO_IP: 1113c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1114c21dee17SSøren Schmidt break; 1115dad3b88aSMike Smith case IPPROTO_TCP: 1116dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1117dad3b88aSMike Smith name = linux_args.optname; 1118dad3b88aSMike Smith break; 1119c21dee17SSøren Schmidt default: 11203f3a4815SMarcel Moolenaar name = -1; 11213f3a4815SMarcel Moolenaar break; 1122c21dee17SSøren Schmidt } 1123c21dee17SSøren Schmidt if (name == -1) 11243f3a4815SMarcel Moolenaar return (EINVAL); 11253f3a4815SMarcel Moolenaar 1126c21dee17SSøren Schmidt bsd_args.name = name; 1127c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1128c21dee17SSøren Schmidt bsd_args.valsize = linux_args.optlen; 1129b40ce416SJulian Elischer return (setsockopt(td, &bsd_args)); 1130c21dee17SSøren Schmidt } 1131c21dee17SSøren Schmidt 1132c21dee17SSøren Schmidt struct linux_getsockopt_args { 1133c21dee17SSøren Schmidt int s; 1134c21dee17SSøren Schmidt int level; 1135c21dee17SSøren Schmidt int optname; 1136c21dee17SSøren Schmidt void *optval; 1137c21dee17SSøren Schmidt int *optlen; 1138c21dee17SSøren Schmidt }; 1139c21dee17SSøren Schmidt 1140c21dee17SSøren Schmidt static int 1141b40ce416SJulian Elischer linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1142c21dee17SSøren Schmidt { 1143c21dee17SSøren Schmidt struct linux_getsockopt_args linux_args; 1144ef04503dSPeter Wemm struct getsockopt_args /* { 1145c21dee17SSøren Schmidt int s; 1146c21dee17SSøren Schmidt int level; 1147c21dee17SSøren Schmidt int name; 1148c21dee17SSøren Schmidt caddr_t val; 1149c21dee17SSøren Schmidt int *avalsize; 1150ef04503dSPeter Wemm } */ bsd_args; 1151c21dee17SSøren Schmidt int error, name; 1152c21dee17SSøren Schmidt 11533f3a4815SMarcel Moolenaar if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 11543f3a4815SMarcel Moolenaar return (error); 11553f3a4815SMarcel Moolenaar 1156c21dee17SSøren Schmidt bsd_args.s = linux_args.s; 1157c21dee17SSøren Schmidt bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1158c21dee17SSøren Schmidt switch (bsd_args.level) { 1159c21dee17SSøren Schmidt case SOL_SOCKET: 1160c21dee17SSøren Schmidt name = linux_to_bsd_so_sockopt(linux_args.optname); 1161c21dee17SSøren Schmidt break; 1162c21dee17SSøren Schmidt case IPPROTO_IP: 1163c21dee17SSøren Schmidt name = linux_to_bsd_ip_sockopt(linux_args.optname); 1164c21dee17SSøren Schmidt break; 1165dad3b88aSMike Smith case IPPROTO_TCP: 1166dad3b88aSMike Smith /* Linux TCP option values match BSD's */ 1167dad3b88aSMike Smith name = linux_args.optname; 1168dad3b88aSMike Smith break; 1169c21dee17SSøren Schmidt default: 11703f3a4815SMarcel Moolenaar name = -1; 11713f3a4815SMarcel Moolenaar break; 1172c21dee17SSøren Schmidt } 1173c21dee17SSøren Schmidt if (name == -1) 11743f3a4815SMarcel Moolenaar return (EINVAL); 11753f3a4815SMarcel Moolenaar 1176f2477ae1SMike Smith bsd_args.name = name; 1177c21dee17SSøren Schmidt bsd_args.val = linux_args.optval; 1178c21dee17SSøren Schmidt bsd_args.avalsize = linux_args.optlen; 1179b40ce416SJulian Elischer return (getsockopt(td, &bsd_args)); 1180c21dee17SSøren Schmidt } 1181c21dee17SSøren Schmidt 1182c21dee17SSøren Schmidt int 1183b40ce416SJulian Elischer linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1184c21dee17SSøren Schmidt { 11855002a60fSMarcel Moolenaar void *arg = (void *)args->args; 11863f3a4815SMarcel Moolenaar 1187c21dee17SSøren Schmidt switch (args->what) { 1188c21dee17SSøren Schmidt case LINUX_SOCKET: 1189b40ce416SJulian Elischer return (linux_socket(td, arg)); 1190c21dee17SSøren Schmidt case LINUX_BIND: 1191b40ce416SJulian Elischer return (linux_bind(td, arg)); 1192c21dee17SSøren Schmidt case LINUX_CONNECT: 1193b40ce416SJulian Elischer return (linux_connect(td, arg)); 1194c21dee17SSøren Schmidt case LINUX_LISTEN: 1195b40ce416SJulian Elischer return (linux_listen(td, arg)); 1196c21dee17SSøren Schmidt case LINUX_ACCEPT: 1197b40ce416SJulian Elischer return (linux_accept(td, arg)); 1198c21dee17SSøren Schmidt case LINUX_GETSOCKNAME: 1199b40ce416SJulian Elischer return (linux_getsockname(td, arg)); 1200c21dee17SSøren Schmidt case LINUX_GETPEERNAME: 1201b40ce416SJulian Elischer return (linux_getpeername(td, arg)); 1202c21dee17SSøren Schmidt case LINUX_SOCKETPAIR: 1203b40ce416SJulian Elischer return (linux_socketpair(td, arg)); 1204c21dee17SSøren Schmidt case LINUX_SEND: 1205b40ce416SJulian Elischer return (linux_send(td, arg)); 1206c21dee17SSøren Schmidt case LINUX_RECV: 1207b40ce416SJulian Elischer return (linux_recv(td, arg)); 1208c21dee17SSøren Schmidt case LINUX_SENDTO: 1209b40ce416SJulian Elischer return (linux_sendto(td, arg)); 1210c21dee17SSøren Schmidt case LINUX_RECVFROM: 1211b40ce416SJulian Elischer return (linux_recvfrom(td, arg)); 1212c21dee17SSøren Schmidt case LINUX_SHUTDOWN: 1213b40ce416SJulian Elischer return (linux_shutdown(td, arg)); 1214c21dee17SSøren Schmidt case LINUX_SETSOCKOPT: 1215b40ce416SJulian Elischer return (linux_setsockopt(td, arg)); 1216c21dee17SSøren Schmidt case LINUX_GETSOCKOPT: 1217b40ce416SJulian Elischer return (linux_getsockopt(td, arg)); 1218e76bba09SSøren Schmidt case LINUX_SENDMSG: 1219ca26842eSHajimu UMEMOTO return (linux_sendmsg(td, arg)); 1220e76bba09SSøren Schmidt case LINUX_RECVMSG: 1221b40ce416SJulian Elischer return (linux_recvmsg(td, arg)); 1222c21dee17SSøren Schmidt } 12233f3a4815SMarcel Moolenaar 12243f3a4815SMarcel Moolenaar uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 12253f3a4815SMarcel Moolenaar return (ENOSYS); 1226c21dee17SSøren Schmidt } 12275231fb20SDavid E. O'Brien #endif /*!__alpha__*/ 1228