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