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