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