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