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