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