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