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/lock.h> 48 #include <sys/malloc.h> 49 #include <sys/mutex.h> 50 #include <sys/mbuf.h> 51 #include <sys/socket.h> 52 #include <sys/socketvar.h> 53 #include <sys/syscallsubr.h> 54 #include <sys/uio.h> 55 #include <sys/syslog.h> 56 57 #include <netinet/in.h> 58 #include <netinet/in_systm.h> 59 #include <netinet/ip.h> 60 #ifdef INET6 61 #include <netinet/ip6.h> 62 #include <netinet6/ip6_var.h> 63 #endif 64 65 #include "opt_compat.h" 66 67 #ifdef COMPAT_LINUX32 68 #include <machine/../linux32/linux.h> 69 #include <machine/../linux32/linux32_proto.h> 70 #else 71 #include <machine/../linux/linux.h> 72 #include <machine/../linux/linux_proto.h> 73 #endif 74 #include <compat/linux/linux_socket.h> 75 #include <compat/linux/linux_util.h> 76 77 static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *, 78 struct malloc_type *); 79 static int linux_to_bsd_domain(int); 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"); 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 #ifndef __alpha__ 203 static int 204 bsd_to_linux_domain(int domain) 205 { 206 207 switch (domain) { 208 case AF_UNSPEC: 209 return (LINUX_AF_UNSPEC); 210 case AF_LOCAL: 211 return (LINUX_AF_UNIX); 212 case AF_INET: 213 return (LINUX_AF_INET); 214 case AF_INET6: 215 return (LINUX_AF_INET6); 216 case AF_CCITT: 217 return (LINUX_AF_AX25); 218 case AF_IPX: 219 return (LINUX_AF_IPX); 220 case AF_APPLETALK: 221 return (LINUX_AF_APPLETALK); 222 } 223 return (-1); 224 } 225 226 static int 227 linux_to_bsd_sockopt_level(int level) 228 { 229 230 switch (level) { 231 case LINUX_SOL_SOCKET: 232 return (SOL_SOCKET); 233 } 234 return (level); 235 } 236 237 static int 238 bsd_to_linux_sockopt_level(int level) 239 { 240 241 switch (level) { 242 case SOL_SOCKET: 243 return (LINUX_SOL_SOCKET); 244 } 245 return (level); 246 } 247 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 306 static int 307 linux_to_bsd_msg_flags(int flags) 308 { 309 int ret_flags = 0; 310 311 if (flags & LINUX_MSG_OOB) 312 ret_flags |= MSG_OOB; 313 if (flags & LINUX_MSG_PEEK) 314 ret_flags |= MSG_PEEK; 315 if (flags & LINUX_MSG_DONTROUTE) 316 ret_flags |= MSG_DONTROUTE; 317 if (flags & LINUX_MSG_CTRUNC) 318 ret_flags |= MSG_CTRUNC; 319 if (flags & LINUX_MSG_TRUNC) 320 ret_flags |= MSG_TRUNC; 321 if (flags & LINUX_MSG_DONTWAIT) 322 ret_flags |= MSG_DONTWAIT; 323 if (flags & LINUX_MSG_EOR) 324 ret_flags |= MSG_EOR; 325 if (flags & LINUX_MSG_WAITALL) 326 ret_flags |= MSG_WAITALL; 327 if (flags & LINUX_MSG_NOSIGNAL) 328 ret_flags |= MSG_NOSIGNAL; 329 #if 0 /* not handled */ 330 if (flags & LINUX_MSG_PROXY) 331 ; 332 if (flags & LINUX_MSG_FIN) 333 ; 334 if (flags & LINUX_MSG_SYN) 335 ; 336 if (flags & LINUX_MSG_CONFIRM) 337 ; 338 if (flags & LINUX_MSG_RST) 339 ; 340 if (flags & LINUX_MSG_ERRQUEUE) 341 ; 342 #endif 343 return ret_flags; 344 } 345 346 static int 347 linux_sa_put(struct osockaddr *osa) 348 { 349 struct osockaddr sa; 350 int error, bdom; 351 352 /* 353 * Only read/write the osockaddr family part, the rest is 354 * not changed. 355 */ 356 error = copyin(osa, &sa, sizeof(sa.sa_family)); 357 if (error) 358 return (error); 359 360 bdom = bsd_to_linux_domain(sa.sa_family); 361 if (bdom == -1) 362 return (EINVAL); 363 364 sa.sa_family = bdom; 365 error = copyout(&sa, osa, sizeof(sa.sa_family)); 366 if (error) 367 return (error); 368 369 return (0); 370 } 371 372 static int 373 linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags, 374 enum uio_seg segflg) 375 { 376 struct mbuf *control; 377 struct sockaddr *to; 378 int error; 379 380 if (mp->msg_name != NULL) { 381 error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen); 382 if (error) 383 return (error); 384 mp->msg_name = to; 385 } else 386 to = NULL; 387 388 if (mp->msg_control != NULL) { 389 struct cmsghdr *cmsg; 390 391 if (mp->msg_controllen < sizeof(struct cmsghdr)) { 392 error = EINVAL; 393 goto bad; 394 } 395 error = sockargs(&control, mp->msg_control, 396 mp->msg_controllen, MT_CONTROL); 397 if (error) 398 goto bad; 399 400 cmsg = mtod(control, struct cmsghdr *); 401 cmsg->cmsg_level = linux_to_bsd_sockopt_level(cmsg->cmsg_level); 402 } else 403 control = NULL; 404 405 error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control, 406 segflg); 407 408 bad: 409 if (to) 410 FREE(to, M_SONAME); 411 return (error); 412 } 413 414 /* Return 0 if IP_HDRINCL is set for the given socket. */ 415 static int 416 linux_check_hdrincl(struct thread *td, int s) 417 { 418 int error, optval, size_val; 419 420 size_val = sizeof(optval); 421 error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL, 422 &optval, UIO_SYSSPACE, &size_val); 423 if (error) 424 return (error); 425 426 return (optval == 0); 427 } 428 429 struct linux_sendto_args { 430 int s; 431 l_uintptr_t msg; 432 int len; 433 int flags; 434 l_uintptr_t to; 435 int tolen; 436 }; 437 438 /* 439 * Updated sendto() when IP_HDRINCL is set: 440 * tweak endian-dependent fields in the IP packet. 441 */ 442 static int 443 linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args) 444 { 445 /* 446 * linux_ip_copysize defines how many bytes we should copy 447 * from the beginning of the IP packet before we customize it for BSD. 448 * It should include all the fields we modify (ip_len and ip_off). 449 */ 450 #define linux_ip_copysize 8 451 452 struct ip *packet; 453 struct msghdr msg; 454 struct iovec aiov[1]; 455 int error; 456 457 /* Check that the packet isn't too big or too small. */ 458 if (linux_args->len < linux_ip_copysize || 459 linux_args->len > IP_MAXPACKET) 460 return (EINVAL); 461 462 packet = (struct ip *)malloc(linux_args->len, M_TEMP, M_WAITOK); 463 464 /* Make kernel copy of the packet to be sent */ 465 if ((error = copyin(PTRIN(linux_args->msg), packet, 466 linux_args->len))) 467 goto goout; 468 469 /* Convert fields from Linux to BSD raw IP socket format */ 470 packet->ip_len = linux_args->len; 471 packet->ip_off = ntohs(packet->ip_off); 472 473 /* Prepare the msghdr and iovec structures describing the new packet */ 474 msg.msg_name = PTRIN(linux_args->to); 475 msg.msg_namelen = linux_args->tolen; 476 msg.msg_iov = aiov; 477 msg.msg_iovlen = 1; 478 msg.msg_control = NULL; 479 msg.msg_flags = 0; 480 aiov[0].iov_base = (char *)packet; 481 aiov[0].iov_len = linux_args->len; 482 error = linux_sendit(td, linux_args->s, &msg, linux_args->flags, 483 UIO_SYSSPACE); 484 goout: 485 free(packet, M_TEMP); 486 return (error); 487 } 488 489 struct linux_socket_args { 490 int domain; 491 int type; 492 int protocol; 493 }; 494 495 static int 496 linux_socket(struct thread *td, struct linux_socket_args *args) 497 { 498 struct linux_socket_args linux_args; 499 struct socket_args /* { 500 int domain; 501 int type; 502 int protocol; 503 } */ bsd_args; 504 int error; 505 int retval_socket; 506 507 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 508 return (error); 509 510 bsd_args.protocol = linux_args.protocol; 511 bsd_args.type = linux_args.type; 512 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 513 if (bsd_args.domain == -1) 514 return (EINVAL); 515 516 retval_socket = socket(td, &bsd_args); 517 if (bsd_args.type == SOCK_RAW 518 && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) 519 && bsd_args.domain == AF_INET 520 && retval_socket >= 0) { 521 /* It's a raw IP socket: set the IP_HDRINCL option. */ 522 int hdrincl; 523 524 hdrincl = 1; 525 /* We ignore any error returned by kern_setsockopt() */ 526 kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL, 527 &hdrincl, UIO_SYSSPACE, sizeof(hdrincl)); 528 } 529 #ifdef INET6 530 /* 531 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by 532 * default and some apps depend on this. So, set V6ONLY to 0 533 * for Linux apps if the sysctl value is set to 1. 534 */ 535 if (bsd_args.domain == PF_INET6 && retval_socket >= 0 536 #ifndef KLD_MODULE 537 /* 538 * XXX: Avoid undefined symbol error with an IPv4 only 539 * kernel. 540 */ 541 && ip6_v6only 542 #endif 543 ) { 544 int v6only; 545 546 v6only = 0; 547 /* We ignore any error returned by setsockopt() */ 548 kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY, 549 &v6only, UIO_SYSSPACE, sizeof(v6only)); 550 } 551 #endif 552 553 return (retval_socket); 554 } 555 556 struct linux_bind_args { 557 int s; 558 l_uintptr_t name; 559 int namelen; 560 }; 561 562 static int 563 linux_bind(struct thread *td, struct linux_bind_args *args) 564 { 565 struct linux_bind_args linux_args; 566 struct sockaddr *sa; 567 int error; 568 569 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 570 return (error); 571 572 error = linux_getsockaddr(&sa, PTRIN(linux_args.name), 573 linux_args.namelen); 574 if (error) 575 return (error); 576 577 return (kern_bind(td, linux_args.s, sa)); 578 } 579 580 struct linux_connect_args { 581 int s; 582 l_uintptr_t name; 583 int namelen; 584 }; 585 int linux_connect(struct thread *, struct linux_connect_args *); 586 #endif /* !__alpha__*/ 587 588 int 589 linux_connect(struct thread *td, struct linux_connect_args *args) 590 { 591 struct linux_connect_args linux_args; 592 struct socket *so; 593 struct sockaddr *sa; 594 u_int fflag; 595 int error; 596 597 #ifdef __alpha__ 598 bcopy(args, &linux_args, sizeof(linux_args)); 599 #else 600 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 601 return (error); 602 #endif /* __alpha__ */ 603 604 error = linux_getsockaddr(&sa, 605 (struct osockaddr *)PTRIN(linux_args.name), 606 linux_args.namelen); 607 if (error) 608 return (error); 609 610 error = kern_connect(td, linux_args.s, sa); 611 if (error != EISCONN) 612 return (error); 613 614 /* 615 * Linux doesn't return EISCONN the first time it occurs, 616 * when on a non-blocking socket. Instead it returns the 617 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 618 */ 619 NET_LOCK_GIANT(); 620 error = fgetsock(td, linux_args.s, &so, &fflag); 621 if (error == 0) { 622 error = EISCONN; 623 if (fflag & FNONBLOCK) { 624 SOCK_LOCK(so); 625 if (so->so_emuldata == 0) 626 error = so->so_error; 627 so->so_emuldata = (void *)1; 628 SOCK_UNLOCK(so); 629 } 630 fputsock(so); 631 } 632 NET_UNLOCK_GIANT(); 633 return (error); 634 } 635 636 #ifndef __alpha__ 637 638 struct linux_listen_args { 639 int s; 640 int backlog; 641 }; 642 643 static int 644 linux_listen(struct thread *td, struct linux_listen_args *args) 645 { 646 struct linux_listen_args linux_args; 647 struct listen_args /* { 648 int s; 649 int backlog; 650 } */ bsd_args; 651 int error; 652 653 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 654 return (error); 655 656 bsd_args.s = linux_args.s; 657 bsd_args.backlog = linux_args.backlog; 658 return (listen(td, &bsd_args)); 659 } 660 661 struct linux_accept_args { 662 int s; 663 l_uintptr_t addr; 664 l_uintptr_t namelen; 665 }; 666 667 static int 668 linux_accept(struct thread *td, struct linux_accept_args *args) 669 { 670 struct linux_accept_args linux_args; 671 struct accept_args /* { 672 int s; 673 struct sockaddr * __restrict name; 674 socklen_t * __restrict anamelen; 675 } */ bsd_args; 676 struct close_args /* { 677 int fd; 678 } */ c_args; 679 int error, fd; 680 681 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 682 return (error); 683 684 bsd_args.s = linux_args.s; 685 /* XXX: */ 686 bsd_args.name = (struct sockaddr * __restrict)PTRIN(linux_args.addr); 687 bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */ 688 error = oaccept(td, &bsd_args); 689 if (error) 690 return (error); 691 if (linux_args.addr) { 692 error = linux_sa_put(PTRIN(linux_args.addr)); 693 if (error) { 694 c_args.fd = td->td_retval[0]; 695 (void)close(td, &c_args); 696 return (error); 697 } 698 } 699 700 /* 701 * linux appears not to copy flags from the parent socket to the 702 * accepted one, so we must clear the flags in the new descriptor. 703 * Ignore any errors, because we already have an open fd. 704 */ 705 fd = td->td_retval[0]; 706 (void)kern_fcntl(td, fd, F_SETFL, 0); 707 td->td_retval[0] = fd; 708 return (0); 709 } 710 711 struct linux_getsockname_args { 712 int s; 713 l_uintptr_t addr; 714 l_uintptr_t namelen; 715 }; 716 717 static int 718 linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 719 { 720 struct linux_getsockname_args linux_args; 721 struct getsockname_args /* { 722 int fdes; 723 struct sockaddr * __restrict asa; 724 socklen_t * __restrict alen; 725 } */ bsd_args; 726 int error; 727 728 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 729 return (error); 730 731 bsd_args.fdes = linux_args.s; 732 /* XXX: */ 733 bsd_args.asa = (struct sockaddr * __restrict)PTRIN(linux_args.addr); 734 bsd_args.alen = PTRIN(linux_args.namelen); /* XXX */ 735 error = ogetsockname(td, &bsd_args); 736 if (error) 737 return (error); 738 error = linux_sa_put(PTRIN(linux_args.addr)); 739 if (error) 740 return (error); 741 return (0); 742 } 743 744 struct linux_getpeername_args { 745 int s; 746 l_uintptr_t addr; 747 l_uintptr_t namelen; 748 }; 749 750 static int 751 linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 752 { 753 struct linux_getpeername_args linux_args; 754 struct ogetpeername_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)PTRIN(linux_args.addr); 766 bsd_args.alen = (int *)PTRIN(linux_args.namelen); 767 error = ogetpeername(td, &bsd_args); 768 if (error) 769 return (error); 770 error = linux_sa_put(PTRIN(linux_args.addr)); 771 if (error) 772 return (error); 773 return (0); 774 } 775 776 struct linux_socketpair_args { 777 int domain; 778 int type; 779 int protocol; 780 l_uintptr_t rsv; 781 }; 782 783 static int 784 linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 785 { 786 struct linux_socketpair_args linux_args; 787 struct socketpair_args /* { 788 int domain; 789 int type; 790 int protocol; 791 int *rsv; 792 } */ bsd_args; 793 int error; 794 795 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 796 return (error); 797 798 bsd_args.domain = linux_to_bsd_domain(linux_args.domain); 799 if (bsd_args.domain == -1) 800 return (EINVAL); 801 802 bsd_args.type = linux_args.type; 803 bsd_args.protocol = linux_args.protocol; 804 bsd_args.rsv = (int *)PTRIN(linux_args.rsv); 805 return (socketpair(td, &bsd_args)); 806 } 807 808 struct linux_send_args { 809 int s; 810 l_uintptr_t msg; 811 int len; 812 int flags; 813 }; 814 815 static int 816 linux_send(struct thread *td, struct linux_send_args *args) 817 { 818 struct linux_send_args linux_args; 819 struct sendto_args /* { 820 int s; 821 caddr_t buf; 822 int len; 823 int flags; 824 caddr_t to; 825 int tolen; 826 } */ bsd_args; 827 int error; 828 829 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 830 return (error); 831 832 bsd_args.s = linux_args.s; 833 bsd_args.buf = (caddr_t)PTRIN(linux_args.msg); 834 bsd_args.len = linux_args.len; 835 bsd_args.flags = linux_args.flags; 836 bsd_args.to = NULL; 837 bsd_args.tolen = 0; 838 return sendto(td, &bsd_args); 839 } 840 841 struct linux_recv_args { 842 int s; 843 l_uintptr_t msg; 844 int len; 845 int flags; 846 }; 847 848 static int 849 linux_recv(struct thread *td, struct linux_recv_args *args) 850 { 851 struct linux_recv_args linux_args; 852 struct recvfrom_args /* { 853 int s; 854 caddr_t buf; 855 int len; 856 int flags; 857 struct sockaddr *from; 858 socklen_t fromlenaddr; 859 } */ bsd_args; 860 int error; 861 862 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 863 return (error); 864 865 bsd_args.s = linux_args.s; 866 bsd_args.buf = (caddr_t)PTRIN(linux_args.msg); 867 bsd_args.len = linux_args.len; 868 bsd_args.flags = linux_args.flags; 869 bsd_args.from = NULL; 870 bsd_args.fromlenaddr = 0; 871 return (recvfrom(td, &bsd_args)); 872 } 873 874 static int 875 linux_sendto(struct thread *td, struct linux_sendto_args *args) 876 { 877 struct linux_sendto_args linux_args; 878 struct msghdr msg; 879 struct iovec aiov; 880 int error; 881 882 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 883 return (error); 884 885 if (linux_check_hdrincl(td, linux_args.s) == 0) 886 /* IP_HDRINCL set, tweak the packet before sending */ 887 return (linux_sendto_hdrincl(td, &linux_args)); 888 889 msg.msg_name = PTRIN(linux_args.to); 890 msg.msg_namelen = linux_args.tolen; 891 msg.msg_iov = &aiov; 892 msg.msg_iovlen = 1; 893 msg.msg_control = NULL; 894 msg.msg_flags = 0; 895 aiov.iov_base = PTRIN(linux_args.msg); 896 aiov.iov_len = linux_args.len; 897 error = linux_sendit(td, linux_args.s, &msg, linux_args.flags, 898 UIO_USERSPACE); 899 return (error); 900 } 901 902 struct linux_recvfrom_args { 903 int s; 904 l_uintptr_t buf; 905 int len; 906 int flags; 907 l_uintptr_t from; 908 l_uintptr_t fromlen; 909 }; 910 911 static int 912 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 913 { 914 struct linux_recvfrom_args linux_args; 915 struct recvfrom_args /* { 916 int s; 917 caddr_t buf; 918 size_t len; 919 int flags; 920 struct sockaddr * __restrict from; 921 socklen_t * __restrict fromlenaddr; 922 } */ bsd_args; 923 int error; 924 925 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 926 return (error); 927 928 bsd_args.s = linux_args.s; 929 bsd_args.buf = PTRIN(linux_args.buf); 930 bsd_args.len = linux_args.len; 931 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 932 /* XXX: */ 933 bsd_args.from = (struct sockaddr * __restrict)PTRIN(linux_args.from); 934 bsd_args.fromlenaddr = PTRIN(linux_args.fromlen);/* XXX */ 935 error = orecvfrom(td, &bsd_args); 936 if (error) 937 return (error); 938 if (linux_args.from) { 939 error = linux_sa_put((struct osockaddr *) 940 PTRIN(linux_args.from)); 941 if (error) 942 return (error); 943 } 944 return (0); 945 } 946 947 struct linux_sendmsg_args { 948 int s; 949 l_uintptr_t msg; 950 int flags; 951 }; 952 953 static int 954 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 955 { 956 struct linux_sendmsg_args linux_args; 957 struct msghdr msg; 958 struct iovec *iov; 959 int error; 960 961 /* XXXTJR sendmsg is broken on amd64 */ 962 963 error = copyin(args, &linux_args, sizeof(linux_args)); 964 if (error) 965 return (error); 966 error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg)); 967 if (error) 968 return (error); 969 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 970 if (error) 971 return (error); 972 msg.msg_iov = iov; 973 msg.msg_flags = 0; 974 error = linux_sendit(td, linux_args.s, &msg, linux_args.flags, 975 UIO_USERSPACE); 976 free(iov, M_IOV); 977 return (error); 978 } 979 980 struct linux_recvmsg_args { 981 int s; 982 l_uintptr_t msg; 983 int flags; 984 }; 985 986 static int 987 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 988 { 989 struct linux_recvmsg_args linux_args; 990 struct recvmsg_args /* { 991 int s; 992 struct msghdr *msg; 993 int flags; 994 } */ bsd_args; 995 struct msghdr msg; 996 struct cmsghdr *cmsg; 997 int error; 998 999 /* XXXTJR recvmsg is broken on amd64 */ 1000 1001 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1002 return (error); 1003 1004 bsd_args.s = linux_args.s; 1005 bsd_args.msg = PTRIN(linux_args.msg); 1006 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); 1007 error = recvmsg(td, &bsd_args); 1008 if (error) 1009 return (error); 1010 1011 if (bsd_args.msg->msg_control != NULL && 1012 bsd_args.msg->msg_controllen > 0) { 1013 cmsg = (struct cmsghdr*)bsd_args.msg->msg_control; 1014 cmsg->cmsg_level = bsd_to_linux_sockopt_level(cmsg->cmsg_level); 1015 } 1016 1017 error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg)); 1018 if (error) 1019 return (error); 1020 if (msg.msg_name && msg.msg_namelen > 2) 1021 error = linux_sa_put(msg.msg_name); 1022 return (error); 1023 } 1024 1025 struct linux_shutdown_args { 1026 int s; 1027 int how; 1028 }; 1029 1030 static int 1031 linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1032 { 1033 struct linux_shutdown_args linux_args; 1034 struct shutdown_args /* { 1035 int s; 1036 int how; 1037 } */ bsd_args; 1038 int error; 1039 1040 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1041 return (error); 1042 1043 bsd_args.s = linux_args.s; 1044 bsd_args.how = linux_args.how; 1045 return (shutdown(td, &bsd_args)); 1046 } 1047 1048 struct linux_setsockopt_args { 1049 int s; 1050 int level; 1051 int optname; 1052 l_uintptr_t optval; 1053 int optlen; 1054 }; 1055 1056 static int 1057 linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1058 { 1059 struct linux_setsockopt_args linux_args; 1060 struct setsockopt_args /* { 1061 int s; 1062 int level; 1063 int name; 1064 caddr_t val; 1065 int valsize; 1066 } */ bsd_args; 1067 int error, name; 1068 1069 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1070 return (error); 1071 1072 bsd_args.s = linux_args.s; 1073 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1074 switch (bsd_args.level) { 1075 case SOL_SOCKET: 1076 name = linux_to_bsd_so_sockopt(linux_args.optname); 1077 break; 1078 case IPPROTO_IP: 1079 name = linux_to_bsd_ip_sockopt(linux_args.optname); 1080 break; 1081 case IPPROTO_TCP: 1082 /* Linux TCP option values match BSD's */ 1083 name = linux_args.optname; 1084 break; 1085 default: 1086 name = -1; 1087 break; 1088 } 1089 if (name == -1) 1090 return (EINVAL); 1091 1092 bsd_args.name = name; 1093 bsd_args.val = PTRIN(linux_args.optval); 1094 bsd_args.valsize = linux_args.optlen; 1095 return (setsockopt(td, &bsd_args)); 1096 } 1097 1098 struct linux_getsockopt_args { 1099 int s; 1100 int level; 1101 int optname; 1102 l_uintptr_t optval; 1103 l_uintptr_t optlen; 1104 }; 1105 1106 static int 1107 linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1108 { 1109 struct linux_getsockopt_args linux_args; 1110 struct getsockopt_args /* { 1111 int s; 1112 int level; 1113 int name; 1114 caddr_t val; 1115 int *avalsize; 1116 } */ bsd_args; 1117 int error, name; 1118 1119 if ((error = copyin(args, &linux_args, sizeof(linux_args)))) 1120 return (error); 1121 1122 bsd_args.s = linux_args.s; 1123 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); 1124 switch (bsd_args.level) { 1125 case SOL_SOCKET: 1126 name = linux_to_bsd_so_sockopt(linux_args.optname); 1127 break; 1128 case IPPROTO_IP: 1129 name = linux_to_bsd_ip_sockopt(linux_args.optname); 1130 break; 1131 case IPPROTO_TCP: 1132 /* Linux TCP option values match BSD's */ 1133 name = linux_args.optname; 1134 break; 1135 default: 1136 name = -1; 1137 break; 1138 } 1139 if (name == -1) 1140 return (EINVAL); 1141 1142 bsd_args.name = name; 1143 bsd_args.val = PTRIN(linux_args.optval); 1144 bsd_args.avalsize = PTRIN(linux_args.optlen); 1145 return (getsockopt(td, &bsd_args)); 1146 } 1147 1148 int 1149 linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1150 { 1151 void *arg = (void *)(intptr_t)args->args; 1152 1153 switch (args->what) { 1154 case LINUX_SOCKET: 1155 return (linux_socket(td, arg)); 1156 case LINUX_BIND: 1157 return (linux_bind(td, arg)); 1158 case LINUX_CONNECT: 1159 return (linux_connect(td, arg)); 1160 case LINUX_LISTEN: 1161 return (linux_listen(td, arg)); 1162 case LINUX_ACCEPT: 1163 return (linux_accept(td, arg)); 1164 case LINUX_GETSOCKNAME: 1165 return (linux_getsockname(td, arg)); 1166 case LINUX_GETPEERNAME: 1167 return (linux_getpeername(td, arg)); 1168 case LINUX_SOCKETPAIR: 1169 return (linux_socketpair(td, arg)); 1170 case LINUX_SEND: 1171 return (linux_send(td, arg)); 1172 case LINUX_RECV: 1173 return (linux_recv(td, arg)); 1174 case LINUX_SENDTO: 1175 return (linux_sendto(td, arg)); 1176 case LINUX_RECVFROM: 1177 return (linux_recvfrom(td, arg)); 1178 case LINUX_SHUTDOWN: 1179 return (linux_shutdown(td, arg)); 1180 case LINUX_SETSOCKOPT: 1181 return (linux_setsockopt(td, arg)); 1182 case LINUX_GETSOCKOPT: 1183 return (linux_getsockopt(td, arg)); 1184 case LINUX_SENDMSG: 1185 return (linux_sendmsg(td, arg)); 1186 case LINUX_RECVMSG: 1187 return (linux_recvmsg(td, arg)); 1188 } 1189 1190 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 1191 return (ENOSYS); 1192 } 1193 #endif /*!__alpha__*/ 1194