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