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