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