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