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