1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1995 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * 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_common.h> 74 #include <compat/linux/linux_file.h> 75 #include <compat/linux/linux_mib.h> 76 #include <compat/linux/linux_socket.h> 77 #include <compat/linux/linux_timer.h> 78 #include <compat/linux/linux_util.h> 79 80 static int linux_sendmsg_common(struct thread *, l_int, struct l_msghdr *, 81 l_uint); 82 static int linux_recvmsg_common(struct thread *, l_int, struct l_msghdr *, 83 l_uint, struct msghdr *); 84 static int linux_set_socket_flags(int, int *); 85 86 87 static int 88 linux_to_bsd_sockopt_level(int level) 89 { 90 91 switch (level) { 92 case LINUX_SOL_SOCKET: 93 return (SOL_SOCKET); 94 } 95 return (level); 96 } 97 98 static int 99 bsd_to_linux_sockopt_level(int level) 100 { 101 102 switch (level) { 103 case SOL_SOCKET: 104 return (LINUX_SOL_SOCKET); 105 } 106 return (level); 107 } 108 109 static int 110 linux_to_bsd_ip_sockopt(int opt) 111 { 112 113 switch (opt) { 114 case LINUX_IP_TOS: 115 return (IP_TOS); 116 case LINUX_IP_TTL: 117 return (IP_TTL); 118 case LINUX_IP_OPTIONS: 119 return (IP_OPTIONS); 120 case LINUX_IP_MULTICAST_IF: 121 return (IP_MULTICAST_IF); 122 case LINUX_IP_MULTICAST_TTL: 123 return (IP_MULTICAST_TTL); 124 case LINUX_IP_MULTICAST_LOOP: 125 return (IP_MULTICAST_LOOP); 126 case LINUX_IP_ADD_MEMBERSHIP: 127 return (IP_ADD_MEMBERSHIP); 128 case LINUX_IP_DROP_MEMBERSHIP: 129 return (IP_DROP_MEMBERSHIP); 130 case LINUX_IP_HDRINCL: 131 return (IP_HDRINCL); 132 } 133 return (-1); 134 } 135 136 static int 137 linux_to_bsd_ip6_sockopt(int opt) 138 { 139 140 switch (opt) { 141 case LINUX_IPV6_NEXTHOP: 142 return (IPV6_NEXTHOP); 143 case LINUX_IPV6_UNICAST_HOPS: 144 return (IPV6_UNICAST_HOPS); 145 case LINUX_IPV6_MULTICAST_IF: 146 return (IPV6_MULTICAST_IF); 147 case LINUX_IPV6_MULTICAST_HOPS: 148 return (IPV6_MULTICAST_HOPS); 149 case LINUX_IPV6_MULTICAST_LOOP: 150 return (IPV6_MULTICAST_LOOP); 151 case LINUX_IPV6_ADD_MEMBERSHIP: 152 return (IPV6_JOIN_GROUP); 153 case LINUX_IPV6_DROP_MEMBERSHIP: 154 return (IPV6_LEAVE_GROUP); 155 case LINUX_IPV6_V6ONLY: 156 return (IPV6_V6ONLY); 157 case LINUX_IPV6_DONTFRAG: 158 return (IPV6_DONTFRAG); 159 #if 0 160 case LINUX_IPV6_CHECKSUM: 161 return (IPV6_CHECKSUM); 162 case LINUX_IPV6_RECVPKTINFO: 163 return (IPV6_RECVPKTINFO); 164 case LINUX_IPV6_PKTINFO: 165 return (IPV6_PKTINFO); 166 case LINUX_IPV6_RECVHOPLIMIT: 167 return (IPV6_RECVHOPLIMIT); 168 case LINUX_IPV6_HOPLIMIT: 169 return (IPV6_HOPLIMIT); 170 case LINUX_IPV6_RECVHOPOPTS: 171 return (IPV6_RECVHOPOPTS); 172 case LINUX_IPV6_HOPOPTS: 173 return (IPV6_HOPOPTS); 174 case LINUX_IPV6_RTHDRDSTOPTS: 175 return (IPV6_RTHDRDSTOPTS); 176 case LINUX_IPV6_RECVRTHDR: 177 return (IPV6_RECVRTHDR); 178 case LINUX_IPV6_RTHDR: 179 return (IPV6_RTHDR); 180 case LINUX_IPV6_RECVDSTOPTS: 181 return (IPV6_RECVDSTOPTS); 182 case LINUX_IPV6_DSTOPTS: 183 return (IPV6_DSTOPTS); 184 case LINUX_IPV6_RECVPATHMTU: 185 return (IPV6_RECVPATHMTU); 186 case LINUX_IPV6_PATHMTU: 187 return (IPV6_PATHMTU); 188 #endif 189 } 190 return (-1); 191 } 192 193 static int 194 linux_to_bsd_so_sockopt(int opt) 195 { 196 197 switch (opt) { 198 case LINUX_SO_DEBUG: 199 return (SO_DEBUG); 200 case LINUX_SO_REUSEADDR: 201 return (SO_REUSEADDR); 202 case LINUX_SO_TYPE: 203 return (SO_TYPE); 204 case LINUX_SO_ERROR: 205 return (SO_ERROR); 206 case LINUX_SO_DONTROUTE: 207 return (SO_DONTROUTE); 208 case LINUX_SO_BROADCAST: 209 return (SO_BROADCAST); 210 case LINUX_SO_SNDBUF: 211 return (SO_SNDBUF); 212 case LINUX_SO_RCVBUF: 213 return (SO_RCVBUF); 214 case LINUX_SO_KEEPALIVE: 215 return (SO_KEEPALIVE); 216 case LINUX_SO_OOBINLINE: 217 return (SO_OOBINLINE); 218 case LINUX_SO_LINGER: 219 return (SO_LINGER); 220 case LINUX_SO_PEERCRED: 221 return (LOCAL_PEERCRED); 222 case LINUX_SO_RCVLOWAT: 223 return (SO_RCVLOWAT); 224 case LINUX_SO_SNDLOWAT: 225 return (SO_SNDLOWAT); 226 case LINUX_SO_RCVTIMEO: 227 return (SO_RCVTIMEO); 228 case LINUX_SO_SNDTIMEO: 229 return (SO_SNDTIMEO); 230 case LINUX_SO_TIMESTAMP: 231 return (SO_TIMESTAMP); 232 case LINUX_SO_ACCEPTCONN: 233 return (SO_ACCEPTCONN); 234 } 235 return (-1); 236 } 237 238 static int 239 linux_to_bsd_tcp_sockopt(int opt) 240 { 241 242 switch (opt) { 243 case LINUX_TCP_NODELAY: 244 return (TCP_NODELAY); 245 case LINUX_TCP_MAXSEG: 246 return (TCP_MAXSEG); 247 case LINUX_TCP_CORK: 248 return (TCP_NOPUSH); 249 case LINUX_TCP_KEEPIDLE: 250 return (TCP_KEEPIDLE); 251 case LINUX_TCP_KEEPINTVL: 252 return (TCP_KEEPINTVL); 253 case LINUX_TCP_KEEPCNT: 254 return (TCP_KEEPCNT); 255 case LINUX_TCP_MD5SIG: 256 return (TCP_MD5SIG); 257 } 258 return (-1); 259 } 260 261 static int 262 linux_to_bsd_msg_flags(int flags) 263 { 264 int ret_flags = 0; 265 266 if (flags & LINUX_MSG_OOB) 267 ret_flags |= MSG_OOB; 268 if (flags & LINUX_MSG_PEEK) 269 ret_flags |= MSG_PEEK; 270 if (flags & LINUX_MSG_DONTROUTE) 271 ret_flags |= MSG_DONTROUTE; 272 if (flags & LINUX_MSG_CTRUNC) 273 ret_flags |= MSG_CTRUNC; 274 if (flags & LINUX_MSG_TRUNC) 275 ret_flags |= MSG_TRUNC; 276 if (flags & LINUX_MSG_DONTWAIT) 277 ret_flags |= MSG_DONTWAIT; 278 if (flags & LINUX_MSG_EOR) 279 ret_flags |= MSG_EOR; 280 if (flags & LINUX_MSG_WAITALL) 281 ret_flags |= MSG_WAITALL; 282 if (flags & LINUX_MSG_NOSIGNAL) 283 ret_flags |= MSG_NOSIGNAL; 284 #if 0 /* not handled */ 285 if (flags & LINUX_MSG_PROXY) 286 ; 287 if (flags & LINUX_MSG_FIN) 288 ; 289 if (flags & LINUX_MSG_SYN) 290 ; 291 if (flags & LINUX_MSG_CONFIRM) 292 ; 293 if (flags & LINUX_MSG_RST) 294 ; 295 if (flags & LINUX_MSG_ERRQUEUE) 296 ; 297 #endif 298 return (ret_flags); 299 } 300 301 static int 302 linux_to_bsd_cmsg_type(int cmsg_type) 303 { 304 305 switch (cmsg_type) { 306 case LINUX_SCM_RIGHTS: 307 return (SCM_RIGHTS); 308 case LINUX_SCM_CREDENTIALS: 309 return (SCM_CREDS); 310 } 311 return (-1); 312 } 313 314 static int 315 bsd_to_linux_cmsg_type(int cmsg_type) 316 { 317 318 switch (cmsg_type) { 319 case SCM_RIGHTS: 320 return (LINUX_SCM_RIGHTS); 321 case SCM_CREDS: 322 return (LINUX_SCM_CREDENTIALS); 323 case SCM_TIMESTAMP: 324 return (LINUX_SCM_TIMESTAMP); 325 } 326 return (-1); 327 } 328 329 static int 330 linux_to_bsd_msghdr(struct msghdr *bhdr, const struct l_msghdr *lhdr) 331 { 332 if (lhdr->msg_controllen > INT_MAX) 333 return (ENOBUFS); 334 335 bhdr->msg_name = PTRIN(lhdr->msg_name); 336 bhdr->msg_namelen = lhdr->msg_namelen; 337 bhdr->msg_iov = PTRIN(lhdr->msg_iov); 338 bhdr->msg_iovlen = lhdr->msg_iovlen; 339 bhdr->msg_control = PTRIN(lhdr->msg_control); 340 341 /* 342 * msg_controllen is skipped since BSD and LINUX control messages 343 * are potentially different sizes (e.g. the cred structure used 344 * by SCM_CREDS is different between the two operating system). 345 * 346 * The caller can set it (if necessary) after converting all the 347 * control messages. 348 */ 349 350 bhdr->msg_flags = linux_to_bsd_msg_flags(lhdr->msg_flags); 351 return (0); 352 } 353 354 static int 355 bsd_to_linux_msghdr(const struct msghdr *bhdr, struct l_msghdr *lhdr) 356 { 357 lhdr->msg_name = PTROUT(bhdr->msg_name); 358 lhdr->msg_namelen = bhdr->msg_namelen; 359 lhdr->msg_iov = PTROUT(bhdr->msg_iov); 360 lhdr->msg_iovlen = bhdr->msg_iovlen; 361 lhdr->msg_control = PTROUT(bhdr->msg_control); 362 363 /* 364 * msg_controllen is skipped since BSD and LINUX control messages 365 * are potentially different sizes (e.g. the cred structure used 366 * by SCM_CREDS is different between the two operating system). 367 * 368 * The caller can set it (if necessary) after converting all the 369 * control messages. 370 */ 371 372 /* msg_flags skipped */ 373 return (0); 374 } 375 376 static int 377 linux_set_socket_flags(int lflags, int *flags) 378 { 379 380 if (lflags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK)) 381 return (EINVAL); 382 if (lflags & LINUX_SOCK_NONBLOCK) 383 *flags |= SOCK_NONBLOCK; 384 if (lflags & LINUX_SOCK_CLOEXEC) 385 *flags |= SOCK_CLOEXEC; 386 return (0); 387 } 388 389 static int 390 linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags, 391 struct mbuf *control, enum uio_seg segflg) 392 { 393 struct sockaddr *to; 394 int error, len; 395 396 if (mp->msg_name != NULL) { 397 len = mp->msg_namelen; 398 error = linux_to_bsd_sockaddr(mp->msg_name, &to, &len); 399 if (error != 0) 400 return (error); 401 mp->msg_name = to; 402 } else 403 to = NULL; 404 405 error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control, 406 segflg); 407 408 if (to) 409 free(to, M_SONAME); 410 return (error); 411 } 412 413 /* Return 0 if IP_HDRINCL is set for the given socket. */ 414 static int 415 linux_check_hdrincl(struct thread *td, int s) 416 { 417 int error, optval; 418 socklen_t size_val; 419 420 size_val = sizeof(optval); 421 error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL, 422 &optval, UIO_SYSSPACE, &size_val); 423 if (error != 0) 424 return (error); 425 426 return (optval == 0); 427 } 428 429 /* 430 * Updated sendto() when IP_HDRINCL is set: 431 * tweak endian-dependent fields in the IP packet. 432 */ 433 static int 434 linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args) 435 { 436 /* 437 * linux_ip_copysize defines how many bytes we should copy 438 * from the beginning of the IP packet before we customize it for BSD. 439 * It should include all the fields we modify (ip_len and ip_off). 440 */ 441 #define linux_ip_copysize 8 442 443 struct ip *packet; 444 struct msghdr msg; 445 struct iovec aiov[1]; 446 int error; 447 448 /* Check that the packet isn't too big or too small. */ 449 if (linux_args->len < linux_ip_copysize || 450 linux_args->len > IP_MAXPACKET) 451 return (EINVAL); 452 453 packet = (struct ip *)malloc(linux_args->len, M_LINUX, M_WAITOK); 454 455 /* Make kernel copy of the packet to be sent */ 456 if ((error = copyin(PTRIN(linux_args->msg), packet, 457 linux_args->len))) 458 goto goout; 459 460 /* Convert fields from Linux to BSD raw IP socket format */ 461 packet->ip_len = linux_args->len; 462 packet->ip_off = ntohs(packet->ip_off); 463 464 /* Prepare the msghdr and iovec structures describing the new packet */ 465 msg.msg_name = PTRIN(linux_args->to); 466 msg.msg_namelen = linux_args->tolen; 467 msg.msg_iov = aiov; 468 msg.msg_iovlen = 1; 469 msg.msg_control = NULL; 470 msg.msg_flags = 0; 471 aiov[0].iov_base = (char *)packet; 472 aiov[0].iov_len = linux_args->len; 473 error = linux_sendit(td, linux_args->s, &msg, linux_args->flags, 474 NULL, UIO_SYSSPACE); 475 goout: 476 free(packet, M_LINUX); 477 return (error); 478 } 479 480 int 481 linux_socket(struct thread *td, struct linux_socket_args *args) 482 { 483 int domain, retval_socket, type; 484 485 type = args->type & LINUX_SOCK_TYPE_MASK; 486 if (type < 0 || type > LINUX_SOCK_MAX) 487 return (EINVAL); 488 retval_socket = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK, 489 &type); 490 if (retval_socket != 0) 491 return (retval_socket); 492 domain = linux_to_bsd_domain(args->domain); 493 if (domain == -1) 494 return (EAFNOSUPPORT); 495 496 retval_socket = kern_socket(td, domain, type, args->protocol); 497 if (retval_socket) 498 return (retval_socket); 499 500 if (type == SOCK_RAW 501 && (args->protocol == IPPROTO_RAW || args->protocol == 0) 502 && domain == PF_INET) { 503 /* It's a raw IP socket: set the IP_HDRINCL option. */ 504 int hdrincl; 505 506 hdrincl = 1; 507 /* We ignore any error returned by kern_setsockopt() */ 508 kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL, 509 &hdrincl, UIO_SYSSPACE, sizeof(hdrincl)); 510 } 511 #ifdef INET6 512 /* 513 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by default 514 * and some apps depend on this. So, set V6ONLY to 0 for Linux apps. 515 * For simplicity we do this unconditionally of the net.inet6.ip6.v6only 516 * sysctl value. 517 */ 518 if (domain == PF_INET6) { 519 int v6only; 520 521 v6only = 0; 522 /* We ignore any error returned by setsockopt() */ 523 kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY, 524 &v6only, UIO_SYSSPACE, sizeof(v6only)); 525 } 526 #endif 527 528 return (retval_socket); 529 } 530 531 int 532 linux_bind(struct thread *td, struct linux_bind_args *args) 533 { 534 struct sockaddr *sa; 535 int error; 536 537 error = linux_to_bsd_sockaddr(PTRIN(args->name), &sa, 538 &args->namelen); 539 if (error != 0) 540 return (error); 541 542 error = kern_bindat(td, AT_FDCWD, args->s, sa); 543 free(sa, M_SONAME); 544 545 /* XXX */ 546 if (error == EADDRNOTAVAIL && args->namelen != sizeof(struct sockaddr_in)) 547 return (EINVAL); 548 return (error); 549 } 550 551 int 552 linux_connect(struct thread *td, struct linux_connect_args *args) 553 { 554 struct socket *so; 555 struct sockaddr *sa; 556 struct file *fp; 557 u_int fflag; 558 int error; 559 560 error = linux_to_bsd_sockaddr(PTRIN(args->name), &sa, 561 &args->namelen); 562 if (error != 0) 563 return (error); 564 565 error = kern_connectat(td, AT_FDCWD, args->s, sa); 566 free(sa, M_SONAME); 567 if (error != EISCONN) 568 return (error); 569 570 /* 571 * Linux doesn't return EISCONN the first time it occurs, 572 * when on a non-blocking socket. Instead it returns the 573 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. 574 */ 575 error = getsock_cap(td, args->s, &cap_connect_rights, 576 &fp, &fflag, NULL); 577 if (error != 0) 578 return (error); 579 580 error = EISCONN; 581 so = fp->f_data; 582 if (fflag & FNONBLOCK) { 583 SOCK_LOCK(so); 584 if (so->so_emuldata == 0) 585 error = so->so_error; 586 so->so_emuldata = (void *)1; 587 SOCK_UNLOCK(so); 588 } 589 fdrop(fp, td); 590 591 return (error); 592 } 593 594 int 595 linux_listen(struct thread *td, struct linux_listen_args *args) 596 { 597 598 return (kern_listen(td, args->s, args->backlog)); 599 } 600 601 static int 602 linux_accept_common(struct thread *td, int s, l_uintptr_t addr, 603 l_uintptr_t namelen, int flags) 604 { 605 struct l_sockaddr *lsa; 606 struct sockaddr *sa; 607 struct file *fp; 608 int bflags, len; 609 struct socket *so; 610 int error, error1; 611 612 bflags = 0; 613 error = linux_set_socket_flags(flags, &bflags); 614 if (error != 0) 615 return (error); 616 617 sa = NULL; 618 if (PTRIN(addr) == NULL) { 619 len = 0; 620 error = kern_accept4(td, s, NULL, NULL, bflags, NULL); 621 } else { 622 error = copyin(PTRIN(namelen), &len, sizeof(len)); 623 if (error != 0) 624 return (error); 625 if (len < 0) 626 return (EINVAL); 627 error = kern_accept4(td, s, &sa, &len, bflags, &fp); 628 if (error == 0) 629 fdrop(fp, td); 630 } 631 632 if (error != 0) { 633 /* 634 * XXX. This is wrong, different sockaddr structures 635 * have different sizes. 636 */ 637 if (error == EFAULT && namelen != sizeof(struct sockaddr_in)) 638 { 639 error = EINVAL; 640 goto out; 641 } 642 if (error == EINVAL) { 643 error1 = getsock_cap(td, s, &cap_accept_rights, &fp, NULL, NULL); 644 if (error1 != 0) { 645 error = error1; 646 goto out; 647 } 648 so = fp->f_data; 649 if (so->so_type == SOCK_DGRAM) 650 error = EOPNOTSUPP; 651 fdrop(fp, td); 652 } 653 goto out; 654 } 655 656 if (len != 0 && error == 0) { 657 error = bsd_to_linux_sockaddr(sa, &lsa, len); 658 if (error == 0) 659 error = copyout(lsa, PTRIN(addr), len); 660 free(lsa, M_SONAME); 661 } 662 663 free(sa, M_SONAME); 664 665 out: 666 if (error != 0) { 667 (void)kern_close(td, td->td_retval[0]); 668 td->td_retval[0] = 0; 669 } 670 return (error); 671 } 672 673 int 674 linux_accept(struct thread *td, struct linux_accept_args *args) 675 { 676 677 return (linux_accept_common(td, args->s, args->addr, 678 args->namelen, 0)); 679 } 680 681 int 682 linux_accept4(struct thread *td, struct linux_accept4_args *args) 683 { 684 685 return (linux_accept_common(td, args->s, args->addr, 686 args->namelen, args->flags)); 687 } 688 689 int 690 linux_getsockname(struct thread *td, struct linux_getsockname_args *args) 691 { 692 struct l_sockaddr *lsa; 693 struct sockaddr *sa; 694 int len, error; 695 696 error = copyin(PTRIN(args->namelen), &len, sizeof(len)); 697 if (error != 0) 698 return (error); 699 700 error = kern_getsockname(td, args->s, &sa, &len); 701 if (error != 0) 702 return (error); 703 704 if (len != 0) { 705 error = bsd_to_linux_sockaddr(sa, &lsa, len); 706 if (error == 0) 707 error = copyout(lsa, PTRIN(args->addr), 708 len); 709 free(lsa, M_SONAME); 710 } 711 712 free(sa, M_SONAME); 713 if (error == 0) 714 error = copyout(&len, PTRIN(args->namelen), sizeof(len)); 715 return (error); 716 } 717 718 int 719 linux_getpeername(struct thread *td, struct linux_getpeername_args *args) 720 { 721 struct l_sockaddr *lsa; 722 struct sockaddr *sa; 723 int len, error; 724 725 error = copyin(PTRIN(args->namelen), &len, sizeof(len)); 726 if (error != 0) 727 return (error); 728 if (len < 0) 729 return (EINVAL); 730 731 error = kern_getpeername(td, args->s, &sa, &len); 732 if (error != 0) 733 return (error); 734 735 if (len != 0) { 736 error = bsd_to_linux_sockaddr(sa, &lsa, len); 737 if (error == 0) 738 error = copyout(lsa, PTRIN(args->addr), 739 len); 740 free(lsa, M_SONAME); 741 } 742 743 free(sa, M_SONAME); 744 if (error == 0) 745 error = copyout(&len, PTRIN(args->namelen), sizeof(len)); 746 return (error); 747 } 748 749 int 750 linux_socketpair(struct thread *td, struct linux_socketpair_args *args) 751 { 752 struct socketpair_args /* { 753 int domain; 754 int type; 755 int protocol; 756 int *rsv; 757 } */ bsd_args; 758 int error; 759 760 bsd_args.domain = linux_to_bsd_domain(args->domain); 761 if (bsd_args.domain != PF_LOCAL) 762 return (EAFNOSUPPORT); 763 bsd_args.type = args->type & LINUX_SOCK_TYPE_MASK; 764 if (bsd_args.type < 0 || bsd_args.type > LINUX_SOCK_MAX) 765 return (EINVAL); 766 error = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK, 767 &bsd_args.type); 768 if (error != 0) 769 return (error); 770 if (args->protocol != 0 && args->protocol != PF_UNIX) 771 772 /* 773 * Use of PF_UNIX as protocol argument is not right, 774 * but Linux does it. 775 * Do not map PF_UNIX as its Linux value is identical 776 * to FreeBSD one. 777 */ 778 return (EPROTONOSUPPORT); 779 else 780 bsd_args.protocol = 0; 781 bsd_args.rsv = (int *)PTRIN(args->rsv); 782 return (sys_socketpair(td, &bsd_args)); 783 } 784 785 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 786 struct linux_send_args { 787 register_t s; 788 register_t msg; 789 register_t len; 790 register_t flags; 791 }; 792 793 static int 794 linux_send(struct thread *td, struct linux_send_args *args) 795 { 796 struct sendto_args /* { 797 int s; 798 caddr_t buf; 799 int len; 800 int flags; 801 caddr_t to; 802 int tolen; 803 } */ bsd_args; 804 struct file *fp; 805 int error, fflag; 806 807 bsd_args.s = args->s; 808 bsd_args.buf = (caddr_t)PTRIN(args->msg); 809 bsd_args.len = args->len; 810 bsd_args.flags = args->flags; 811 bsd_args.to = NULL; 812 bsd_args.tolen = 0; 813 error = sys_sendto(td, &bsd_args); 814 if (error == ENOTCONN) { 815 /* 816 * Linux doesn't return ENOTCONN for non-blocking sockets. 817 * Instead it returns the EAGAIN. 818 */ 819 error = getsock_cap(td, args->s, &cap_send_rights, &fp, 820 &fflag, NULL); 821 if (error == 0) { 822 if (fflag & FNONBLOCK) 823 error = EAGAIN; 824 fdrop(fp, td); 825 } 826 } 827 return (error); 828 } 829 830 struct linux_recv_args { 831 register_t s; 832 register_t msg; 833 register_t len; 834 register_t flags; 835 }; 836 837 static int 838 linux_recv(struct thread *td, struct linux_recv_args *args) 839 { 840 struct recvfrom_args /* { 841 int s; 842 caddr_t buf; 843 int len; 844 int flags; 845 struct sockaddr *from; 846 socklen_t fromlenaddr; 847 } */ bsd_args; 848 849 bsd_args.s = args->s; 850 bsd_args.buf = (caddr_t)PTRIN(args->msg); 851 bsd_args.len = args->len; 852 bsd_args.flags = linux_to_bsd_msg_flags(args->flags); 853 bsd_args.from = NULL; 854 bsd_args.fromlenaddr = 0; 855 return (sys_recvfrom(td, &bsd_args)); 856 } 857 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 858 859 int 860 linux_sendto(struct thread *td, struct linux_sendto_args *args) 861 { 862 struct msghdr msg; 863 struct iovec aiov; 864 865 if (linux_check_hdrincl(td, args->s) == 0) 866 /* IP_HDRINCL set, tweak the packet before sending */ 867 return (linux_sendto_hdrincl(td, args)); 868 869 msg.msg_name = PTRIN(args->to); 870 msg.msg_namelen = args->tolen; 871 msg.msg_iov = &aiov; 872 msg.msg_iovlen = 1; 873 msg.msg_control = NULL; 874 msg.msg_flags = 0; 875 aiov.iov_base = PTRIN(args->msg); 876 aiov.iov_len = args->len; 877 return (linux_sendit(td, args->s, &msg, args->flags, NULL, 878 UIO_USERSPACE)); 879 } 880 881 int 882 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) 883 { 884 struct l_sockaddr *lsa; 885 struct sockaddr *sa; 886 struct msghdr msg; 887 struct iovec aiov; 888 int error, fromlen; 889 890 if (PTRIN(args->fromlen) != NULL) { 891 error = copyin(PTRIN(args->fromlen), &fromlen, 892 sizeof(fromlen)); 893 if (error != 0) 894 return (error); 895 if (fromlen < 0) 896 return (EINVAL); 897 sa = malloc(fromlen, M_SONAME, M_WAITOK); 898 } else { 899 fromlen = 0; 900 sa = NULL; 901 } 902 903 msg.msg_name = sa; 904 msg.msg_namelen = fromlen; 905 msg.msg_iov = &aiov; 906 msg.msg_iovlen = 1; 907 aiov.iov_base = PTRIN(args->buf); 908 aiov.iov_len = args->len; 909 msg.msg_control = 0; 910 msg.msg_flags = linux_to_bsd_msg_flags(args->flags); 911 912 error = kern_recvit(td, args->s, &msg, UIO_SYSSPACE, NULL); 913 if (error != 0) 914 goto out; 915 916 if (PTRIN(args->from) != NULL) { 917 error = bsd_to_linux_sockaddr(sa, &lsa, msg.msg_namelen); 918 if (error == 0) 919 error = copyout(lsa, PTRIN(args->from), 920 msg.msg_namelen); 921 free(lsa, M_SONAME); 922 } 923 924 if (error == 0 && PTRIN(args->fromlen) != NULL) 925 error = copyout(&msg.msg_namelen, PTRIN(args->fromlen), 926 sizeof(msg.msg_namelen)); 927 out: 928 free(sa, M_SONAME); 929 return (error); 930 } 931 932 static int 933 linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, 934 l_uint flags) 935 { 936 struct cmsghdr *cmsg; 937 struct mbuf *control; 938 struct msghdr msg; 939 struct l_cmsghdr linux_cmsg; 940 struct l_cmsghdr *ptr_cmsg; 941 struct l_msghdr linux_msg; 942 struct iovec *iov; 943 socklen_t datalen; 944 struct sockaddr *sa; 945 struct socket *so; 946 sa_family_t sa_family; 947 struct file *fp; 948 void *data; 949 l_size_t len; 950 l_size_t clen; 951 int error, fflag; 952 953 error = copyin(msghdr, &linux_msg, sizeof(linux_msg)); 954 if (error != 0) 955 return (error); 956 957 /* 958 * Some Linux applications (ping) define a non-NULL control data 959 * pointer, but a msg_controllen of 0, which is not allowed in the 960 * FreeBSD system call interface. NULL the msg_control pointer in 961 * order to handle this case. This should be checked, but allows the 962 * Linux ping to work. 963 */ 964 if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0) 965 linux_msg.msg_control = PTROUT(NULL); 966 967 error = linux_to_bsd_msghdr(&msg, &linux_msg); 968 if (error != 0) 969 return (error); 970 971 #ifdef COMPAT_LINUX32 972 error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen, 973 &iov, EMSGSIZE); 974 #else 975 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); 976 #endif 977 if (error != 0) 978 return (error); 979 980 control = NULL; 981 982 error = kern_getsockname(td, s, &sa, &datalen); 983 if (error != 0) 984 goto bad; 985 sa_family = sa->sa_family; 986 free(sa, M_SONAME); 987 988 if (flags & LINUX_MSG_OOB) { 989 error = EOPNOTSUPP; 990 if (sa_family == AF_UNIX) 991 goto bad; 992 993 error = getsock_cap(td, s, &cap_send_rights, &fp, 994 &fflag, NULL); 995 if (error != 0) 996 goto bad; 997 so = fp->f_data; 998 if (so->so_type != SOCK_STREAM) 999 error = EOPNOTSUPP; 1000 fdrop(fp, td); 1001 if (error != 0) 1002 goto bad; 1003 } 1004 1005 if (linux_msg.msg_controllen >= sizeof(struct l_cmsghdr)) { 1006 1007 error = ENOBUFS; 1008 control = m_get(M_WAITOK, MT_CONTROL); 1009 MCLGET(control, M_WAITOK); 1010 data = mtod(control, void *); 1011 datalen = 0; 1012 1013 ptr_cmsg = PTRIN(linux_msg.msg_control); 1014 clen = linux_msg.msg_controllen; 1015 do { 1016 error = copyin(ptr_cmsg, &linux_cmsg, 1017 sizeof(struct l_cmsghdr)); 1018 if (error != 0) 1019 goto bad; 1020 1021 error = EINVAL; 1022 if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr) || 1023 linux_cmsg.cmsg_len > clen) 1024 goto bad; 1025 1026 if (datalen + CMSG_HDRSZ > MCLBYTES) 1027 goto bad; 1028 1029 /* 1030 * Now we support only SCM_RIGHTS and SCM_CRED, 1031 * so return EINVAL in any other cmsg_type 1032 */ 1033 cmsg = data; 1034 cmsg->cmsg_type = 1035 linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type); 1036 cmsg->cmsg_level = 1037 linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level); 1038 if (cmsg->cmsg_type == -1 1039 || cmsg->cmsg_level != SOL_SOCKET) 1040 goto bad; 1041 1042 /* 1043 * Some applications (e.g. pulseaudio) attempt to 1044 * send ancillary data even if the underlying protocol 1045 * doesn't support it which is not allowed in the 1046 * FreeBSD system call interface. 1047 */ 1048 if (sa_family != AF_UNIX) 1049 continue; 1050 1051 if (cmsg->cmsg_type == SCM_CREDS) { 1052 len = sizeof(struct cmsgcred); 1053 if (datalen + CMSG_SPACE(len) > MCLBYTES) 1054 goto bad; 1055 1056 /* 1057 * The lower levels will fill in the structure 1058 */ 1059 memset(CMSG_DATA(data), 0, len); 1060 } else { 1061 len = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; 1062 if (datalen + CMSG_SPACE(len) < datalen || 1063 datalen + CMSG_SPACE(len) > MCLBYTES) 1064 goto bad; 1065 1066 error = copyin(LINUX_CMSG_DATA(ptr_cmsg), 1067 CMSG_DATA(data), len); 1068 if (error != 0) 1069 goto bad; 1070 } 1071 1072 cmsg->cmsg_len = CMSG_LEN(len); 1073 data = (char *)data + CMSG_SPACE(len); 1074 datalen += CMSG_SPACE(len); 1075 1076 if (clen <= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len)) 1077 break; 1078 1079 clen -= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len); 1080 ptr_cmsg = (struct l_cmsghdr *)((char *)ptr_cmsg + 1081 LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len)); 1082 } while(clen >= sizeof(struct l_cmsghdr)); 1083 1084 control->m_len = datalen; 1085 if (datalen == 0) { 1086 m_freem(control); 1087 control = NULL; 1088 } 1089 } 1090 1091 msg.msg_iov = iov; 1092 msg.msg_flags = 0; 1093 error = linux_sendit(td, s, &msg, flags, control, UIO_USERSPACE); 1094 control = NULL; 1095 1096 bad: 1097 m_freem(control); 1098 free(iov, M_IOV); 1099 return (error); 1100 } 1101 1102 int 1103 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) 1104 { 1105 1106 return (linux_sendmsg_common(td, args->s, PTRIN(args->msg), 1107 args->flags)); 1108 } 1109 1110 int 1111 linux_sendmmsg(struct thread *td, struct linux_sendmmsg_args *args) 1112 { 1113 struct l_mmsghdr *msg; 1114 l_uint retval; 1115 int error, datagrams; 1116 1117 if (args->vlen > UIO_MAXIOV) 1118 args->vlen = UIO_MAXIOV; 1119 1120 msg = PTRIN(args->msg); 1121 datagrams = 0; 1122 while (datagrams < args->vlen) { 1123 error = linux_sendmsg_common(td, args->s, &msg->msg_hdr, 1124 args->flags); 1125 if (error != 0) 1126 break; 1127 1128 retval = td->td_retval[0]; 1129 error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len)); 1130 if (error != 0) 1131 break; 1132 ++msg; 1133 ++datagrams; 1134 } 1135 if (error == 0) 1136 td->td_retval[0] = datagrams; 1137 return (error); 1138 } 1139 1140 static int 1141 linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, 1142 l_uint flags, struct msghdr *msg) 1143 { 1144 struct cmsghdr *cm; 1145 struct cmsgcred *cmcred; 1146 struct l_cmsghdr *linux_cmsg = NULL; 1147 struct l_ucred linux_ucred; 1148 socklen_t datalen, maxlen, outlen; 1149 struct l_msghdr linux_msg; 1150 struct iovec *iov, *uiov; 1151 struct mbuf *control = NULL; 1152 struct mbuf **controlp; 1153 struct timeval *ftmvl; 1154 struct l_sockaddr *lsa; 1155 struct sockaddr *sa; 1156 l_timeval ltmvl; 1157 caddr_t outbuf; 1158 void *data; 1159 int error, i, fd, fds, *fdp; 1160 1161 error = copyin(msghdr, &linux_msg, sizeof(linux_msg)); 1162 if (error != 0) 1163 return (error); 1164 1165 error = linux_to_bsd_msghdr(msg, &linux_msg); 1166 if (error != 0) 1167 return (error); 1168 1169 #ifdef COMPAT_LINUX32 1170 error = linux32_copyiniov(PTRIN(msg->msg_iov), msg->msg_iovlen, 1171 &iov, EMSGSIZE); 1172 #else 1173 error = copyiniov(msg->msg_iov, msg->msg_iovlen, &iov, EMSGSIZE); 1174 #endif 1175 if (error != 0) 1176 return (error); 1177 1178 if (msg->msg_name) { 1179 sa = malloc(msg->msg_namelen, M_SONAME, M_WAITOK); 1180 msg->msg_name = sa; 1181 } else 1182 sa = NULL; 1183 1184 uiov = msg->msg_iov; 1185 msg->msg_iov = iov; 1186 controlp = (msg->msg_control != NULL) ? &control : NULL; 1187 error = kern_recvit(td, s, msg, UIO_SYSSPACE, controlp); 1188 msg->msg_iov = uiov; 1189 if (error != 0) 1190 goto bad; 1191 1192 if (msg->msg_name) { 1193 msg->msg_name = PTRIN(linux_msg.msg_name); 1194 error = bsd_to_linux_sockaddr(sa, &lsa, msg->msg_namelen); 1195 if (error == 0) 1196 error = copyout(lsa, PTRIN(msg->msg_name), 1197 msg->msg_namelen); 1198 free(lsa, M_SONAME); 1199 if (error != 0) 1200 goto bad; 1201 } 1202 1203 error = bsd_to_linux_msghdr(msg, &linux_msg); 1204 if (error != 0) 1205 goto bad; 1206 1207 maxlen = linux_msg.msg_controllen; 1208 linux_msg.msg_controllen = 0; 1209 if (control) { 1210 linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO); 1211 1212 msg->msg_control = mtod(control, struct cmsghdr *); 1213 msg->msg_controllen = control->m_len; 1214 1215 cm = CMSG_FIRSTHDR(msg); 1216 outbuf = PTRIN(linux_msg.msg_control); 1217 outlen = 0; 1218 while (cm != NULL) { 1219 linux_cmsg->cmsg_type = 1220 bsd_to_linux_cmsg_type(cm->cmsg_type); 1221 linux_cmsg->cmsg_level = 1222 bsd_to_linux_sockopt_level(cm->cmsg_level); 1223 if (linux_cmsg->cmsg_type == -1 || 1224 cm->cmsg_level != SOL_SOCKET) { 1225 error = EINVAL; 1226 goto bad; 1227 } 1228 1229 data = CMSG_DATA(cm); 1230 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1231 1232 switch (cm->cmsg_type) { 1233 case SCM_RIGHTS: 1234 if (flags & LINUX_MSG_CMSG_CLOEXEC) { 1235 fds = datalen / sizeof(int); 1236 fdp = data; 1237 for (i = 0; i < fds; i++) { 1238 fd = *fdp++; 1239 (void)kern_fcntl(td, fd, 1240 F_SETFD, FD_CLOEXEC); 1241 } 1242 } 1243 break; 1244 1245 case SCM_CREDS: 1246 /* 1247 * Currently LOCAL_CREDS is never in 1248 * effect for Linux so no need to worry 1249 * about sockcred 1250 */ 1251 if (datalen != sizeof(*cmcred)) { 1252 error = EMSGSIZE; 1253 goto bad; 1254 } 1255 cmcred = (struct cmsgcred *)data; 1256 bzero(&linux_ucred, sizeof(linux_ucred)); 1257 linux_ucred.pid = cmcred->cmcred_pid; 1258 linux_ucred.uid = cmcred->cmcred_uid; 1259 linux_ucred.gid = cmcred->cmcred_gid; 1260 data = &linux_ucred; 1261 datalen = sizeof(linux_ucred); 1262 break; 1263 1264 case SCM_TIMESTAMP: 1265 if (datalen != sizeof(struct timeval)) { 1266 error = EMSGSIZE; 1267 goto bad; 1268 } 1269 ftmvl = (struct timeval *)data; 1270 ltmvl.tv_sec = ftmvl->tv_sec; 1271 ltmvl.tv_usec = ftmvl->tv_usec; 1272 data = <mvl; 1273 datalen = sizeof(ltmvl); 1274 break; 1275 } 1276 1277 if (outlen + LINUX_CMSG_LEN(datalen) > maxlen) { 1278 if (outlen == 0) { 1279 error = EMSGSIZE; 1280 goto bad; 1281 } else { 1282 linux_msg.msg_flags |= LINUX_MSG_CTRUNC; 1283 m_dispose_extcontrolm(control); 1284 goto out; 1285 } 1286 } 1287 1288 linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); 1289 1290 error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); 1291 if (error != 0) 1292 goto bad; 1293 outbuf += L_CMSG_HDRSZ; 1294 1295 error = copyout(data, outbuf, datalen); 1296 if (error != 0) 1297 goto bad; 1298 1299 outbuf += LINUX_CMSG_ALIGN(datalen); 1300 outlen += LINUX_CMSG_LEN(datalen); 1301 1302 cm = CMSG_NXTHDR(msg, cm); 1303 } 1304 linux_msg.msg_controllen = outlen; 1305 } 1306 1307 out: 1308 error = copyout(&linux_msg, msghdr, sizeof(linux_msg)); 1309 1310 bad: 1311 if (control != NULL) { 1312 if (error != 0) 1313 m_dispose_extcontrolm(control); 1314 m_freem(control); 1315 } 1316 free(iov, M_IOV); 1317 free(linux_cmsg, M_LINUX); 1318 free(sa, M_SONAME); 1319 1320 return (error); 1321 } 1322 1323 int 1324 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) 1325 { 1326 struct msghdr bsd_msg; 1327 1328 return (linux_recvmsg_common(td, args->s, PTRIN(args->msg), 1329 args->flags, &bsd_msg)); 1330 } 1331 1332 int 1333 linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args) 1334 { 1335 struct l_mmsghdr *msg; 1336 struct msghdr bsd_msg; 1337 struct l_timespec lts; 1338 struct timespec ts, tts; 1339 l_uint retval; 1340 int error, datagrams; 1341 1342 if (args->timeout) { 1343 error = copyin(args->timeout, <s, sizeof(struct l_timespec)); 1344 if (error != 0) 1345 return (error); 1346 error = linux_to_native_timespec(&ts, <s); 1347 if (error != 0) 1348 return (error); 1349 getnanotime(&tts); 1350 timespecadd(&tts, &ts, &tts); 1351 } 1352 1353 msg = PTRIN(args->msg); 1354 datagrams = 0; 1355 while (datagrams < args->vlen) { 1356 error = linux_recvmsg_common(td, args->s, &msg->msg_hdr, 1357 args->flags & ~LINUX_MSG_WAITFORONE, &bsd_msg); 1358 if (error != 0) 1359 break; 1360 1361 retval = td->td_retval[0]; 1362 error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len)); 1363 if (error != 0) 1364 break; 1365 ++msg; 1366 ++datagrams; 1367 1368 /* 1369 * MSG_WAITFORONE turns on MSG_DONTWAIT after one packet. 1370 */ 1371 if (args->flags & LINUX_MSG_WAITFORONE) 1372 args->flags |= LINUX_MSG_DONTWAIT; 1373 1374 /* 1375 * See BUGS section of recvmmsg(2). 1376 */ 1377 if (args->timeout) { 1378 getnanotime(&ts); 1379 timespecsub(&ts, &tts, &ts); 1380 if (!timespecisset(&ts) || ts.tv_sec > 0) 1381 break; 1382 } 1383 /* Out of band data, return right away. */ 1384 if (bsd_msg.msg_flags & MSG_OOB) 1385 break; 1386 } 1387 if (error == 0) 1388 td->td_retval[0] = datagrams; 1389 return (error); 1390 } 1391 1392 int 1393 linux_shutdown(struct thread *td, struct linux_shutdown_args *args) 1394 { 1395 1396 return (kern_shutdown(td, args->s, args->how)); 1397 } 1398 1399 int 1400 linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) 1401 { 1402 l_timeval linux_tv; 1403 struct sockaddr *sa; 1404 struct timeval tv; 1405 socklen_t len; 1406 int error, level, name; 1407 1408 level = linux_to_bsd_sockopt_level(args->level); 1409 switch (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 != 0) 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, level, 1423 name, &tv, UIO_SYSSPACE, sizeof(tv))); 1424 /* NOTREACHED */ 1425 default: 1426 break; 1427 } 1428 break; 1429 case IPPROTO_IP: 1430 if (args->optname == LINUX_IP_RECVERR && 1431 linux_ignore_ip_recverr) { 1432 /* 1433 * XXX: This is a hack to unbreak DNS resolution 1434 * with glibc 2.30 and above. 1435 */ 1436 return (0); 1437 } 1438 name = linux_to_bsd_ip_sockopt(args->optname); 1439 break; 1440 case IPPROTO_IPV6: 1441 name = linux_to_bsd_ip6_sockopt(args->optname); 1442 break; 1443 case IPPROTO_TCP: 1444 name = linux_to_bsd_tcp_sockopt(args->optname); 1445 break; 1446 default: 1447 name = -1; 1448 break; 1449 } 1450 if (name == -1) 1451 return (ENOPROTOOPT); 1452 1453 1454 if (name == IPV6_NEXTHOP) { 1455 len = args->optlen; 1456 error = linux_to_bsd_sockaddr(PTRIN(args->optval), &sa, &len); 1457 if (error != 0) 1458 return (error); 1459 1460 error = kern_setsockopt(td, args->s, level, 1461 name, sa, UIO_SYSSPACE, len); 1462 free(sa, M_SONAME); 1463 } else { 1464 error = kern_setsockopt(td, args->s, level, 1465 name, PTRIN(args->optval), UIO_USERSPACE, args->optlen); 1466 } 1467 1468 return (error); 1469 } 1470 1471 int 1472 linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) 1473 { 1474 l_timeval linux_tv; 1475 struct timeval tv; 1476 socklen_t tv_len, xulen, len; 1477 struct l_sockaddr *lsa; 1478 struct sockaddr *sa; 1479 struct xucred xu; 1480 struct l_ucred lxu; 1481 int error, level, name, newval; 1482 1483 level = linux_to_bsd_sockopt_level(args->level); 1484 switch (level) { 1485 case SOL_SOCKET: 1486 name = linux_to_bsd_so_sockopt(args->optname); 1487 switch (name) { 1488 case SO_RCVTIMEO: 1489 /* FALLTHROUGH */ 1490 case SO_SNDTIMEO: 1491 tv_len = sizeof(tv); 1492 error = kern_getsockopt(td, args->s, level, 1493 name, &tv, UIO_SYSSPACE, &tv_len); 1494 if (error != 0) 1495 return (error); 1496 linux_tv.tv_sec = tv.tv_sec; 1497 linux_tv.tv_usec = tv.tv_usec; 1498 return (copyout(&linux_tv, PTRIN(args->optval), 1499 sizeof(linux_tv))); 1500 /* NOTREACHED */ 1501 case LOCAL_PEERCRED: 1502 if (args->optlen < sizeof(lxu)) 1503 return (EINVAL); 1504 /* 1505 * LOCAL_PEERCRED is not served at the SOL_SOCKET level, 1506 * but by the Unix socket's level 0. 1507 */ 1508 level = 0; 1509 xulen = sizeof(xu); 1510 error = kern_getsockopt(td, args->s, level, 1511 name, &xu, UIO_SYSSPACE, &xulen); 1512 if (error != 0) 1513 return (error); 1514 lxu.pid = xu.cr_pid; 1515 lxu.uid = xu.cr_uid; 1516 lxu.gid = xu.cr_gid; 1517 return (copyout(&lxu, PTRIN(args->optval), sizeof(lxu))); 1518 /* NOTREACHED */ 1519 case SO_ERROR: 1520 len = sizeof(newval); 1521 error = kern_getsockopt(td, args->s, level, 1522 name, &newval, UIO_SYSSPACE, &len); 1523 if (error != 0) 1524 return (error); 1525 newval = -SV_ABI_ERRNO(td->td_proc, newval); 1526 return (copyout(&newval, PTRIN(args->optval), len)); 1527 /* NOTREACHED */ 1528 default: 1529 break; 1530 } 1531 break; 1532 case IPPROTO_IP: 1533 name = linux_to_bsd_ip_sockopt(args->optname); 1534 break; 1535 case IPPROTO_IPV6: 1536 name = linux_to_bsd_ip6_sockopt(args->optname); 1537 break; 1538 case IPPROTO_TCP: 1539 name = linux_to_bsd_tcp_sockopt(args->optname); 1540 break; 1541 default: 1542 name = -1; 1543 break; 1544 } 1545 if (name == -1) 1546 return (EINVAL); 1547 1548 if (name == IPV6_NEXTHOP) { 1549 error = copyin(PTRIN(args->optlen), &len, sizeof(len)); 1550 if (error != 0) 1551 return (error); 1552 sa = malloc(len, M_SONAME, M_WAITOK); 1553 1554 error = kern_getsockopt(td, args->s, level, 1555 name, sa, UIO_SYSSPACE, &len); 1556 if (error != 0) 1557 goto out; 1558 1559 error = bsd_to_linux_sockaddr(sa, &lsa, len); 1560 if (error == 0) 1561 error = copyout(lsa, PTRIN(args->optval), len); 1562 free(lsa, M_SONAME); 1563 if (error == 0) 1564 error = copyout(&len, PTRIN(args->optlen), 1565 sizeof(len)); 1566 out: 1567 free(sa, M_SONAME); 1568 } else { 1569 if (args->optval) { 1570 error = copyin(PTRIN(args->optlen), &len, sizeof(len)); 1571 if (error != 0) 1572 return (error); 1573 } 1574 error = kern_getsockopt(td, args->s, level, 1575 name, PTRIN(args->optval), UIO_USERSPACE, &len); 1576 if (error == 0) 1577 error = copyout(&len, PTRIN(args->optlen), 1578 sizeof(len)); 1579 } 1580 1581 return (error); 1582 } 1583 1584 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1585 1586 /* Argument list sizes for linux_socketcall */ 1587 static const unsigned char lxs_args_cnt[] = { 1588 0 /* unused*/, 3 /* socket */, 1589 3 /* bind */, 3 /* connect */, 1590 2 /* listen */, 3 /* accept */, 1591 3 /* getsockname */, 3 /* getpeername */, 1592 4 /* socketpair */, 4 /* send */, 1593 4 /* recv */, 6 /* sendto */, 1594 6 /* recvfrom */, 2 /* shutdown */, 1595 5 /* setsockopt */, 5 /* getsockopt */, 1596 3 /* sendmsg */, 3 /* recvmsg */, 1597 4 /* accept4 */, 5 /* recvmmsg */, 1598 4 /* sendmmsg */ 1599 }; 1600 #define LINUX_ARGS_CNT (nitems(lxs_args_cnt) - 1) 1601 #define LINUX_ARG_SIZE(x) (lxs_args_cnt[x] * sizeof(l_ulong)) 1602 1603 int 1604 linux_socketcall(struct thread *td, struct linux_socketcall_args *args) 1605 { 1606 l_ulong a[6]; 1607 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1608 register_t l_args[6]; 1609 #endif 1610 void *arg; 1611 int error; 1612 1613 if (args->what < LINUX_SOCKET || args->what > LINUX_ARGS_CNT) 1614 return (EINVAL); 1615 error = copyin(PTRIN(args->args), a, LINUX_ARG_SIZE(args->what)); 1616 if (error != 0) 1617 return (error); 1618 1619 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1620 for (int i = 0; i < lxs_args_cnt[args->what]; ++i) 1621 l_args[i] = a[i]; 1622 arg = l_args; 1623 #else 1624 arg = a; 1625 #endif 1626 switch (args->what) { 1627 case LINUX_SOCKET: 1628 return (linux_socket(td, arg)); 1629 case LINUX_BIND: 1630 return (linux_bind(td, arg)); 1631 case LINUX_CONNECT: 1632 return (linux_connect(td, arg)); 1633 case LINUX_LISTEN: 1634 return (linux_listen(td, arg)); 1635 case LINUX_ACCEPT: 1636 return (linux_accept(td, arg)); 1637 case LINUX_GETSOCKNAME: 1638 return (linux_getsockname(td, arg)); 1639 case LINUX_GETPEERNAME: 1640 return (linux_getpeername(td, arg)); 1641 case LINUX_SOCKETPAIR: 1642 return (linux_socketpair(td, arg)); 1643 case LINUX_SEND: 1644 return (linux_send(td, arg)); 1645 case LINUX_RECV: 1646 return (linux_recv(td, arg)); 1647 case LINUX_SENDTO: 1648 return (linux_sendto(td, arg)); 1649 case LINUX_RECVFROM: 1650 return (linux_recvfrom(td, arg)); 1651 case LINUX_SHUTDOWN: 1652 return (linux_shutdown(td, arg)); 1653 case LINUX_SETSOCKOPT: 1654 return (linux_setsockopt(td, arg)); 1655 case LINUX_GETSOCKOPT: 1656 return (linux_getsockopt(td, arg)); 1657 case LINUX_SENDMSG: 1658 return (linux_sendmsg(td, arg)); 1659 case LINUX_RECVMSG: 1660 return (linux_recvmsg(td, arg)); 1661 case LINUX_ACCEPT4: 1662 return (linux_accept4(td, arg)); 1663 case LINUX_RECVMMSG: 1664 return (linux_recvmmsg(td, arg)); 1665 case LINUX_SENDMMSG: 1666 return (linux_sendmmsg(td, arg)); 1667 } 1668 1669 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); 1670 return (ENOSYS); 1671 } 1672 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1673