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