1 /*- 2 * Copyright (c) 1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 /* XXX we use functions that might not exist. */ 32 #include "opt_compat.h" 33 #include "opt_inet6.h" 34 35 #ifndef COMPAT_43 36 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/proc.h> 41 #include <sys/systm.h> 42 #include <sys/sysproto.h> 43 #include <sys/fcntl.h> 44 #include <sys/file.h> 45 #include <sys/limits.h> 46 #include <sys/malloc.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/syscallsubr.h> 50 #include <sys/uio.h> 51 #include <sys/syslog.h> 52 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/ip.h> 56 #ifdef INET6 57 #include <netinet/ip6.h> 58 #include <netinet6/ip6_var.h> 59 #endif 60 61 #include <machine/../linux/linux.h> 62 #include <machine/../linux/linux_proto.h> 63 #include <compat/linux/linux_socket.h> 64 #include <compat/linux/linux_util.h> 65 66 static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *, 67 struct malloc_type *); 68 static int linux_to_bsd_domain(int); 69 70 /* 71 * Reads a linux sockaddr and does any necessary translation. 72 * Linux sockaddrs don't have a length field, only a family. 73 */ 74 static int 75 linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int len) 76 { 77 int osalen = len; 78 79 return (do_sa_get(sap, osa, &osalen, M_SONAME)); 80 } 81 82 /* 83 * Copy the osockaddr structure pointed to by osa to kernel, adjust 84 * family and convert to sockaddr. 85 */ 86 static int 87 do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, 88 struct malloc_type *mtype) 89 { 90 int error=0, bdom; 91 struct sockaddr *sa; 92 struct osockaddr *kosa; 93 int alloclen; 94 #ifdef INET6 95 int oldv6size; 96 struct sockaddr_in6 *sin6; 97 #endif 98 99 if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) 100 return (EINVAL); 101 102 alloclen = *osalen; 103 #ifdef INET6 104 oldv6size = 0; 105 /* 106 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 107 * if it's a v4-mapped address, so reserve the proper space 108 * for it. 109 */ 110 if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { 111 alloclen = sizeof (struct sockaddr_in6); 112 oldv6size = 1; 113 } 114 #endif 115 116 MALLOC(kosa, struct osockaddr *, alloclen, mtype, M_WAITOK); 117 118 if ((error = copyin(osa, kosa, *osalen))) 119 goto out; 120 121 bdom = linux_to_bsd_domain(kosa->sa_family); 122 if (bdom == -1) { 123 error = EINVAL; 124 goto out; 125 } 126 127 #ifdef INET6 128 /* 129 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 130 * which lacks the scope id compared with RFC2553 one. If we detect 131 * the situation, reject the address and write a message to system log. 132 * 133 * Still accept addresses for which the scope id is not used. 134 */ 135 if (oldv6size && bdom == AF_INET6) { 136 sin6 = (struct sockaddr_in6 *)kosa; 137 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 138 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 139 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 140 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 141 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 142 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 143 sin6->sin6_scope_id = 0; 144 } else { 145 log(LOG_DEBUG, 146 "obsolete pre-RFC2553 sockaddr_in6 rejected"); 147 error = EINVAL; 148 goto out; 149 } 150 } else 151 #endif 152 if (bdom == AF_INET) 153 alloclen = sizeof(struct sockaddr_in); 154 155 sa = (struct sockaddr *) kosa; 156 sa->sa_family = bdom; 157 sa->sa_len = alloclen; 158 159 *sap = sa; 160 *osalen = alloclen; 161 return (0); 162 163 out: 164 FREE(kosa, mtype); 165 return (error); 166 } 167 168 static int 169 linux_to_bsd_domain(int domain) 170 { 171 172 switch (domain) { 173 case LINUX_AF_UNSPEC: 174 return (AF_UNSPEC); 175 case LINUX_AF_UNIX: 176 return (AF_LOCAL); 177 case LINUX_AF_INET: 178 return (AF_INET); 179 case LINUX_AF_INET6: 180 return (AF_INET6); 181 case LINUX_AF_AX25: 182 return (AF_CCITT); 183 case LINUX_AF_IPX: 184 return (AF_IPX); 185 case LINUX_AF_APPLETALK: 186 return (AF_APPLETALK); 187 } 188 return (-1); 189 } 190 191 #ifndef __alpha__ 192 static int 193 bsd_to_linux_domain(int domain) 194 { 195 196 switch (domain) { 197 case AF_UNSPEC: 198 return (LINUX_AF_UNSPEC); 199 case AF_LOCAL: 200 return (LINUX_AF_UNIX); 201 case AF_INET: 202 return (LINUX_AF_INET); 203 case AF_INET6: 204 return (LINUX_AF_INET6); 205 case AF_CCITT: 206 return (LINUX_AF_AX25); 207 case AF_IPX: 208 return (LINUX_AF_IPX); 209 case AF_APPLETALK: 210 return (LINUX_AF_APPLETALK); 211 } 212 return (-1); 213 } 214 215 static int 216 linux_to_bsd_sockopt_level(int level) 217 { 218 219 switch (level) { 220 case LINUX_SOL_SOCKET: 221 return (SOL_SOCKET); 222 } 223 return (level); 224 } 225 226 static int 227 linux_to_bsd_ip_sockopt(int opt) 228 { 229 230 switch (opt) { 231 case LINUX_IP_TOS: 232 return (IP_TOS); 233 case LINUX_IP_TTL: 234 return (IP_TTL); 235 case LINUX_IP_OPTIONS: 236 return (IP_OPTIONS); 237 case LINUX_IP_MULTICAST_IF: 238 return (IP_MULTICAST_IF); 239 case LINUX_IP_MULTICAST_TTL: 240 return (IP_MULTICAST_TTL); 241 case LINUX_IP_MULTICAST_LOOP: 242 return (IP_MULTICAST_LOOP); 243 case LINUX_IP_ADD_MEMBERSHIP: 244 return (IP_ADD_MEMBERSHIP); 245 case LINUX_IP_DROP_MEMBERSHIP: 246 return (IP_DROP_MEMBERSHIP); 247 case LINUX_IP_HDRINCL: 248 return (IP_HDRINCL); 249 } 250 return (-1); 251 } 252 253 static int 254 linux_to_bsd_so_sockopt(int opt) 255 { 256 257 switch (opt) { 258 case LINUX_SO_DEBUG: 259 return (SO_DEBUG); 260 case LINUX_SO_REUSEADDR: 261 return (SO_REUSEADDR); 262 case LINUX_SO_TYPE: 263 return (SO_TYPE); 264 case LINUX_SO_ERROR: 265 return (SO_ERROR); 266 case LINUX_SO_DONTROUTE: 267 return (SO_DONTROUTE); 268 case LINUX_SO_BROADCAST: 269 return (SO_BROADCAST); 270 case LINUX_SO_SNDBUF: 271 return (SO_SNDBUF); 272 case LINUX_SO_RCVBUF: 273 return (SO_RCVBUF); 274 case LINUX_SO_KEEPALIVE: 275 return (SO_KEEPALIVE); 276 case LINUX_SO_OOBINLINE: 277 return (SO_OOBINLINE); 278 case LINUX_SO_LINGER: 279 return (SO_LINGER); 280 } 281 return (-1); 282 } 283 284 static int 285 linux_to_bsd_msg_flags(int flags) 286 { 287 int ret_flags = 0; 288 289 if (flags & LINUX_MSG_OOB) 290 ret_flags |= MSG_OOB; 291 if (flags & LINUX_MSG_PEEK) 292 ret_flags |= MSG_PEEK; 293 if (flags & LINUX_MSG_DONTROUTE) 294 ret_flags |= MSG_DONTROUTE; 295 if (flags & LINUX_MSG_CTRUNC) 296 ret_flags |= MSG_CTRUNC; 297 if (flags & LINUX_MSG_TRUNC) 298 ret_flags |= MSG_TRUNC; 299 if (flags & LINUX_MSG_DONTWAIT) 300 ret_flags |= MSG_DONTWAIT; 301 if (flags & LINUX_MSG_EOR) 302 ret_flags |= MSG_EOR; 303 if (flags & LINUX_MSG_WAITALL) 304 ret_flags |= MSG_WAITALL; 305 #if 0 /* not handled */ 306 if (flags & LINUX_MSG_PROXY) 307 ; 308 if (flags & LINUX_MSG_FIN) 309 ; 310 if (flags & LINUX_MSG_SYN) 311 ; 312 if (flags & LINUX_MSG_CONFIRM) 313 ; 314 if (flags & LINUX_MSG_RST) 315 ; 316 if (flags & LINUX_MSG_ERRQUEUE) 317 ; 318 if (flags & LINUX_MSG_NOSIGNAL) 319 ; 320 #endif 321 return ret_flags; 322 } 323 324 /* 325 * Allocate stackgap and put the converted sockaddr structure 326 * there, address on stackgap returned in sap. 327 */ 328 static int 329 linux_sa_get(caddr_t *sgp, struct sockaddr **sap, 330 const struct osockaddr *osa, int *osalen) 331 { 332 struct sockaddr *sa, *usa; 333 int alloclen, error; 334 335 alloclen = *osalen; 336 error = do_sa_get(&sa, osa, &alloclen, M_TEMP); 337 if (error) 338 return (error); 339 340 usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen); 341 if (!usa) { 342 error = ENOMEM; 343 goto out; 344 } 345 346 if ((error = copyout(sa, usa, alloclen))) 347 goto out; 348 349 *sap = usa; 350 *osalen = alloclen; 351 352 out: 353 FREE(sa, M_TEMP); 354 return (error); 355 } 356 357 static int 358 linux_sa_put(struct osockaddr *osa) 359 { 360 struct osockaddr sa; 361 int error, bdom; 362 363 /* 364 * Only read/write the osockaddr family part, the rest is 365 * not changed. 366 */ 367 error = copyin(osa, &sa, sizeof(sa.sa_family)); 368 if (error) 369 return (error); 370 371 bdom = bsd_to_linux_domain(sa.sa_family); 372 if (bdom == -1) 373 return (EINVAL); 374 375 sa.sa_family = bdom; 376 error = copyout(&sa, osa, sizeof(sa.sa_family)); 377 if (error) 378 return (error); 379 380 return (0); 381 } 382 383 /* Return 0 if IP_HDRINCL is set for the given socket. */ 384 static int 385 linux_check_hdrincl(struct thread *td, caddr_t *sg, int s) 386 { 387 struct getsockopt_args /* { 388 int s; 389 int level; 390 int name; 391 caddr_t val; 392 int *avalsize; 393 } */ bsd_args; 394 int error; 395 caddr_t val, valsize; 396 int size_val = sizeof val; 397 int optval; 398 399 val = stackgap_alloc(sg, sizeof(int)); 400 valsize = stackgap_alloc(sg, sizeof(int)); 401 402 if ((error = copyout(&size_val, valsize, sizeof(size_val)))) 403 return (error); 404 405 bsd_args.s = s; 406 bsd_args.level = IPPROTO_IP; 407 bsd_args.name = IP_HDRINCL; 408 bsd_args.val = val; 409 bsd_args.avalsize = (int *)valsize; 410 if ((error = getsockopt(td, &bsd_args))) 411 return (error); 412 413 if ((error = copyin(val, &optval, sizeof(optval)))) 414 return (error); 415 416 return (optval == 0); 417 } 418 419 /* 420 * Updated sendto() when IP_HDRINCL is set: 421 * tweak endian-dependent fields in the IP packet. 422 */ 423 static int 424 linux_sendto_hdrincl(struct thread *td, caddr_t *sg, struct sendto_args *bsd_args) 425 { 426 /* 427 * linux_ip_copysize defines how many bytes we should copy 428 * from the beginning of the IP packet before we customize it for BSD. 429 * It should include all the fields we modify (ip_len and ip_off) 430 * and be as small as possible to minimize copying overhead. 431 */ 432 #define linux_ip_copysize 8 433 434 struct ip *packet; 435 struct msghdr *msg; 436 struct iovec *iov; 437 438 int error; 439 struct sendmsg_args /* { 440 int s; 441 caddr_t msg; 442 int flags; 443 } */ sendmsg_args; 444 445 /* Check the packet isn't too small before we mess with it */ 446 if (bsd_args->len < linux_ip_copysize) 447 return (EINVAL); 448 449 /* 450 * Tweaking the user buffer in place would be bad manners. 451 * We create a corrected IP header with just the needed length, 452 * then use an iovec to glue it to the rest of the user packet 453 * when calling sendmsg(). 454 */ 455 packet = (struct ip *)stackgap_alloc(sg, linux_ip_copysize); 456 msg = (struct msghdr *)stackgap_alloc(sg, sizeof(*msg)); 457 iov = (struct iovec *)stackgap_alloc(sg, sizeof(*iov)*2); 458 459 /* Make a copy of the beginning of the packet to be sent */ 460 if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) 461 return (error); 462 463 /* Convert fields from Linux to BSD raw IP socket format */ 464 packet->ip_len = bsd_args->len; 465 packet->ip_off = ntohs(packet->ip_off); 466 467 /* Prepare the msghdr and iovec structures describing the new packet */ 468 msg->msg_name = bsd_args->to; 469 msg->msg_namelen = bsd_args->tolen; 470 msg->msg_iov = iov; 471 msg->msg_iovlen = 2; 472 msg->msg_control = NULL; 473 msg->msg_controllen = 0; 474 msg->msg_flags = 0; 475 iov[0].iov_base = (char *)packet; 476 iov[0].iov_len = linux_ip_copysize; 477 iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; 478 iov[1].iov_len = bsd_args->len - linux_ip_copysize; 479 480 sendmsg_args.s = bsd_args->s; 481 sendmsg_args.msg = (caddr_t)msg; 482 sendmsg_args.flags = bsd_args->flags; 483 return (sendmsg(td, &sendmsg_args)); 484 } 485 486 struct linux_socket_args { 487 int domain; 488 int type; 489 int protocol; 490 }; 491 492 static int 493 linux_socket(struct thread *td, struct linux_socket_args *args) 494 { 495 struct linux_socket_args linux_args; 496 struct socket_args /* { 497 int domain; 498 int type; 499 int protocol; 500 } */ bsd_args; 501 struct setsockopt_args /* { 502 int s; 503 int level; 504 int name; 505 caddr_t val; 506 int valsize; 507 } */ bsd_setsockopt_args; 508 int error; 509 int retval_socket; 510 511 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 512 return (error); 513 514 bsd_args.protocol = linux_args.protocol; 515 bsd_args.type = linux_args.type; 516 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 517 if (bsd_args.domain == -1) 518 return (EINVAL); 519 520 retval_socket = socket(td, &bsd_args); 521 if (bsd_args.type == SOCK_RAW 522 && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 523 && bsd_args.domain == AF_INET 524 && retval_socket >= 0) { 525 /* It's a raw IP socket: set the IP_HDRINCL option. */ 526 caddr_t sg; 527 int *hdrincl; 528 529 sg = stackgap_init(); 530 hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); 531 *hdrincl = 1; 532 bsd_setsockopt_args.s = td->td_retval[0]; 533 bsd_setsockopt_args.level = IPPROTO_IP; 534 bsd_setsockopt_args.name = IP_HDRINCL; 535 bsd_setsockopt_args.val = (caddr_t)hdrincl; 536 bsd_setsockopt_args.valsize = sizeof(*hdrincl); 537 /* We ignore any error returned by setsockopt() */ 538 setsockopt(td, &bsd_setsockopt_args); 539 /* Copy back the return value from socket() */ 540 td->td_retval[0] = bsd_setsockopt_args.s; 541 } 542 #ifdef INET6 543 /* 544 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 545 * default and some apps depend on this. So, set V6ONLY to 0 546 * for Linux apps if the sysctl value is set to 1. 547 */ 548 if (bsd_args.domain == PF_INET6 && retval_socket >= 0 549 #ifndef KLD_MODULE 550 /* 551 * XXX: Avoid undefined symbol error with an IPv4 only 552 * kernel. 553 */ 554 && ip6_v6only 555 #endif 556 ) { 557 caddr_t sg; 558 int *v6only; 559 560 sg = stackgap_init(); 561 v6only = (int *)stackgap_alloc(&sg, sizeof(*v6only)); 562 *v6only = 0; 563 bsd_setsockopt_args.s = td->td_retval[0]; 564 bsd_setsockopt_args.level = IPPROTO_IPV6; 565 bsd_setsockopt_args.name = IPV6_V6ONLY; 566 bsd_setsockopt_args.val = (caddr_t)v6only; 567 bsd_setsockopt_args.valsize = sizeof(*v6only); 568 /* We ignore any error returned by setsockopt() */ 569 setsockopt(td, &bsd_setsockopt_args); 570 /* Copy back the return value from socket() */ 571 td->td_retval[0] = bsd_setsockopt_args.s; 572 } 573 #endif 574 575 return (retval_socket); 576 } 577 578 struct linux_bind_args { 579 int s; 580 struct osockaddr *name; 581 int namelen; 582 }; 583 584 static int 585 linux_bind(struct thread *td, struct linux_bind_args *args) 586 { 587 struct linux_bind_args linux_args; 588 struct sockaddr *sa; 589 int error; 590 591 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 592 return (error); 593 594 error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); 595 if (error) 596 return (error); 597 598 return (kern_bind(td, linux_args.s, sa)); 599 } 600 601 struct linux_connect_args { 602 int s; 603 struct osockaddr * name; 604 int namelen; 605 }; 606 int linux_connect(struct thread *, struct linux_connect_args *); 607 #endif /* !__alpha__*/ 608 609 int 610 linux_connect(struct thread *td, struct linux_connect_args *args) 611 { 612 struct linux_connect_args linux_args; 613 struct socket *so; 614 struct sockaddr *sa; 615 u_int fflag; 616 int error; 617 618 #ifdef __alpha__ 619 bcopy(args, &linux_args, sizeof(linux_args)); 620 #else 621 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 622 return (error); 623 #endif /* __alpha__ */ 624 625 error = linux_getsockaddr(&sa, (struct osockaddr *)linux_args.name, 626 linux_args.namelen); 627 if (error) 628 return (error); 629 630 error = kern_connect(td, linux_args.s, sa); 631 if (error != EISCONN) 632 return (error); 633 634 /* 635 * Linux doesn't return EISCONN the first time it occurs, 636 * when on a non-blocking socket. Instead it returns the 637 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 638 */ 639 if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) 640 return(error); 641 error = EISCONN; 642 if (fflag & FNONBLOCK) { 643 if (so->so_emuldata == 0) 644 error = so->so_error; 645 so->so_emuldata = (void *)1; 646 } 647 fputsock(so); 648 return (error); 649 } 650 651 #ifndef __alpha__ 652 653 struct linux_listen_args { 654 int s; 655 int backlog; 656 }; 657 658 static int 659 linux_listen(struct thread *td, struct linux_listen_args *args) 660 { 661 struct linux_listen_args linux_args; 662 struct listen_args /* { 663 int s; 664 int backlog; 665 } */ bsd_args; 666 int error; 667 668 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 669 return (error); 670 671 bsd_args.s = linux_args.s; 672 bsd_args.backlog = linux_args.backlog; 673 return (listen(td, &bsd_args)); 674 } 675 676 struct linux_accept_args { 677 int s; 678 struct osockaddr *addr; 679 int *namelen; 680 }; 681 682 static int 683 linux_accept(struct thread *td, struct linux_accept_args *args) 684 { 685 struct linux_accept_args linux_args; 686 struct accept_args /* { 687 int s; 688 caddr_t name; 689 int *anamelen; 690 } */ bsd_args; 691 struct close_args /* { 692 int fd; 693 } */ c_args; 694 struct fcntl_args /* { 695 int fd; 696 int cmd; 697 long arg; 698 } */ f_args; 699 int error; 700 701 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 702 return (error); 703 704 bsd_args.s = linux_args.s; 705 bsd_args.name = (caddr_t)linux_args.addr; 706 bsd_args.anamelen = linux_args.namelen; 707 error = oaccept(td, &bsd_args); 708 if (error) 709 return (error); 710 if (linux_args.addr) { 711 error = linux_sa_put(linux_args.addr); 712 if (error) { 713 c_args.fd = td->td_retval[0]; 714 (void)close(td, &c_args); 715 return (error); 716 } 717 } 718 719 /* 720 * linux appears not to copy flags from the parent socket to the 721 * accepted one, so we must clear the flags in the new descriptor. 722 * Ignore any errors, because we already have an open fd. 723 */ 724 f_args.fd = td->td_retval[0]; 725 f_args.cmd = F_SETFL; 726 f_args.arg = 0; 727 (void)fcntl(td, &f_args); 728 td->td_retval[0] = f_args.fd; 729 return (0); 730 } 731 732 struct linux_getsockname_args { 733 int s; 734 struct osockaddr *addr; 735 int *namelen; 736 }; 737 738 static int 739 linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 740 { 741 struct linux_getsockname_args linux_args; 742 struct getsockname_args /* { 743 int fdes; 744 caddr_t asa; 745 int *alen; 746 } */ bsd_args; 747 int error; 748 749 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 750 return (error); 751 752 bsd_args.fdes = linux_args.s; 753 bsd_args.asa = (caddr_t) linux_args.addr; 754 bsd_args.alen = linux_args.namelen; 755 error = ogetsockname(td, &bsd_args); 756 if (error) 757 return (error); 758 error = linux_sa_put(linux_args.addr); 759 if (error) 760 return (error); 761 return (0); 762 } 763 764 struct linux_getpeername_args { 765 int s; 766 struct osockaddr *addr; 767 int *namelen; 768 }; 769 770 static int 771 linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 772 { 773 struct linux_getpeername_args linux_args; 774 struct ogetpeername_args /* { 775 int fdes; 776 caddr_t asa; 777 int *alen; 778 } */ bsd_args; 779 int error; 780 781 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 782 return (error); 783 784 bsd_args.fdes = linux_args.s; 785 bsd_args.asa = (caddr_t) linux_args.addr; 786 bsd_args.alen = linux_args.namelen; 787 error = ogetpeername(td, &bsd_args); 788 if (error) 789 return (error); 790 error = linux_sa_put(linux_args.addr); 791 if (error) 792 return (error); 793 return (0); 794 } 795 796 struct linux_socketpair_args { 797 int domain; 798 int type; 799 int protocol; 800 int *rsv; 801 }; 802 803 static int 804 linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 805 { 806 struct linux_socketpair_args linux_args; 807 struct socketpair_args /* { 808 int domain; 809 int type; 810 int protocol; 811 int *rsv; 812 } */ bsd_args; 813 int error; 814 815 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 816 return (error); 817 818 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 819 if (bsd_args.domain == -1) 820 return (EINVAL); 821 822 bsd_args.type = linux_args.type; 823 bsd_args.protocol = linux_args.protocol; 824 bsd_args.rsv = linux_args.rsv; 825 return (socketpair(td, &bsd_args)); 826 } 827 828 struct linux_send_args { 829 int s; 830 void *msg; 831 int len; 832 int flags; 833 }; 834 835 static int 836 linux_send(struct thread *td, struct linux_send_args *args) 837 { 838 struct linux_send_args linux_args; 839 struct osend_args /* { 840 int s; 841 caddr_t buf; 842 int len; 843 int flags; 844 } */ bsd_args; 845 int error; 846 847 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 848 return (error); 849 850 bsd_args.s = linux_args.s; 851 bsd_args.buf = linux_args.msg; 852 bsd_args.len = linux_args.len; 853 bsd_args.flags = linux_args.flags; 854 return (osend(td, &bsd_args)); 855 } 856 857 struct linux_recv_args { 858 int s; 859 void *msg; 860 int len; 861 int flags; 862 }; 863 864 static int 865 linux_recv(struct thread *td, struct linux_recv_args *args) 866 { 867 struct linux_recv_args linux_args; 868 struct orecv_args /* { 869 int s; 870 caddr_t buf; 871 int len; 872 int flags; 873 } */ bsd_args; 874 int error; 875 876 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 877 return (error); 878 879 bsd_args.s = linux_args.s; 880 bsd_args.buf = linux_args.msg; 881 bsd_args.len = linux_args.len; 882 bsd_args.flags = linux_args.flags; 883 return (orecv(td, &bsd_args)); 884 } 885 886 struct linux_sendto_args { 887 int s; 888 void *msg; 889 int len; 890 int flags; 891 caddr_t to; 892 int tolen; 893 }; 894 895 static int 896 linux_sendto(struct thread *td, struct linux_sendto_args *args) 897 { 898 struct linux_sendto_args linux_args; 899 struct sendto_args /* { 900 int s; 901 caddr_t buf; 902 size_t len; 903 int flags; 904 caddr_t to; 905 int tolen; 906 } */ bsd_args; 907 caddr_t sg = stackgap_init(); 908 struct sockaddr *to; 909 int tolen, error; 910 911 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 912 return (error); 913 914 tolen = linux_args.tolen; 915 if (linux_args.to) { 916 error = linux_sa_get(&sg, &to, 917 (struct osockaddr *) linux_args.to, &tolen); 918 if (error) 919 return (error); 920 } else 921 to = NULL; 922 923 bsd_args.s = linux_args.s; 924 bsd_args.buf = linux_args.msg; 925 bsd_args.len = linux_args.len; 926 bsd_args.flags = linux_args.flags; 927 bsd_args.to = (caddr_t) to; 928 bsd_args.tolen = (unsigned int) tolen; 929 930 if (linux_check_hdrincl(td, &sg, linux_args.s) == 0) 931 /* IP_HDRINCL set, tweak the packet before sending */ 932 return (linux_sendto_hdrincl(td, &sg, &bsd_args)); 933 934 return (sendto(td, &bsd_args)); 935 } 936 937 struct linux_recvfrom_args { 938 int s; 939 void *buf; 940 int len; 941 int flags; 942 caddr_t from; 943 int *fromlen; 944 }; 945 946 static int 947 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 948 { 949 struct linux_recvfrom_args linux_args; 950 struct recvfrom_args /* { 951 int s; 952 caddr_t buf; 953 size_t len; 954 int flags; 955 caddr_t from; 956 int *fromlenaddr; 957 } */ bsd_args; 958 int error; 959 960 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 961 return (error); 962 963 bsd_args.s = linux_args.s; 964 bsd_args.buf = linux_args.buf; 965 bsd_args.len = linux_args.len; 966 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 967 bsd_args.from = linux_args.from; 968 bsd_args.fromlenaddr = linux_args.fromlen; 969 error = orecvfrom(td, &bsd_args); 970 if (error) 971 return (error); 972 if (linux_args.from) { 973 error = linux_sa_put((struct osockaddr *) linux_args.from); 974 if (error) 975 return (error); 976 } 977 return (0); 978 } 979 980 struct linux_sendmsg_args { 981 int s; 982 const struct msghdr *msg; 983 int flags; 984 }; 985 986 static int 987 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 988 { 989 struct linux_sendmsg_args linux_args; 990 struct sendmsg_args /* { 991 int s; 992 const struct msghdr *msg; 993 int flags; 994 } */ bsd_args; 995 struct msghdr msg; 996 struct msghdr *nmsg = NULL; 997 int error; 998 int level; 999 caddr_t control; 1000 1001 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1002 return (error); 1003 1004 error = copyin(linux_args.msg, &msg, sizeof(msg)); 1005 if (error) 1006 return (error); 1007 1008 if (msg.msg_name) { 1009 struct sockaddr *sa; 1010 caddr_t sg = stackgap_init(); 1011 1012 nmsg = (struct msghdr *) stackgap_alloc(&sg, 1013 sizeof(struct msghdr)); 1014 if (!nmsg) 1015 return (ENOMEM); 1016 1017 error = linux_sa_get(&sg, &sa, 1018 (struct osockaddr *) msg.msg_name, &msg.msg_namelen); 1019 if (error) 1020 return (error); 1021 1022 msg.msg_name = (struct sockaddr *) sa; 1023 error = copyout(&msg, nmsg, sizeof(struct msghdr)); 1024 if (error) 1025 return (error); 1026 } 1027 1028 error = copyin(&linux_args.msg->msg_control, &control, 1029 sizeof(caddr_t)); 1030 if (error) 1031 return (error); 1032 1033 if (control == NULL) 1034 goto done; 1035 1036 error = copyin(&((struct cmsghdr*)control)->cmsg_level, &level, 1037 sizeof(int)); 1038 if (error) 1039 return (error); 1040 1041 if (level == 1) { 1042 /* 1043 * Linux thinks that SOL_SOCKET is 1; we know 1044 * that it's really 0xffff, of course. 1045 */ 1046 level = SOL_SOCKET; 1047 error = copyout(&level, 1048 &((struct cmsghdr *)control)->cmsg_level, sizeof(int)); 1049 if (error) 1050 return (error); 1051 } 1052 done: 1053 bsd_args.s = linux_args.s; 1054 bsd_args.msg = (caddr_t)nmsg; 1055 bsd_args.flags = linux_args.flags; 1056 return (sendmsg(td, &bsd_args)); 1057 } 1058 1059 struct linux_recvmsg_args { 1060 int s; 1061 struct msghdr *msg; 1062 int flags; 1063 }; 1064 1065 static int 1066 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 1067 { 1068 struct linux_recvmsg_args linux_args; 1069 struct recvmsg_args /* { 1070 int s; 1071 struct msghdr *msg; 1072 int flags; 1073 } */ bsd_args; 1074 struct msghdr msg; 1075 int error; 1076 1077 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1078 return (error); 1079 1080 bsd_args.s = linux_args.s; 1081 bsd_args.msg = linux_args.msg; 1082 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 1083 error = recvmsg(td, &bsd_args); 1084 if (error) 1085 return (error); 1086 1087 error = copyin(linux_args.msg, &msg, sizeof(msg)); 1088 if (error) 1089 return (error); 1090 if (msg.msg_name && msg.msg_namelen > 2) 1091 error = linux_sa_put(msg.msg_name); 1092 return (error); 1093 } 1094 1095 struct linux_shutdown_args { 1096 int s; 1097 int how; 1098 }; 1099 1100 static int 1101 linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1102 { 1103 struct linux_shutdown_args linux_args; 1104 struct shutdown_args /* { 1105 int s; 1106 int how; 1107 } */ bsd_args; 1108 int error; 1109 1110 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1111 return (error); 1112 1113 bsd_args.s = linux_args.s; 1114 bsd_args.how = linux_args.how; 1115 return (shutdown(td, &bsd_args)); 1116 } 1117 1118 struct linux_setsockopt_args { 1119 int s; 1120 int level; 1121 int optname; 1122 void *optval; 1123 int optlen; 1124 }; 1125 1126 static int 1127 linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1128 { 1129 struct linux_setsockopt_args linux_args; 1130 struct setsockopt_args /* { 1131 int s; 1132 int level; 1133 int name; 1134 caddr_t val; 1135 int valsize; 1136 } */ bsd_args; 1137 int error, name; 1138 1139 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1140 return (error); 1141 1142 bsd_args.s = linux_args.s; 1143 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1144 switch (bsd_args.level) { 1145 case SOL_SOCKET: 1146 name = linux_to_bsd_so_sockopt(linux_args.optname); 1147 break; 1148 case IPPROTO_IP: 1149 name = linux_to_bsd_ip_sockopt(linux_args.optname); 1150 break; 1151 case IPPROTO_TCP: 1152 /* Linux TCP option values match BSD's */ 1153 name = linux_args.optname; 1154 break; 1155 default: 1156 name = -1; 1157 break; 1158 } 1159 if (name == -1) 1160 return (EINVAL); 1161 1162 bsd_args.name = name; 1163 bsd_args.val = linux_args.optval; 1164 bsd_args.valsize = linux_args.optlen; 1165 return (setsockopt(td, &bsd_args)); 1166 } 1167 1168 struct linux_getsockopt_args { 1169 int s; 1170 int level; 1171 int optname; 1172 void *optval; 1173 int *optlen; 1174 }; 1175 1176 static int 1177 linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1178 { 1179 struct linux_getsockopt_args linux_args; 1180 struct getsockopt_args /* { 1181 int s; 1182 int level; 1183 int name; 1184 caddr_t val; 1185 int *avalsize; 1186 } */ bsd_args; 1187 int error, name; 1188 1189 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1190 return (error); 1191 1192 bsd_args.s = linux_args.s; 1193 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1194 switch (bsd_args.level) { 1195 case SOL_SOCKET: 1196 name = linux_to_bsd_so_sockopt(linux_args.optname); 1197 break; 1198 case IPPROTO_IP: 1199 name = linux_to_bsd_ip_sockopt(linux_args.optname); 1200 break; 1201 case IPPROTO_TCP: 1202 /* Linux TCP option values match BSD's */ 1203 name = linux_args.optname; 1204 break; 1205 default: 1206 name = -1; 1207 break; 1208 } 1209 if (name == -1) 1210 return (EINVAL); 1211 1212 bsd_args.name = name; 1213 bsd_args.val = linux_args.optval; 1214 bsd_args.avalsize = linux_args.optlen; 1215 return (getsockopt(td, &bsd_args)); 1216 } 1217 1218 int 1219 linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1220 { 1221 void *arg = (void *)args->args; 1222 1223 switch (args->what) { 1224 case LINUX_SOCKET: 1225 return (linux_socket(td, arg)); 1226 case LINUX_BIND: 1227 return (linux_bind(td, arg)); 1228 case LINUX_CONNECT: 1229 return (linux_connect(td, arg)); 1230 case LINUX_LISTEN: 1231 return (linux_listen(td, arg)); 1232 case LINUX_ACCEPT: 1233 return (linux_accept(td, arg)); 1234 case LINUX_GETSOCKNAME: 1235 return (linux_getsockname(td, arg)); 1236 case LINUX_GETPEERNAME: 1237 return (linux_getpeername(td, arg)); 1238 case LINUX_SOCKETPAIR: 1239 return (linux_socketpair(td, arg)); 1240 case LINUX_SEND: 1241 return (linux_send(td, arg)); 1242 case LINUX_RECV: 1243 return (linux_recv(td, arg)); 1244 case LINUX_SENDTO: 1245 return (linux_sendto(td, arg)); 1246 case LINUX_RECVFROM: 1247 return (linux_recvfrom(td, arg)); 1248 case LINUX_SHUTDOWN: 1249 return (linux_shutdown(td, arg)); 1250 case LINUX_SETSOCKOPT: 1251 return (linux_setsockopt(td, arg)); 1252 case LINUX_GETSOCKOPT: 1253 return (linux_getsockopt(td, arg)); 1254 case LINUX_SENDMSG: 1255 return (linux_sendmsg(td, arg)); 1256 case LINUX_RECVMSG: 1257 return (linux_recvmsg(td, arg)); 1258 } 1259 1260 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 1261 return (ENOSYS); 1262 } 1263 #endif /*!__alpha__*/ 1264