1 /* 2 * Copyright (c) 2010 Kip Macy. All rights reserved. 3 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Derived in part from libplebnet's pn_syscall_wrapper.c. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/limits.h> 31 #include <sys/uio.h> 32 #include <sys/proc.h> 33 #include <sys/syscallsubr.h> 34 #include <sys/module.h> 35 #include <sys/param.h> 36 #include <sys/malloc.h> 37 #include <sys/socketvar.h> 38 #include <sys/event.h> 39 #include <sys/kernel.h> 40 #include <sys/refcount.h> 41 #include <sys/sysctl.h> 42 #include <sys/pcpu.h> 43 #include <sys/select.h> 44 #include <sys/poll.h> 45 #include <sys/event.h> 46 #include <sys/file.h> 47 #include <netinet/in.h> 48 #include <netinet/tcp.h> 49 #include <sys/ttycom.h> 50 #include <sys/filio.h> 51 #include <sys/sysproto.h> 52 #include <sys/fcntl.h> 53 #include <net/route.h> 54 55 #include <net/if.h> 56 #include <sys/sockio.h> 57 58 #include <machine/stdarg.h> 59 60 #include "ff_api.h" 61 #include "ff_host_interface.h" 62 63 /* setsockopt/getsockopt define start */ 64 65 #define LINUX_SOL_SOCKET 1 66 67 #define LINUX_SO_DEBUG 1 68 #define LINUX_SO_REUSEADDR 2 69 #define LINUX_SO_ERROR 4 70 #define LINUX_SO_DONTROUTE 5 71 #define LINUX_SO_BROADCAST 6 72 #define LINUX_SO_SNDBUF 7 73 #define LINUX_SO_RCVBUF 8 74 #define LINUX_SO_KEEPALIVE 9 75 #define LINUX_SO_OOBINLINE 10 76 #define LINUX_SO_LINGER 13 77 #define LINUX_SO_REUSEPORT 15 78 #define LINUX_SO_RCVLOWAT 18 79 #define LINUX_SO_SNDLOWAT 19 80 #define LINUX_SO_RCVTIMEO 20 81 #define LINUX_SO_SNDTIMEO 21 82 #define LINUX_SO_ACCEPTCONN 30 83 #define LINUX_SO_PROTOCOL 38 84 85 86 #define LINUX_IP_TOS 1 87 #define LINUX_IP_TTL 2 88 #define LINUX_IP_HDRINCL 3 89 #define LINUX_IP_OPTIONS 4 90 91 #define LINUX_IP_MULTICAST_IF 32 92 #define LINUX_IP_MULTICAST_TTL 33 93 #define LINUX_IP_MULTICAST_LOOP 34 94 #define LINUX_IP_ADD_MEMBERSHIP 35 95 #define LINUX_IP_DROP_MEMBERSHIP 36 96 97 #define LINUX_IPV6_V6ONLY 26 98 #define LINUX_IPV6_RECVPKTINFO 49 99 100 #define LINUX_TCP_NODELAY 1 101 #define LINUX_TCP_MAXSEG 2 102 #define LINUX_TCP_KEEPIDLE 4 103 #define LINUX_TCP_KEEPINTVL 5 104 #define LINUX_TCP_KEEPCNT 6 105 #define LINUX_TCP_INFO 11 106 #define LINUX_TCP_MD5SIG 14 107 108 /* setsockopt/getsockopt define end */ 109 110 111 /* ioctl define start */ 112 113 #define LINUX_TIOCEXCL 0x540C 114 #define LINUX_TIOCNXCL 0x540D 115 #define LINUX_TIOCSCTTY 0x540E 116 #define LINUX_TIOCGPGRP 0x540F 117 #define LINUX_TIOCSPGRP 0x5410 118 #define LINUX_TIOCOUTQ 0x5411 119 #define LINUX_TIOCSTI 0x5412 120 #define LINUX_TIOCGWINSZ 0x5413 121 #define LINUX_TIOCSWINSZ 0x5414 122 #define LINUX_TIOCMGET 0x5415 123 #define LINUX_TIOCMBIS 0x5416 124 #define LINUX_TIOCMBIC 0x5417 125 #define LINUX_TIOCMSET 0x5418 126 127 #define LINUX_FIONREAD 0x541B 128 #define LINUX_TIOCCONS 0x541D 129 #define LINUX_TIOCPKT 0x5420 130 #define LINUX_FIONBIO 0x5421 131 #define LINUX_TIOCNOTTY 0x5422 132 #define LINUX_TIOCSETD 0x5423 133 #define LINUX_TIOCGETD 0x5424 134 #define LINUX_TIOCSBRK 0x5427 135 #define LINUX_TIOCCBRK 0x5428 136 #define LINUX_TIOCGSID 0x5429 137 138 #define LINUX_FIONCLEX 0x5450 139 #define LINUX_FIOCLEX 0x5451 140 #define LINUX_FIOASYNC 0x5452 141 142 #define LINUX_TIOCPKT_DATA 0 143 #define LINUX_TIOCPKT_FLUSHREAD 1 144 #define LINUX_TIOCPKT_FLUSHWRITE 2 145 #define LINUX_TIOCPKT_STOP 4 146 #define LINUX_TIOCPKT_START 8 147 #define LINUX_TIOCPKT_NOSTOP 16 148 #define LINUX_TIOCPKT_DOSTOP 32 149 #define LINUX_TIOCPKT_IOCTL 64 150 151 #define LINUX_SIOCGIFCONF 0x8912 152 #define LINUX_SIOCGIFFLAGS 0x8913 153 #define LINUX_SIOCSIFFLAGS 0x8914 154 #define LINUX_SIOCGIFADDR 0x8915 155 #define LINUX_SIOCSIFADDR 0x8916 156 #define LINUX_SIOCGIFDSTADDR 0x8917 157 #define LINUX_SIOCSIFDSTADDR 0x8918 158 #define LINUX_SIOCGIFBRDADDR 0x8919 159 #define LINUX_SIOCSIFBRDADDR 0x891a 160 #define LINUX_SIOCGIFNETMASK 0x891b 161 #define LINUX_SIOCSIFNETMASK 0x891c 162 #define LINUX_SIOCGIFMETRIC 0x891d 163 #define LINUX_SIOCSIFMETRIC 0x891e 164 #define LINUX_SIOCGIFMTU 0x8921 165 #define LINUX_SIOCSIFMTU 0x8922 166 #define LINUX_SIOCSIFNAME 0x8923 167 #define LINUX_SIOCADDMULTI 0x8931 168 #define LINUX_SIOCDELMULTI 0x8932 169 #define LINUX_SIOCGIFINDEX 0x8933 170 #define LINUX_SIOCDIFADDR 0x8936 171 172 /* ioctl define end */ 173 174 /* af define start */ 175 176 #define LINUX_AF_INET6 10 177 178 /* af define end */ 179 180 /* msghdr define start */ 181 182 struct linux_msghdr { 183 void *msg_name; /* Address to send to/receive from. */ 184 socklen_t msg_namelen; /* Length of address data. */ 185 186 struct iovec *msg_iov; /* Vector of data to send/receive into. */ 187 size_t msg_iovlen; /* Number of elements in the vector. */ 188 189 void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ 190 size_t msg_controllen; /* Ancillary data buffer length. 191 !! The type should be socklen_t but the 192 definition of the kernel is incompatible 193 with this. */ 194 195 int msg_flags; /* Flags on received message. */ 196 }; 197 198 /* msghdr define end */ 199 200 extern int sendit(struct thread *td, int s, struct msghdr *mp, int flags); 201 202 static long 203 linux2freebsd_ioctl(unsigned long request) 204 { 205 switch(request) { 206 case LINUX_TIOCEXCL: 207 return TIOCEXCL; 208 case LINUX_TIOCNXCL: 209 return TIOCNXCL; 210 case LINUX_TIOCSCTTY: 211 return TIOCSCTTY; 212 case LINUX_TIOCGPGRP: 213 return TIOCGPGRP; 214 case LINUX_TIOCSPGRP: 215 return TIOCSPGRP; 216 case LINUX_TIOCOUTQ: 217 return TIOCOUTQ; 218 case LINUX_TIOCSTI: 219 return TIOCSTI; 220 case LINUX_TIOCGWINSZ: 221 return TIOCGWINSZ; 222 case LINUX_TIOCSWINSZ: 223 return TIOCSWINSZ; 224 case LINUX_TIOCMGET: 225 return TIOCMGET; 226 case LINUX_TIOCMBIS: 227 return TIOCMBIS; 228 case LINUX_TIOCMBIC: 229 return TIOCMBIC; 230 case LINUX_TIOCMSET: 231 return TIOCMSET; 232 case LINUX_FIONREAD: 233 return FIONREAD; 234 case LINUX_TIOCCONS: 235 return TIOCCONS; 236 case LINUX_TIOCPKT: 237 return TIOCPKT; 238 case LINUX_FIONBIO: 239 return FIONBIO; 240 case LINUX_TIOCNOTTY: 241 return TIOCNOTTY; 242 case LINUX_TIOCSETD: 243 return TIOCSETD; 244 case LINUX_TIOCGETD: 245 return TIOCGETD; 246 case LINUX_TIOCSBRK: 247 return TIOCSBRK; 248 case LINUX_TIOCCBRK: 249 return TIOCCBRK; 250 case LINUX_TIOCGSID: 251 return TIOCGSID; 252 case LINUX_FIONCLEX: 253 return FIONCLEX; 254 case LINUX_FIOCLEX: 255 return FIOCLEX; 256 case LINUX_FIOASYNC: 257 return FIOASYNC; 258 case LINUX_TIOCPKT_DATA: 259 return TIOCPKT_DATA; 260 case LINUX_TIOCPKT_FLUSHREAD: 261 return TIOCPKT_FLUSHREAD; 262 case LINUX_TIOCPKT_FLUSHWRITE: 263 return TIOCPKT_FLUSHWRITE; 264 case LINUX_TIOCPKT_STOP: 265 return TIOCPKT_STOP; 266 case LINUX_TIOCPKT_START: 267 return TIOCPKT_START; 268 case LINUX_TIOCPKT_NOSTOP: 269 return TIOCPKT_NOSTOP; 270 case LINUX_TIOCPKT_DOSTOP: 271 return TIOCPKT_DOSTOP; 272 case LINUX_TIOCPKT_IOCTL: 273 return TIOCPKT_IOCTL; 274 case LINUX_SIOCGIFCONF: 275 return SIOCGIFCONF; 276 case LINUX_SIOCGIFFLAGS: 277 return SIOCGIFFLAGS; 278 case LINUX_SIOCSIFFLAGS: 279 return SIOCSIFFLAGS; 280 case LINUX_SIOCGIFADDR: 281 return SIOCGIFADDR; 282 case LINUX_SIOCSIFADDR: 283 return SIOCSIFADDR; 284 case LINUX_SIOCGIFDSTADDR: 285 return SIOCGIFDSTADDR; 286 case LINUX_SIOCSIFDSTADDR: 287 return SIOCSIFDSTADDR; 288 case LINUX_SIOCGIFBRDADDR: 289 return SIOCGIFBRDADDR; 290 case LINUX_SIOCSIFBRDADDR: 291 return SIOCSIFBRDADDR; 292 case LINUX_SIOCGIFNETMASK: 293 return SIOCGIFNETMASK; 294 case LINUX_SIOCSIFNETMASK: 295 return SIOCSIFNETMASK; 296 case LINUX_SIOCGIFMETRIC: 297 return SIOCGIFMETRIC; 298 case LINUX_SIOCSIFMETRIC: 299 return SIOCSIFMETRIC; 300 case LINUX_SIOCGIFMTU: 301 return SIOCGIFMTU; 302 case LINUX_SIOCSIFMTU: 303 return SIOCSIFMTU; 304 case LINUX_SIOCSIFNAME: 305 return SIOCSIFNAME; 306 case LINUX_SIOCADDMULTI: 307 return SIOCADDMULTI; 308 case LINUX_SIOCDELMULTI: 309 return SIOCDELMULTI; 310 case LINUX_SIOCGIFINDEX: 311 return SIOCGIFINDEX; 312 case LINUX_SIOCDIFADDR: 313 return SIOCDIFADDR; 314 default: 315 return -1; 316 } 317 } 318 319 static int 320 so_opt_convert(int optname) 321 { 322 switch(optname) { 323 case LINUX_SO_DEBUG: 324 return SO_DEBUG; 325 case LINUX_SO_REUSEADDR: 326 return SO_REUSEADDR; 327 case LINUX_SO_ERROR: 328 return SO_ERROR; 329 case LINUX_SO_DONTROUTE: 330 return SO_DONTROUTE; 331 case LINUX_SO_BROADCAST: 332 return SO_BROADCAST; 333 case LINUX_SO_SNDBUF: 334 return SO_SNDBUF; 335 case LINUX_SO_RCVBUF: 336 return SO_RCVBUF; 337 case LINUX_SO_KEEPALIVE: 338 return SO_KEEPALIVE; 339 case LINUX_SO_OOBINLINE: 340 return SO_OOBINLINE; 341 case LINUX_SO_LINGER: 342 return SO_LINGER; 343 case LINUX_SO_REUSEPORT: 344 return SO_REUSEPORT; 345 case LINUX_SO_RCVLOWAT: 346 return SO_RCVLOWAT; 347 case LINUX_SO_SNDLOWAT: 348 return SO_SNDLOWAT; 349 case LINUX_SO_RCVTIMEO: 350 return SO_RCVTIMEO; 351 case LINUX_SO_SNDTIMEO: 352 return SO_SNDTIMEO; 353 case LINUX_SO_ACCEPTCONN: 354 return SO_ACCEPTCONN; 355 case LINUX_SO_PROTOCOL: 356 return SO_PROTOCOL; 357 default: 358 return -1; 359 } 360 } 361 362 static int 363 ip_opt_convert(int optname) 364 { 365 switch(optname) { 366 case LINUX_IP_TOS: 367 return IP_TOS; 368 case LINUX_IP_TTL: 369 return IP_TTL; 370 case LINUX_IP_HDRINCL: 371 return IP_HDRINCL; 372 case LINUX_IP_OPTIONS: 373 return IP_OPTIONS; 374 case LINUX_IP_MULTICAST_IF: 375 return IP_MULTICAST_IF; 376 case LINUX_IP_MULTICAST_TTL: 377 return IP_MULTICAST_TTL; 378 case LINUX_IP_MULTICAST_LOOP: 379 return IP_MULTICAST_LOOP; 380 case LINUX_IP_ADD_MEMBERSHIP: 381 return IP_ADD_MEMBERSHIP; 382 case LINUX_IP_DROP_MEMBERSHIP: 383 return IP_DROP_MEMBERSHIP; 384 default: 385 return optname; 386 } 387 } 388 389 static int 390 ip6_opt_convert(int optname) 391 { 392 switch(optname) { 393 case LINUX_IPV6_V6ONLY: 394 return IPV6_V6ONLY; 395 case LINUX_IPV6_RECVPKTINFO: 396 return IPV6_RECVPKTINFO; 397 default: 398 return optname; 399 } 400 } 401 402 static int 403 tcp_opt_convert(int optname) 404 { 405 switch(optname) { 406 case LINUX_TCP_NODELAY: 407 return TCP_NODELAY; 408 case LINUX_TCP_MAXSEG: 409 return TCP_MAXSEG; 410 case LINUX_TCP_KEEPIDLE: 411 return TCP_KEEPIDLE; 412 case LINUX_TCP_KEEPINTVL: 413 return TCP_KEEPINTVL; 414 case LINUX_TCP_KEEPCNT: 415 return TCP_KEEPCNT; 416 case LINUX_TCP_INFO: 417 return TCP_INFO; 418 case LINUX_TCP_MD5SIG: 419 return TCP_MD5SIG; 420 default: 421 return -1; 422 } 423 } 424 425 static int 426 linux2freebsd_opt(int level, int optname) 427 { 428 switch(level) { 429 case SOL_SOCKET: 430 return so_opt_convert(optname); 431 case IPPROTO_IP: 432 return ip_opt_convert(optname); 433 case IPPROTO_IPV6: 434 return ip6_opt_convert(optname); 435 case IPPROTO_TCP: 436 return tcp_opt_convert(optname); 437 default: 438 return -1; 439 } 440 } 441 442 static void 443 linux2freebsd_sockaddr(const struct linux_sockaddr *linux, 444 socklen_t addrlen, struct sockaddr *freebsd) 445 { 446 if (linux == NULL) { 447 return; 448 } 449 450 /* #linux and #freebsd may point to the same address */ 451 freebsd->sa_family = linux->sa_family == LINUX_AF_INET6 ? AF_INET6 : linux->sa_family; 452 freebsd->sa_len = addrlen; 453 454 bcopy(linux->sa_data, freebsd->sa_data, addrlen - sizeof(linux->sa_family)); 455 } 456 457 static void 458 freebsd2linux_sockaddr(struct linux_sockaddr *linux, 459 struct sockaddr *freebsd) 460 { 461 if (linux == NULL) { 462 return; 463 } 464 465 linux->sa_family = freebsd->sa_family == AF_INET6 ? LINUX_AF_INET6 : freebsd->sa_family; 466 467 bcopy(freebsd->sa_data, linux->sa_data, freebsd->sa_len - sizeof(linux->sa_family)); 468 } 469 470 int 471 ff_socket(int domain, int type, int protocol) 472 { 473 int rc; 474 struct socket_args sa; 475 sa.domain = domain == LINUX_AF_INET6 ? AF_INET6 : domain; 476 sa.type = type; 477 sa.protocol = protocol; 478 if ((rc = sys_socket(curthread, &sa))) 479 goto kern_fail; 480 481 return curthread->td_retval[0]; 482 kern_fail: 483 ff_os_errno(rc); 484 return (-1); 485 } 486 487 int 488 ff_getsockopt(int s, int level, int optname, void *optval, 489 socklen_t *optlen) 490 { 491 int rc; 492 if (level == LINUX_SOL_SOCKET) 493 level = SOL_SOCKET; 494 495 optname = linux2freebsd_opt(level, optname); 496 if (optname < 0) { 497 rc = EINVAL; 498 goto kern_fail; 499 } 500 501 if ((rc = kern_getsockopt(curthread, s, level, optname, 502 optval, UIO_USERSPACE, optlen))) 503 goto kern_fail; 504 505 return (rc); 506 507 kern_fail: 508 ff_os_errno(rc); 509 return (-1); 510 } 511 512 int 513 ff_getsockopt_freebsd(int s, int level, int optname, 514 void *optval, socklen_t *optlen) 515 { 516 int rc; 517 518 if ((rc = kern_getsockopt(curthread, s, level, optname, 519 optval, UIO_USERSPACE, optlen))) 520 goto kern_fail; 521 522 return (rc); 523 524 kern_fail: 525 ff_os_errno(rc); 526 return (-1); 527 } 528 529 int 530 ff_setsockopt(int s, int level, int optname, const void *optval, 531 socklen_t optlen) 532 { 533 int rc; 534 535 if (level == LINUX_SOL_SOCKET) 536 level = SOL_SOCKET; 537 538 optname = linux2freebsd_opt(level, optname); 539 if (optname < 0) { 540 rc = EINVAL; 541 goto kern_fail; 542 } 543 544 if ((rc = kern_setsockopt(curthread, s, level, optname, 545 __DECONST(void *, optval), UIO_USERSPACE, optlen))) 546 goto kern_fail; 547 548 return (rc); 549 550 kern_fail: 551 ff_os_errno(rc); 552 return (-1); 553 } 554 555 int 556 ff_setsockopt_freebsd(int s, int level, int optname, 557 const void *optval, socklen_t optlen) 558 { 559 int rc; 560 561 if ((rc = kern_setsockopt(curthread, s, level, optname, 562 __DECONST(void *, optval), UIO_USERSPACE, optlen))) 563 goto kern_fail; 564 565 return (rc); 566 567 kern_fail: 568 ff_os_errno(rc); 569 return (-1); 570 } 571 572 int 573 ff_ioctl(int fd, unsigned long request, ...) 574 { 575 int rc; 576 va_list ap; 577 caddr_t argp; 578 579 long req = linux2freebsd_ioctl(request); 580 if (req < 0) { 581 rc = EINVAL; 582 goto kern_fail; 583 } 584 585 va_start(ap, request); 586 587 argp = va_arg(ap, caddr_t); 588 va_end(ap); 589 if ((rc = kern_ioctl(curthread, fd, req, argp))) 590 goto kern_fail; 591 592 return (rc); 593 594 kern_fail: 595 ff_os_errno(rc); 596 return (-1); 597 } 598 599 int 600 ff_ioctl_freebsd(int fd, unsigned long request, ...) 601 { 602 int rc; 603 va_list ap; 604 caddr_t argp; 605 606 va_start(ap, request); 607 608 argp = va_arg(ap, caddr_t); 609 va_end(ap); 610 if ((rc = kern_ioctl(curthread, fd, request, argp))) 611 goto kern_fail; 612 613 return (rc); 614 615 kern_fail: 616 ff_os_errno(rc); 617 return (-1); 618 } 619 620 int 621 ff_close(int fd) 622 { 623 int rc; 624 625 if ((rc = kern_close(curthread, fd))) 626 goto kern_fail; 627 628 return (rc); 629 kern_fail: 630 ff_os_errno(rc); 631 return (-1); 632 } 633 634 ssize_t 635 ff_read(int fd, void *buf, size_t nbytes) 636 { 637 struct uio auio; 638 struct iovec aiov; 639 int rc; 640 641 if (nbytes > INT_MAX) { 642 rc = EINVAL; 643 goto kern_fail; 644 } 645 646 aiov.iov_base = buf; 647 aiov.iov_len = nbytes; 648 auio.uio_iov = &aiov; 649 auio.uio_iovcnt = 1; 650 auio.uio_resid = nbytes; 651 auio.uio_segflg = UIO_SYSSPACE; 652 if ((rc = kern_readv(curthread, fd, &auio))) 653 goto kern_fail; 654 rc = curthread->td_retval[0]; 655 656 return (rc); 657 kern_fail: 658 ff_os_errno(rc); 659 return (-1); 660 } 661 662 ssize_t 663 ff_readv(int fd, const struct iovec *iov, int iovcnt) 664 { 665 struct uio auio; 666 int rc, len, i; 667 668 len = 0; 669 for (i = 0; i < iovcnt; i++) 670 len += iov[i].iov_len; 671 auio.uio_iov = __DECONST(struct iovec *, iov); 672 auio.uio_iovcnt = iovcnt; 673 auio.uio_resid = len; 674 auio.uio_segflg = UIO_SYSSPACE; 675 676 if ((rc = kern_readv(curthread, fd, &auio))) 677 goto kern_fail; 678 rc = curthread->td_retval[0]; 679 680 return (rc); 681 kern_fail: 682 ff_os_errno(rc); 683 return (-1); 684 } 685 686 ssize_t 687 ff_write(int fd, const void *buf, size_t nbytes) 688 { 689 struct uio auio; 690 struct iovec aiov; 691 int rc; 692 693 if (nbytes > INT_MAX) { 694 rc = EINVAL; 695 goto kern_fail; 696 } 697 698 aiov.iov_base = (void *)(uintptr_t)buf; 699 aiov.iov_len = nbytes; 700 auio.uio_iov = &aiov; 701 auio.uio_iovcnt = 1; 702 auio.uio_resid = nbytes; 703 auio.uio_segflg = UIO_SYSSPACE; 704 if ((rc = kern_writev(curthread, fd, &auio))) 705 goto kern_fail; 706 rc = curthread->td_retval[0]; 707 708 return (rc); 709 kern_fail: 710 ff_os_errno(rc); 711 return (-1); 712 } 713 714 ssize_t 715 ff_writev(int fd, const struct iovec *iov, int iovcnt) 716 { 717 struct uio auio; 718 int i, rc, len; 719 720 len = 0; 721 for (i = 0; i < iovcnt; i++) 722 len += iov[i].iov_len; 723 auio.uio_iov = __DECONST(struct iovec *, iov); 724 auio.uio_iovcnt = iovcnt; 725 auio.uio_resid = len; 726 auio.uio_segflg = UIO_SYSSPACE; 727 if ((rc = kern_writev(curthread, fd, &auio))) 728 goto kern_fail; 729 rc = curthread->td_retval[0]; 730 731 return (rc); 732 kern_fail: 733 ff_os_errno(rc); 734 return (-1); 735 } 736 737 ssize_t 738 ff_send(int s, const void *buf, size_t len, int flags) 739 { 740 return (ff_sendto(s, buf, len, flags, NULL, 0)); 741 } 742 743 ssize_t 744 ff_sendto(int s, const void *buf, size_t len, int flags, 745 const struct linux_sockaddr *to, socklen_t tolen) 746 { 747 struct msghdr msg; 748 struct iovec aiov; 749 int rc; 750 751 struct sockaddr_storage bsdaddr; 752 struct sockaddr *pf = (struct sockaddr *)&bsdaddr; 753 754 if (to) { 755 linux2freebsd_sockaddr(to, tolen, pf); 756 } else { 757 pf = NULL; 758 } 759 760 msg.msg_name = pf; 761 msg.msg_namelen = tolen; 762 msg.msg_iov = &aiov; 763 msg.msg_iovlen = 1; 764 msg.msg_control = 0; 765 aiov.iov_base = __DECONST(void *, buf); 766 aiov.iov_len = len; 767 if ((rc = sendit(curthread, s, &msg, flags))) 768 goto kern_fail; 769 770 rc = curthread->td_retval[0]; 771 772 return (rc); 773 kern_fail: 774 ff_os_errno(rc); 775 return (-1); 776 } 777 778 ssize_t 779 ff_sendmsg(int s, const struct msghdr *msg, int flags) 780 { 781 int rc; 782 struct sockaddr_storage freebsd_sa; 783 void *linux_sa = msg->msg_name; 784 785 if (linux_sa != NULL) { 786 linux2freebsd_sockaddr(linux_sa, 787 sizeof(struct linux_sockaddr), (struct sockaddr *)&freebsd_sa); 788 __DECONST(struct msghdr *, msg)->msg_name = &freebsd_sa; 789 } 790 791 rc = sendit(curthread, s, __DECONST(struct msghdr *, msg), flags); 792 793 __DECONST(struct msghdr *, msg)->msg_name = linux_sa; 794 795 if (rc) 796 goto kern_fail; 797 798 rc = curthread->td_retval[0]; 799 800 return (rc); 801 kern_fail: 802 ff_os_errno(rc); 803 return (-1); 804 } 805 806 807 ssize_t 808 ff_recv(int s, void *buf, size_t len, int flags) 809 { 810 return (ff_recvfrom(s, buf, len, flags, NULL, 0)); 811 } 812 813 ssize_t 814 ff_recvfrom(int s, void *buf, size_t len, int flags, 815 struct linux_sockaddr *from, socklen_t *fromlen) 816 { 817 struct msghdr msg; 818 struct iovec aiov; 819 int rc; 820 struct sockaddr_storage bsdaddr; 821 822 if (fromlen != NULL) 823 msg.msg_namelen = *fromlen; 824 else 825 msg.msg_namelen = 0; 826 827 msg.msg_name = &bsdaddr; 828 msg.msg_iov = &aiov; 829 msg.msg_iovlen = 1; 830 aiov.iov_base = buf; 831 aiov.iov_len = len; 832 msg.msg_control = 0; 833 msg.msg_flags = flags; 834 if ((rc = kern_recvit(curthread, s, &msg, UIO_SYSSPACE, NULL))) 835 goto kern_fail; 836 rc = curthread->td_retval[0]; 837 if (fromlen != NULL) 838 *fromlen = msg.msg_namelen; 839 840 if (from) 841 freebsd2linux_sockaddr(from, (struct sockaddr *)&bsdaddr); 842 843 return (rc); 844 kern_fail: 845 ff_os_errno(rc); 846 return (-1); 847 } 848 849 /* 850 * It is considered here that the upper 4 bytes of 851 * msg->iovlen and msg->msg_controllen in linux_msghdr are 0. 852 */ 853 ssize_t 854 ff_recvmsg(int s, struct msghdr *msg, int flags) 855 { 856 int rc; 857 struct linux_msghdr *linux_msg = (struct linux_msghdr *)msg; 858 859 msg->msg_flags = flags; 860 861 if ((rc = kern_recvit(curthread, s, msg, UIO_SYSSPACE, NULL))) { 862 msg->msg_flags = 0; 863 goto kern_fail; 864 } 865 rc = curthread->td_retval[0]; 866 867 freebsd2linux_sockaddr(linux_msg->msg_name, msg->msg_name); 868 linux_msg->msg_flags = msg->msg_flags; 869 msg->msg_flags = 0; 870 871 return (rc); 872 kern_fail: 873 ff_os_errno(rc); 874 return (-1); 875 } 876 877 int 878 ff_fcntl(int fd, int cmd, ...) 879 { 880 int rc; 881 va_list ap; 882 uintptr_t argp; 883 884 va_start(ap, cmd); 885 886 argp = va_arg(ap, uintptr_t); 887 va_end(ap); 888 889 if ((rc = kern_fcntl(curthread, fd, cmd, argp))) 890 goto kern_fail; 891 rc = curthread->td_retval[0]; 892 return (rc); 893 kern_fail: 894 ff_os_errno(rc); 895 return (-1); 896 } 897 898 int 899 ff_accept(int s, struct linux_sockaddr * addr, 900 socklen_t * addrlen) 901 { 902 int rc; 903 struct file *fp; 904 struct sockaddr *pf = NULL; 905 socklen_t socklen = sizeof(struct sockaddr_storage); 906 907 if ((rc = kern_accept(curthread, s, &pf, &socklen, &fp))) 908 goto kern_fail; 909 910 rc = curthread->td_retval[0]; 911 fdrop(fp, curthread); 912 913 if (addr && pf) 914 freebsd2linux_sockaddr(addr, pf); 915 916 if (addrlen) 917 *addrlen = pf->sa_len; 918 919 if(pf != NULL) 920 free(pf, M_SONAME); 921 return (rc); 922 923 kern_fail: 924 if(pf != NULL) 925 free(pf, M_SONAME); 926 ff_os_errno(rc); 927 return (-1); 928 } 929 930 int 931 ff_listen(int s, int backlog) 932 { 933 int rc; 934 struct listen_args la = { 935 .s = s, 936 .backlog = backlog, 937 }; 938 if ((rc = sys_listen(curthread, &la))) 939 goto kern_fail; 940 941 return (rc); 942 kern_fail: 943 ff_os_errno(rc); 944 return (-1); 945 } 946 947 int 948 ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen) 949 { 950 int rc; 951 struct sockaddr_storage bsdaddr; 952 linux2freebsd_sockaddr(addr, addrlen, (struct sockaddr *)&bsdaddr); 953 954 if ((rc = kern_bindat(curthread, AT_FDCWD, s, (struct sockaddr *)&bsdaddr))) 955 goto kern_fail; 956 957 return (rc); 958 kern_fail: 959 ff_os_errno(rc); 960 return (-1); 961 } 962 963 int 964 ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen) 965 { 966 int rc; 967 struct sockaddr_storage bsdaddr; 968 linux2freebsd_sockaddr(name, namelen, (struct sockaddr *)&bsdaddr); 969 970 if ((rc = kern_connectat(curthread, AT_FDCWD, s, (struct sockaddr *)&bsdaddr))) 971 goto kern_fail; 972 973 return (rc); 974 kern_fail: 975 ff_os_errno(rc); 976 return (-1); 977 } 978 979 int 980 ff_getpeername(int s, struct linux_sockaddr * name, 981 socklen_t *namelen) 982 { 983 int rc; 984 struct sockaddr *pf = NULL; 985 986 if ((rc = kern_getpeername(curthread, s, &pf, namelen))) 987 goto kern_fail; 988 989 if (name && pf) 990 freebsd2linux_sockaddr(name, pf); 991 992 if(pf != NULL) 993 free(pf, M_SONAME); 994 return (rc); 995 996 kern_fail: 997 if(pf != NULL) 998 free(pf, M_SONAME); 999 ff_os_errno(rc); 1000 return (-1); 1001 } 1002 1003 int 1004 ff_getsockname(int s, struct linux_sockaddr *name, 1005 socklen_t *namelen) 1006 { 1007 int rc; 1008 struct sockaddr *pf = NULL; 1009 1010 if ((rc = kern_getsockname(curthread, s, &pf, namelen))) 1011 goto kern_fail; 1012 1013 if (name && pf) 1014 freebsd2linux_sockaddr(name, pf); 1015 1016 if(pf != NULL) 1017 free(pf, M_SONAME); 1018 return (rc); 1019 1020 kern_fail: 1021 if(pf != NULL) 1022 free(pf, M_SONAME); 1023 ff_os_errno(rc); 1024 return (-1); 1025 } 1026 1027 int 1028 ff_shutdown(int s, int how) 1029 { 1030 int rc; 1031 1032 struct shutdown_args sa = { 1033 .s = s, 1034 .how = how, 1035 }; 1036 if ((rc = sys_shutdown(curthread, &sa))) 1037 goto kern_fail; 1038 1039 return (rc); 1040 kern_fail: 1041 ff_os_errno(rc); 1042 return (-1); 1043 } 1044 1045 int 1046 ff_sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, 1047 const void *newp, size_t newlen) 1048 { 1049 int rc; 1050 size_t retval; 1051 1052 rc = userland_sysctl(curthread, __DECONST(int *, name), namelen, oldp, oldlenp, 1053 1, __DECONST(void *, newp), newlen, &retval, 0); 1054 if (rc) 1055 goto kern_fail; 1056 if (oldlenp) 1057 *oldlenp = retval; 1058 return (0); 1059 kern_fail: 1060 ff_os_errno(rc); 1061 return (-1); 1062 } 1063 1064 int 1065 ff_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 1066 struct timeval *timeout) 1067 1068 { 1069 int rc; 1070 1071 rc = kern_select(curthread, nfds, readfds, writefds, exceptfds, timeout, 64); 1072 if (rc) 1073 goto kern_fail; 1074 rc = curthread->td_retval[0]; 1075 1076 return (rc); 1077 kern_fail: 1078 ff_os_errno(rc); 1079 return (-1); 1080 1081 } 1082 1083 int 1084 ff_poll(struct pollfd fds[], nfds_t nfds, int timeout) 1085 { 1086 int rc; 1087 struct timespec ts; 1088 ts.tv_sec = 0; 1089 ts.tv_nsec = 0; 1090 if ((rc = kern_poll(curthread, fds, nfds, &ts, NULL))) 1091 goto kern_fail; 1092 rc = curthread->td_retval[0]; 1093 return (rc); 1094 1095 kern_fail: 1096 ff_os_errno(rc); 1097 return (-1); 1098 } 1099 1100 int 1101 ff_kqueue(void) 1102 { 1103 int rc; 1104 if ((rc = kern_kqueue(curthread, 0, NULL))) 1105 goto kern_fail; 1106 1107 rc = curthread->td_retval[0]; 1108 return (rc); 1109 1110 kern_fail: 1111 ff_os_errno(rc); 1112 return (-1); 1113 } 1114 1115 struct sys_kevent_args { 1116 int fd; 1117 const struct kevent *changelist; 1118 int nchanges; 1119 void *eventlist; 1120 int nevents; 1121 const struct timespec *timeout; 1122 void (*do_each)(void **, struct kevent *); 1123 }; 1124 1125 static int 1126 kevent_copyout(void *arg, struct kevent *kevp, int count) 1127 { 1128 int i; 1129 struct kevent *ke; 1130 struct sys_kevent_args *uap; 1131 1132 uap = (struct sys_kevent_args *)arg; 1133 1134 if (!uap->do_each) { 1135 bcopy(kevp, uap->eventlist, count * sizeof *kevp); 1136 uap->eventlist = (void *)((struct kevent *)(uap->eventlist) + count); 1137 1138 } else { 1139 for (ke = kevp, i = 0; i < count; i++, ke++) { 1140 uap->do_each(&(uap->eventlist), ke); 1141 } 1142 } 1143 1144 return (0); 1145 } 1146 1147 /* 1148 * Copy 'count' items from the list pointed to by uap->changelist. 1149 */ 1150 static int 1151 kevent_copyin(void *arg, struct kevent *kevp, int count) 1152 { 1153 struct sys_kevent_args *uap; 1154 1155 uap = (struct sys_kevent_args *)arg; 1156 bcopy(uap->changelist, kevp, count * sizeof *kevp); 1157 1158 uap->changelist += count; 1159 1160 return (0); 1161 } 1162 1163 int 1164 ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges, 1165 void *eventlist, int nevents, const struct timespec *timeout, 1166 void (*do_each)(void **, struct kevent *)) 1167 { 1168 int rc; 1169 struct timespec ts; 1170 ts.tv_sec = 0; 1171 ts.tv_nsec = 0; 1172 1173 struct sys_kevent_args ska = { 1174 kq, 1175 changelist, 1176 nchanges, 1177 eventlist, 1178 nevents, 1179 &ts, 1180 do_each 1181 }; 1182 1183 struct kevent_copyops k_ops = { 1184 &ska, 1185 kevent_copyout, 1186 kevent_copyin 1187 }; 1188 1189 if ((rc = kern_kevent(curthread, kq, nchanges, nevents, &k_ops, 1190 &ts))) 1191 goto kern_fail; 1192 1193 rc = curthread->td_retval[0]; 1194 return (rc); 1195 kern_fail: 1196 ff_os_errno(rc); 1197 return (-1); 1198 } 1199 1200 int 1201 ff_kevent(int kq, const struct kevent *changelist, int nchanges, 1202 struct kevent *eventlist, int nevents, const struct timespec *timeout) 1203 { 1204 return ff_kevent_do_each(kq, changelist, nchanges, eventlist, nevents, timeout, NULL); 1205 } 1206 1207 int 1208 ff_gettimeofday(struct timeval *tv, struct timezone *tz) 1209 { 1210 long nsec; 1211 ff_get_current_time(&(tv->tv_sec), &nsec); 1212 tv->tv_usec = nsec/1000; 1213 return 0; 1214 } 1215 1216 int 1217 ff_dup(int oldfd) 1218 { 1219 int rc; 1220 struct dup_args da = { 1221 .fd = oldfd, 1222 }; 1223 if ((rc = sys_dup(curthread, &da))) 1224 goto kern_fail; 1225 1226 rc = curthread->td_retval[0]; 1227 1228 return (rc); 1229 kern_fail: 1230 ff_os_errno(rc); 1231 return (-1); 1232 } 1233 1234 int 1235 ff_dup2(int oldfd, int newfd) 1236 { 1237 int rc; 1238 struct dup2_args da = { 1239 .from = oldfd, 1240 .to = newfd 1241 }; 1242 if ((rc = sys_dup2(curthread, &da))) 1243 goto kern_fail; 1244 1245 rc = curthread->td_retval[0]; 1246 1247 return (rc); 1248 kern_fail: 1249 ff_os_errno(rc); 1250 return (-1); 1251 } 1252 1253 int 1254 ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag, 1255 struct linux_sockaddr *dst, struct linux_sockaddr *gw, 1256 struct linux_sockaddr *netmask) 1257 1258 { 1259 struct sockaddr_storage sa_gw, sa_dst, sa_nm; 1260 struct sockaddr *psa_gw, *psa_dst, *psa_nm; 1261 int rtreq, rtflag; 1262 int rc; 1263 1264 switch (req) { 1265 case FF_ROUTE_ADD: 1266 rtreq = RTM_ADD; 1267 break; 1268 case FF_ROUTE_DEL: 1269 rtreq = RTM_DELETE; 1270 break; 1271 case FF_ROUTE_CHANGE: 1272 rtreq = RTM_CHANGE; 1273 break; 1274 default: 1275 rc = EINVAL; 1276 goto kern_fail; 1277 } 1278 1279 switch (flag) { 1280 case FF_RTF_HOST: 1281 rtflag = RTF_HOST; 1282 break; 1283 case FF_RTF_GATEWAY: 1284 rtflag = RTF_GATEWAY; 1285 break; 1286 default: 1287 rc = EINVAL; 1288 goto kern_fail; 1289 }; 1290 1291 if (gw != NULL) { 1292 psa_gw = (struct sockaddr *)&sa_gw; 1293 linux2freebsd_sockaddr(gw, sizeof(*gw), psa_gw); 1294 } else { 1295 psa_gw = NULL; 1296 } 1297 1298 if (dst != NULL) { 1299 psa_dst = (struct sockaddr *)&sa_dst; 1300 linux2freebsd_sockaddr(dst, sizeof(*dst), psa_dst); 1301 } else { 1302 psa_dst = NULL; 1303 } 1304 1305 if (netmask != NULL) { 1306 psa_nm = (struct sockaddr *)&sa_nm; 1307 linux2freebsd_sockaddr(netmask, sizeof(*netmask), psa_nm); 1308 } else { 1309 psa_nm = NULL; 1310 } 1311 1312 rc = rtrequest_fib(rtreq, psa_dst, psa_gw, psa_nm, rtflag, 1313 NULL, RT_DEFAULT_FIB); 1314 1315 if (rc != 0) 1316 goto kern_fail; 1317 1318 return (rc); 1319 1320 kern_fail: 1321 ff_os_errno(rc); 1322 return (-1); 1323 } 1324