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