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