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 bcopy(linux->sa_data, freebsd->sa_data, sizeof(linux->sa_data)); 408 } 409 410 static void 411 freebsd2linux_sockaddr(struct linux_sockaddr *linux, 412 struct sockaddr *freebsd) 413 { 414 if (linux == NULL) { 415 return; 416 } 417 418 linux->sa_family = freebsd->sa_family; 419 bcopy(freebsd->sa_data, linux->sa_data, sizeof(freebsd->sa_data)); 420 } 421 422 int 423 ff_socket(int domain, int type, int protocol) 424 { 425 int rc; 426 struct socket_args sa; 427 sa.domain = domain; 428 sa.type = type; 429 sa.protocol = protocol; 430 if ((rc = sys_socket(curthread, &sa))) 431 goto kern_fail; 432 433 return curthread->td_retval[0]; 434 kern_fail: 435 ff_os_errno(rc); 436 return (-1); 437 } 438 439 int 440 ff_getsockopt(int s, int level, int optname, void *optval, 441 socklen_t *optlen) 442 { 443 int rc; 444 if (level == LINUX_SOL_SOCKET) 445 level = SOL_SOCKET; 446 447 optname = linux2freebsd_opt(level, optname); 448 if (optname < 0) { 449 rc = EINVAL; 450 goto kern_fail; 451 } 452 453 if ((rc = kern_getsockopt(curthread, s, level, optname, 454 optval, UIO_USERSPACE, optlen))) 455 goto kern_fail; 456 457 return (rc); 458 459 kern_fail: 460 ff_os_errno(rc); 461 return (-1); 462 } 463 464 int 465 ff_getsockopt_freebsd(int s, int level, int optname, 466 void *optval, socklen_t *optlen) 467 { 468 int rc; 469 470 if ((rc = kern_getsockopt(curthread, s, level, optname, 471 optval, UIO_USERSPACE, optlen))) 472 goto kern_fail; 473 474 return (rc); 475 476 kern_fail: 477 ff_os_errno(rc); 478 return (-1); 479 } 480 481 int 482 ff_setsockopt(int s, int level, int optname, const void *optval, 483 socklen_t optlen) 484 { 485 int rc; 486 487 if (level == LINUX_SOL_SOCKET) 488 level = SOL_SOCKET; 489 490 optname = linux2freebsd_opt(level, optname); 491 if (optname < 0) { 492 rc = EINVAL; 493 goto kern_fail; 494 } 495 496 if ((rc = kern_setsockopt(curthread, s, level, optname, 497 __DECONST(void *, optval), UIO_USERSPACE, optlen))) 498 goto kern_fail; 499 500 return (rc); 501 502 kern_fail: 503 ff_os_errno(rc); 504 return (-1); 505 } 506 507 int 508 ff_setsockopt_freebsd(int s, int level, int optname, 509 const void *optval, socklen_t optlen) 510 { 511 int rc; 512 513 if ((rc = kern_setsockopt(curthread, s, level, optname, 514 __DECONST(void *, optval), UIO_USERSPACE, optlen))) 515 goto kern_fail; 516 517 return (rc); 518 519 kern_fail: 520 ff_os_errno(rc); 521 return (-1); 522 } 523 524 int 525 ff_ioctl(int fd, unsigned long request, ...) 526 { 527 int rc; 528 va_list ap; 529 caddr_t argp; 530 531 long req = linux2freebsd_ioctl(request); 532 if (req < 0) { 533 rc = EINVAL; 534 goto kern_fail; 535 } 536 537 va_start(ap, request); 538 539 argp = va_arg(ap, caddr_t); 540 va_end(ap); 541 if ((rc = kern_ioctl(curthread, fd, req, argp))) 542 goto kern_fail; 543 544 return (rc); 545 546 kern_fail: 547 ff_os_errno(rc); 548 return (-1); 549 } 550 551 int 552 ff_ioctl_freebsd(int fd, unsigned long request, ...) 553 { 554 int rc; 555 va_list ap; 556 caddr_t argp; 557 558 va_start(ap, request); 559 560 argp = va_arg(ap, caddr_t); 561 va_end(ap); 562 if ((rc = kern_ioctl(curthread, fd, request, argp))) 563 goto kern_fail; 564 565 return (rc); 566 567 kern_fail: 568 ff_os_errno(rc); 569 return (-1); 570 } 571 572 int 573 ff_close(int fd) 574 { 575 int rc; 576 577 if ((rc = kern_close(curthread, fd))) 578 goto kern_fail; 579 580 return (rc); 581 kern_fail: 582 ff_os_errno(rc); 583 return (-1); 584 } 585 586 ssize_t 587 ff_read(int fd, void *buf, size_t nbytes) 588 { 589 struct uio auio; 590 struct iovec aiov; 591 int rc; 592 593 if (nbytes > INT_MAX) { 594 rc = EINVAL; 595 goto kern_fail; 596 } 597 598 aiov.iov_base = buf; 599 aiov.iov_len = nbytes; 600 auio.uio_iov = &aiov; 601 auio.uio_iovcnt = 1; 602 auio.uio_resid = nbytes; 603 auio.uio_segflg = UIO_SYSSPACE; 604 if ((rc = kern_readv(curthread, fd, &auio))) 605 goto kern_fail; 606 rc = curthread->td_retval[0]; 607 608 return (rc); 609 kern_fail: 610 ff_os_errno(rc); 611 return (-1); 612 } 613 614 ssize_t 615 ff_readv(int fd, const struct iovec *iov, int iovcnt) 616 { 617 struct uio auio; 618 int rc, len, i; 619 620 len = 0; 621 for (i = 0; i < iovcnt; i++) 622 len += iov[i].iov_len; 623 auio.uio_iov = __DECONST(struct iovec *, iov); 624 auio.uio_iovcnt = iovcnt; 625 auio.uio_resid = len; 626 auio.uio_segflg = UIO_SYSSPACE; 627 628 if ((rc = kern_readv(curthread, fd, &auio))) 629 goto kern_fail; 630 rc = curthread->td_retval[0]; 631 632 return (rc); 633 kern_fail: 634 ff_os_errno(rc); 635 return (-1); 636 } 637 638 ssize_t 639 ff_write(int fd, const void *buf, size_t nbytes) 640 { 641 struct uio auio; 642 struct iovec aiov; 643 int rc; 644 645 if (nbytes > INT_MAX) { 646 rc = EINVAL; 647 goto kern_fail; 648 } 649 650 aiov.iov_base = (void *)(uintptr_t)buf; 651 aiov.iov_len = nbytes; 652 auio.uio_iov = &aiov; 653 auio.uio_iovcnt = 1; 654 auio.uio_resid = nbytes; 655 auio.uio_segflg = UIO_SYSSPACE; 656 if ((rc = kern_writev(curthread, fd, &auio))) 657 goto kern_fail; 658 rc = curthread->td_retval[0]; 659 660 return (rc); 661 kern_fail: 662 ff_os_errno(rc); 663 return (-1); 664 } 665 666 ssize_t 667 ff_writev(int fd, const struct iovec *iov, int iovcnt) 668 { 669 struct uio auio; 670 int i, rc, len; 671 672 len = 0; 673 for (i = 0; i < iovcnt; i++) 674 len += iov[i].iov_len; 675 auio.uio_iov = __DECONST(struct iovec *, iov); 676 auio.uio_iovcnt = iovcnt; 677 auio.uio_resid = len; 678 auio.uio_segflg = UIO_SYSSPACE; 679 if ((rc = kern_writev(curthread, fd, &auio))) 680 goto kern_fail; 681 rc = curthread->td_retval[0]; 682 683 return (rc); 684 kern_fail: 685 ff_os_errno(rc); 686 return (-1); 687 } 688 689 ssize_t 690 ff_send(int s, const void *buf, size_t len, int flags) 691 { 692 return (ff_sendto(s, buf, len, flags, NULL, 0)); 693 } 694 695 ssize_t 696 ff_sendto(int s, const void *buf, size_t len, int flags, 697 const struct linux_sockaddr *to, socklen_t tolen) 698 { 699 struct msghdr msg; 700 struct iovec aiov; 701 int rc; 702 703 struct sockaddr bsdaddr; 704 struct sockaddr *pf = &bsdaddr; 705 706 if (to) { 707 linux2freebsd_sockaddr(to, tolen, pf); 708 } else { 709 pf = NULL; 710 } 711 712 msg.msg_name = pf; 713 msg.msg_namelen = tolen; 714 msg.msg_iov = &aiov; 715 msg.msg_iovlen = 1; 716 msg.msg_control = 0; 717 aiov.iov_base = __DECONST(void *, buf); 718 aiov.iov_len = len; 719 if ((rc = sendit(curthread, s, &msg, flags))) 720 goto kern_fail; 721 722 rc = curthread->td_retval[0]; 723 724 return (rc); 725 kern_fail: 726 ff_os_errno(rc); 727 return (-1); 728 } 729 730 ssize_t 731 ff_sendmsg(int s, const struct msghdr *msg, int flags) 732 { 733 int rc; 734 struct sockaddr freebsd_sa; 735 void *linux_sa = msg->msg_name; 736 737 if (linux_sa != NULL) { 738 linux2freebsd_sockaddr(linux_sa, 739 sizeof(struct linux_sockaddr), &freebsd_sa); 740 __DECONST(struct msghdr *, msg)->msg_name = &freebsd_sa; 741 } 742 743 rc = sendit(curthread, s, __DECONST(struct msghdr *, msg), flags); 744 745 __DECONST(struct msghdr *, msg)->msg_name = linux_sa; 746 747 if (rc) 748 goto kern_fail; 749 750 rc = curthread->td_retval[0]; 751 752 return (rc); 753 kern_fail: 754 ff_os_errno(rc); 755 return (-1); 756 } 757 758 759 ssize_t 760 ff_recv(int s, void *buf, size_t len, int flags) 761 { 762 return (ff_recvfrom(s, buf, len, flags, NULL, 0)); 763 } 764 765 ssize_t 766 ff_recvfrom(int s, void *buf, size_t len, int flags, 767 struct linux_sockaddr *from, socklen_t *fromlen) 768 { 769 struct msghdr msg; 770 struct iovec aiov; 771 int rc; 772 struct sockaddr bsdaddr; 773 774 if (fromlen != NULL) 775 msg.msg_namelen = *fromlen; 776 else 777 msg.msg_namelen = 0; 778 779 msg.msg_name = &bsdaddr; 780 msg.msg_iov = &aiov; 781 msg.msg_iovlen = 1; 782 aiov.iov_base = buf; 783 aiov.iov_len = len; 784 msg.msg_control = 0; 785 msg.msg_flags = flags; 786 if ((rc = kern_recvit(curthread, s, &msg, UIO_SYSSPACE, NULL))) 787 goto kern_fail; 788 rc = curthread->td_retval[0]; 789 if (fromlen != NULL) 790 *fromlen = msg.msg_namelen; 791 792 if (from) 793 freebsd2linux_sockaddr(from, &bsdaddr); 794 795 return (rc); 796 kern_fail: 797 ff_os_errno(rc); 798 return (-1); 799 } 800 801 ssize_t 802 ff_recvmsg(int s, struct msghdr *msg, int flags) 803 { 804 int rc, oldflags; 805 806 oldflags = msg->msg_flags; 807 msg->msg_flags = flags; 808 809 if ((rc = kern_recvit(curthread, s, msg, UIO_SYSSPACE, NULL))) { 810 msg->msg_flags = oldflags; 811 goto kern_fail; 812 } 813 rc = curthread->td_retval[0]; 814 815 freebsd2linux_sockaddr(msg->msg_name, msg->msg_name); 816 817 return (rc); 818 kern_fail: 819 ff_os_errno(rc); 820 return (-1); 821 } 822 823 int 824 ff_fcntl(int fd, int cmd, ...) 825 { 826 int rc; 827 va_list ap; 828 uintptr_t argp; 829 830 va_start(ap, cmd); 831 832 argp = va_arg(ap, uintptr_t); 833 va_end(ap); 834 835 if ((rc = kern_fcntl(curthread, fd, cmd, argp))) 836 goto kern_fail; 837 rc = curthread->td_retval[0]; 838 return (rc); 839 kern_fail: 840 ff_os_errno(rc); 841 return (-1); 842 } 843 844 int 845 ff_accept(int s, struct linux_sockaddr * addr, 846 socklen_t * addrlen) 847 { 848 int rc; 849 struct file *fp; 850 struct sockaddr *pf = NULL; 851 socklen_t socklen = sizeof(struct sockaddr); 852 853 if ((rc = kern_accept(curthread, s, &pf, &socklen, &fp))) 854 goto kern_fail; 855 856 rc = curthread->td_retval[0]; 857 fdrop(fp, curthread); 858 859 if (addr && pf) 860 freebsd2linux_sockaddr(addr, pf); 861 862 if (addrlen) 863 *addrlen = socklen; 864 865 if(pf != NULL) 866 free(pf, M_SONAME); 867 return (rc); 868 869 kern_fail: 870 if(pf != NULL) 871 free(pf, M_SONAME); 872 ff_os_errno(rc); 873 return (-1); 874 } 875 876 int 877 ff_listen(int s, int backlog) 878 { 879 int rc; 880 struct listen_args la = { 881 .s = s, 882 .backlog = backlog, 883 }; 884 if ((rc = sys_listen(curthread, &la))) 885 goto kern_fail; 886 887 return (rc); 888 kern_fail: 889 ff_os_errno(rc); 890 return (-1); 891 } 892 893 int 894 ff_bind(int s, const struct linux_sockaddr *addr, socklen_t addrlen) 895 { 896 int rc; 897 struct sockaddr bsdaddr; 898 linux2freebsd_sockaddr(addr, addrlen, &bsdaddr); 899 900 if ((rc = kern_bindat(curthread, AT_FDCWD, s, &bsdaddr))) 901 goto kern_fail; 902 903 return (rc); 904 kern_fail: 905 ff_os_errno(rc); 906 return (-1); 907 } 908 909 int 910 ff_connect(int s, const struct linux_sockaddr *name, socklen_t namelen) 911 { 912 int rc; 913 struct sockaddr bsdaddr; 914 linux2freebsd_sockaddr(name, namelen, &bsdaddr); 915 916 if ((rc = kern_connectat(curthread, AT_FDCWD, s, &bsdaddr))) 917 goto kern_fail; 918 919 return (rc); 920 kern_fail: 921 ff_os_errno(rc); 922 return (-1); 923 } 924 925 int 926 ff_getpeername(int s, struct linux_sockaddr * name, 927 socklen_t *namelen) 928 { 929 int rc; 930 struct sockaddr *pf = NULL; 931 932 if ((rc = kern_getpeername(curthread, s, &pf, namelen))) 933 goto kern_fail; 934 935 if (name && pf) 936 freebsd2linux_sockaddr(name, pf); 937 938 if(pf != NULL) 939 free(pf, M_SONAME); 940 return (rc); 941 942 kern_fail: 943 if(pf != NULL) 944 free(pf, M_SONAME); 945 ff_os_errno(rc); 946 return (-1); 947 } 948 949 int 950 ff_getsockname(int s, struct linux_sockaddr *name, 951 socklen_t *namelen) 952 { 953 int rc; 954 struct sockaddr *pf = NULL; 955 956 if ((rc = kern_getsockname(curthread, s, &pf, namelen))) 957 goto kern_fail; 958 959 if (name && pf) 960 freebsd2linux_sockaddr(name, pf); 961 962 if(pf != NULL) 963 free(pf, M_SONAME); 964 return (rc); 965 966 kern_fail: 967 if(pf != NULL) 968 free(pf, M_SONAME); 969 ff_os_errno(rc); 970 return (-1); 971 } 972 973 int 974 ff_shutdown(int s, int how) 975 { 976 int rc; 977 978 struct shutdown_args sa = { 979 .s = s, 980 .how = how, 981 }; 982 if ((rc = sys_shutdown(curthread, &sa))) 983 goto kern_fail; 984 985 return (rc); 986 kern_fail: 987 ff_os_errno(rc); 988 return (-1); 989 } 990 991 int 992 ff_sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp, 993 const void *newp, size_t newlen) 994 { 995 int rc; 996 size_t retval; 997 998 rc = userland_sysctl(curthread, __DECONST(int *, name), namelen, oldp, oldlenp, 999 1, __DECONST(void *, newp), newlen, &retval, 0); 1000 if (rc) 1001 goto kern_fail; 1002 if (oldlenp) 1003 *oldlenp = retval; 1004 return (0); 1005 kern_fail: 1006 ff_os_errno(rc); 1007 return (-1); 1008 } 1009 1010 int 1011 ff_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 1012 struct timeval *timeout) 1013 1014 { 1015 int rc; 1016 1017 rc = kern_select(curthread, nfds, readfds, writefds, exceptfds, timeout, 64); 1018 if (rc) 1019 goto kern_fail; 1020 rc = curthread->td_retval[0]; 1021 1022 return (rc); 1023 kern_fail: 1024 ff_os_errno(rc); 1025 return (-1); 1026 1027 } 1028 1029 int 1030 ff_poll(struct pollfd fds[], nfds_t nfds, int timeout) 1031 { 1032 int rc; 1033 struct timespec ts; 1034 ts.tv_sec = 0; 1035 ts.tv_nsec = 0; 1036 if ((rc = kern_poll(curthread, fds, nfds, &ts, NULL))) 1037 goto kern_fail; 1038 rc = curthread->td_retval[0]; 1039 return (rc); 1040 1041 kern_fail: 1042 ff_os_errno(rc); 1043 return (-1); 1044 } 1045 1046 int 1047 ff_kqueue(void) 1048 { 1049 int rc; 1050 if ((rc = kern_kqueue(curthread, 0, NULL))) 1051 goto kern_fail; 1052 1053 rc = curthread->td_retval[0]; 1054 return (rc); 1055 1056 kern_fail: 1057 ff_os_errno(rc); 1058 return (-1); 1059 } 1060 1061 struct sys_kevent_args { 1062 int fd; 1063 const struct kevent *changelist; 1064 int nchanges; 1065 void *eventlist; 1066 int nevents; 1067 const struct timespec *timeout; 1068 void (*do_each)(void **, struct kevent *); 1069 }; 1070 1071 static int 1072 kevent_copyout(void *arg, struct kevent *kevp, int count) 1073 { 1074 int i; 1075 struct kevent *ke; 1076 struct sys_kevent_args *uap; 1077 1078 uap = (struct sys_kevent_args *)arg; 1079 1080 if (!uap->do_each) { 1081 bcopy(kevp, uap->eventlist, count * sizeof *kevp); 1082 uap->eventlist = (void *)((struct kevent *)(uap->eventlist) + count); 1083 1084 } else { 1085 for (ke = kevp, i = 0; i < count; i++, ke++) { 1086 uap->do_each(&(uap->eventlist), ke); 1087 } 1088 } 1089 1090 return (0); 1091 } 1092 1093 /* 1094 * Copy 'count' items from the list pointed to by uap->changelist. 1095 */ 1096 static int 1097 kevent_copyin(void *arg, struct kevent *kevp, int count) 1098 { 1099 struct sys_kevent_args *uap; 1100 1101 uap = (struct sys_kevent_args *)arg; 1102 bcopy(uap->changelist, kevp, count * sizeof *kevp); 1103 1104 uap->changelist += count; 1105 1106 return (0); 1107 } 1108 1109 int 1110 ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges, 1111 void *eventlist, int nevents, const struct timespec *timeout, 1112 void (*do_each)(void **, struct kevent *)) 1113 { 1114 int rc; 1115 struct timespec ts; 1116 ts.tv_sec = 0; 1117 ts.tv_nsec = 0; 1118 1119 struct sys_kevent_args ska = { 1120 kq, 1121 changelist, 1122 nchanges, 1123 eventlist, 1124 nevents, 1125 &ts, 1126 do_each 1127 }; 1128 1129 struct kevent_copyops k_ops = { 1130 &ska, 1131 kevent_copyout, 1132 kevent_copyin 1133 }; 1134 1135 if ((rc = kern_kevent(curthread, kq, nchanges, nevents, &k_ops, 1136 &ts))) 1137 goto kern_fail; 1138 1139 rc = curthread->td_retval[0]; 1140 return (rc); 1141 kern_fail: 1142 ff_os_errno(rc); 1143 return (-1); 1144 } 1145 1146 int 1147 ff_kevent(int kq, const struct kevent *changelist, int nchanges, 1148 struct kevent *eventlist, int nevents, const struct timespec *timeout) 1149 { 1150 return ff_kevent_do_each(kq, changelist, nchanges, eventlist, nevents, timeout, NULL); 1151 } 1152 1153 int 1154 ff_gettimeofday(struct timeval *tv, struct timezone *tz) 1155 { 1156 long nsec; 1157 ff_get_current_time(&(tv->tv_sec), &nsec); 1158 tv->tv_usec = nsec/1000; 1159 return 0; 1160 } 1161 1162 int 1163 ff_dup(int oldfd) 1164 { 1165 int rc; 1166 struct dup_args da = { 1167 .fd = oldfd, 1168 }; 1169 if ((rc = sys_dup(curthread, &da))) 1170 goto kern_fail; 1171 1172 rc = curthread->td_retval[0]; 1173 1174 return (rc); 1175 kern_fail: 1176 ff_os_errno(rc); 1177 return (-1); 1178 } 1179 1180 int 1181 ff_dup2(int oldfd, int newfd) 1182 { 1183 int rc; 1184 struct dup2_args da = { 1185 .from = oldfd, 1186 .to = newfd 1187 }; 1188 if ((rc = sys_dup2(curthread, &da))) 1189 goto kern_fail; 1190 1191 rc = curthread->td_retval[0]; 1192 1193 return (rc); 1194 kern_fail: 1195 ff_os_errno(rc); 1196 return (-1); 1197 } 1198 1199 int 1200 ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag, 1201 struct linux_sockaddr *dst, struct linux_sockaddr *gw, 1202 struct linux_sockaddr *netmask) 1203 1204 { 1205 struct sockaddr sa_gw, sa_dst, sa_nm; 1206 struct sockaddr *psa_gw, *psa_dst, *psa_nm; 1207 int rtreq, rtflag; 1208 int rc; 1209 1210 switch (req) { 1211 case FF_ROUTE_ADD: 1212 rtreq = RTM_ADD; 1213 break; 1214 case FF_ROUTE_DEL: 1215 rtreq = RTM_DELETE; 1216 break; 1217 case FF_ROUTE_CHANGE: 1218 rtreq = RTM_CHANGE; 1219 break; 1220 default: 1221 rc = EINVAL; 1222 goto kern_fail; 1223 } 1224 1225 switch (flag) { 1226 case FF_RTF_HOST: 1227 rtflag = RTF_HOST; 1228 break; 1229 case FF_RTF_GATEWAY: 1230 rtflag = RTF_GATEWAY; 1231 break; 1232 default: 1233 rc = EINVAL; 1234 goto kern_fail; 1235 }; 1236 1237 if (gw != NULL) { 1238 psa_gw = &sa_gw; 1239 linux2freebsd_sockaddr(gw, sizeof(*gw), psa_gw); 1240 } else { 1241 psa_gw = NULL; 1242 } 1243 1244 if (dst != NULL) { 1245 psa_dst = &sa_dst; 1246 linux2freebsd_sockaddr(dst, sizeof(*dst), psa_dst); 1247 } else { 1248 psa_dst = NULL; 1249 } 1250 1251 if (netmask != NULL) { 1252 psa_nm = &sa_nm; 1253 linux2freebsd_sockaddr(netmask, sizeof(*netmask), psa_nm); 1254 } else { 1255 psa_nm = NULL; 1256 } 1257 1258 rc = rtrequest_fib(rtreq, psa_dst, psa_gw, psa_nm, rtflag, 1259 NULL, RT_DEFAULT_FIB); 1260 1261 if (rc != 0) 1262 goto kern_fail; 1263 1264 return (rc); 1265 1266 kern_fail: 1267 ff_os_errno(rc); 1268 return (-1); 1269 } 1270