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