1 /*- 2 * Copyright (c) 2015 Dmitry Chagin <dchagin@FreeBSD.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include <opt_inet6.h> 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/conf.h> 34 #include <sys/ctype.h> 35 #include <sys/file.h> 36 #include <sys/filedesc.h> 37 #include <sys/jail.h> 38 #include <sys/lock.h> 39 #include <sys/malloc.h> 40 #include <sys/poll.h> 41 #include <sys/proc.h> 42 #include <sys/signalvar.h> 43 #include <sys/socket.h> 44 #include <sys/socketvar.h> 45 46 #include <net/if.h> 47 #include <net/if_var.h> 48 #include <net/if_dl.h> 49 #include <net/if_types.h> 50 51 #include <sys/un.h> 52 #include <netinet/in.h> 53 54 #include <compat/linux/linux.h> 55 #include <compat/linux/linux_common.h> 56 #include <compat/linux/linux_mib.h> 57 #include <compat/linux/linux_util.h> 58 59 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ); 60 61 static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = { 62 LINUX_SIGHUP, /* SIGHUP */ 63 LINUX_SIGINT, /* SIGINT */ 64 LINUX_SIGQUIT, /* SIGQUIT */ 65 LINUX_SIGILL, /* SIGILL */ 66 LINUX_SIGTRAP, /* SIGTRAP */ 67 LINUX_SIGABRT, /* SIGABRT */ 68 0, /* SIGEMT */ 69 LINUX_SIGFPE, /* SIGFPE */ 70 LINUX_SIGKILL, /* SIGKILL */ 71 LINUX_SIGBUS, /* SIGBUS */ 72 LINUX_SIGSEGV, /* SIGSEGV */ 73 LINUX_SIGSYS, /* SIGSYS */ 74 LINUX_SIGPIPE, /* SIGPIPE */ 75 LINUX_SIGALRM, /* SIGALRM */ 76 LINUX_SIGTERM, /* SIGTERM */ 77 LINUX_SIGURG, /* SIGURG */ 78 LINUX_SIGSTOP, /* SIGSTOP */ 79 LINUX_SIGTSTP, /* SIGTSTP */ 80 LINUX_SIGCONT, /* SIGCONT */ 81 LINUX_SIGCHLD, /* SIGCHLD */ 82 LINUX_SIGTTIN, /* SIGTTIN */ 83 LINUX_SIGTTOU, /* SIGTTOU */ 84 LINUX_SIGIO, /* SIGIO */ 85 LINUX_SIGXCPU, /* SIGXCPU */ 86 LINUX_SIGXFSZ, /* SIGXFSZ */ 87 LINUX_SIGVTALRM,/* SIGVTALRM */ 88 LINUX_SIGPROF, /* SIGPROF */ 89 LINUX_SIGWINCH, /* SIGWINCH */ 90 0, /* SIGINFO */ 91 LINUX_SIGUSR1, /* SIGUSR1 */ 92 LINUX_SIGUSR2 /* SIGUSR2 */ 93 }; 94 95 static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = { 96 SIGHUP, /* LINUX_SIGHUP */ 97 SIGINT, /* LINUX_SIGINT */ 98 SIGQUIT, /* LINUX_SIGQUIT */ 99 SIGILL, /* LINUX_SIGILL */ 100 SIGTRAP, /* LINUX_SIGTRAP */ 101 SIGABRT, /* LINUX_SIGABRT */ 102 SIGBUS, /* LINUX_SIGBUS */ 103 SIGFPE, /* LINUX_SIGFPE */ 104 SIGKILL, /* LINUX_SIGKILL */ 105 SIGUSR1, /* LINUX_SIGUSR1 */ 106 SIGSEGV, /* LINUX_SIGSEGV */ 107 SIGUSR2, /* LINUX_SIGUSR2 */ 108 SIGPIPE, /* LINUX_SIGPIPE */ 109 SIGALRM, /* LINUX_SIGALRM */ 110 SIGTERM, /* LINUX_SIGTERM */ 111 SIGBUS, /* LINUX_SIGSTKFLT */ 112 SIGCHLD, /* LINUX_SIGCHLD */ 113 SIGCONT, /* LINUX_SIGCONT */ 114 SIGSTOP, /* LINUX_SIGSTOP */ 115 SIGTSTP, /* LINUX_SIGTSTP */ 116 SIGTTIN, /* LINUX_SIGTTIN */ 117 SIGTTOU, /* LINUX_SIGTTOU */ 118 SIGURG, /* LINUX_SIGURG */ 119 SIGXCPU, /* LINUX_SIGXCPU */ 120 SIGXFSZ, /* LINUX_SIGXFSZ */ 121 SIGVTALRM, /* LINUX_SIGVTALARM */ 122 SIGPROF, /* LINUX_SIGPROF */ 123 SIGWINCH, /* LINUX_SIGWINCH */ 124 SIGIO, /* LINUX_SIGIO */ 125 /* 126 * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal 127 * to the first unused FreeBSD signal number. Since Linux supports 128 * signals from 1 to 64 we are ok here as our SIGRTMIN = 65. 129 */ 130 SIGRTMIN, /* LINUX_SIGPWR */ 131 SIGSYS /* LINUX_SIGSYS */ 132 }; 133 134 static struct cdev *dev_shm_cdev; 135 static struct cdevsw dev_shm_cdevsw = { 136 .d_version = D_VERSION, 137 .d_name = "dev_shm", 138 }; 139 140 /* 141 * Map Linux RT signals to the FreeBSD RT signals. 142 */ 143 static inline int 144 linux_to_bsd_rt_signal(int sig) 145 { 146 147 return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN); 148 } 149 150 static inline int 151 bsd_to_linux_rt_signal(int sig) 152 { 153 154 return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN); 155 } 156 157 int 158 linux_to_bsd_signal(int sig) 159 { 160 161 KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("invalid Linux signal %d\n", sig)); 162 163 if (sig < LINUX_SIGRTMIN) 164 return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]); 165 166 return (linux_to_bsd_rt_signal(sig)); 167 } 168 169 int 170 bsd_to_linux_signal(int sig) 171 { 172 173 if (sig <= LINUX_SIGTBLSZ) 174 return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]); 175 if (sig == SIGRTMIN) 176 return (LINUX_SIGPWR); 177 178 return (bsd_to_linux_rt_signal(sig)); 179 } 180 181 int 182 linux_to_bsd_sigaltstack(int lsa) 183 { 184 int bsa = 0; 185 186 if (lsa & LINUX_SS_DISABLE) 187 bsa |= SS_DISABLE; 188 /* 189 * Linux ignores SS_ONSTACK flag for ss 190 * parameter while FreeBSD prohibits it. 191 */ 192 return (bsa); 193 } 194 195 int 196 bsd_to_linux_sigaltstack(int bsa) 197 { 198 int lsa = 0; 199 200 if (bsa & SS_DISABLE) 201 lsa |= LINUX_SS_DISABLE; 202 if (bsa & SS_ONSTACK) 203 lsa |= LINUX_SS_ONSTACK; 204 return (lsa); 205 } 206 207 void 208 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 209 { 210 int b, l; 211 212 SIGEMPTYSET(*bss); 213 for (l = 1; l <= LINUX_SIGRTMAX; l++) { 214 if (LINUX_SIGISMEMBER(*lss, l)) { 215 b = linux_to_bsd_signal(l); 216 if (b) 217 SIGADDSET(*bss, b); 218 } 219 } 220 } 221 222 void 223 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 224 { 225 int b, l; 226 227 LINUX_SIGEMPTYSET(*lss); 228 for (b = 1; b <= SIGRTMAX; b++) { 229 if (SIGISMEMBER(*bss, b)) { 230 l = bsd_to_linux_signal(b); 231 if (l) 232 LINUX_SIGADDSET(*lss, l); 233 } 234 } 235 } 236 237 /* 238 * Translate a Linux interface name to a FreeBSD interface name, 239 * and return the associated ifnet structure 240 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 241 * can point to the same buffer. 242 */ 243 struct ifnet * 244 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) 245 { 246 struct ifnet *ifp; 247 int len, unit; 248 char *ep; 249 int index; 250 bool is_eth, is_lo; 251 252 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 253 if (!isalpha(lxname[len]) || lxname[len] == '\0') 254 break; 255 if (len == 0 || len == LINUX_IFNAMSIZ) 256 return (NULL); 257 /* Linux loopback interface name is lo (not lo0) */ 258 is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0); 259 unit = (int)strtoul(lxname + len, &ep, 10); 260 if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) && 261 is_lo == 0) 262 return (NULL); 263 index = 0; 264 is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); 265 266 CURVNET_SET(TD_TO_VNET(td)); 267 IFNET_RLOCK(); 268 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 269 /* 270 * Allow Linux programs to use FreeBSD names. Don't presume 271 * we never have an interface named "eth", so don't make 272 * the test optional based on is_eth. 273 */ 274 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) 275 break; 276 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 277 break; 278 if (is_lo && IFP_IS_LOOP(ifp)) 279 break; 280 } 281 IFNET_RUNLOCK(); 282 CURVNET_RESTORE(); 283 if (ifp != NULL && bsdname != NULL) 284 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); 285 return (ifp); 286 } 287 288 void 289 linux_ifflags(struct ifnet *ifp, short *flags) 290 { 291 unsigned short fl; 292 293 fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; 294 *flags = 0; 295 if (fl & IFF_UP) 296 *flags |= LINUX_IFF_UP; 297 if (fl & IFF_BROADCAST) 298 *flags |= LINUX_IFF_BROADCAST; 299 if (fl & IFF_DEBUG) 300 *flags |= LINUX_IFF_DEBUG; 301 if (fl & IFF_LOOPBACK) 302 *flags |= LINUX_IFF_LOOPBACK; 303 if (fl & IFF_POINTOPOINT) 304 *flags |= LINUX_IFF_POINTOPOINT; 305 if (fl & IFF_DRV_RUNNING) 306 *flags |= LINUX_IFF_RUNNING; 307 if (fl & IFF_NOARP) 308 *flags |= LINUX_IFF_NOARP; 309 if (fl & IFF_PROMISC) 310 *flags |= LINUX_IFF_PROMISC; 311 if (fl & IFF_ALLMULTI) 312 *flags |= LINUX_IFF_ALLMULTI; 313 if (fl & IFF_MULTICAST) 314 *flags |= LINUX_IFF_MULTICAST; 315 } 316 317 int 318 linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa) 319 { 320 struct ifaddr *ifa; 321 struct sockaddr_dl *sdl; 322 323 if (IFP_IS_LOOP(ifp)) { 324 bzero(lsa, sizeof(*lsa)); 325 lsa->sa_family = LINUX_ARPHRD_LOOPBACK; 326 return (0); 327 } 328 329 if (!IFP_IS_ETH(ifp)) 330 return (ENOENT); 331 332 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 333 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 334 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 335 (sdl->sdl_type == IFT_ETHER)) { 336 bzero(lsa, sizeof(*lsa)); 337 lsa->sa_family = LINUX_ARPHRD_ETHER; 338 bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); 339 return (0); 340 } 341 } 342 343 return (ENOENT); 344 } 345 346 int 347 linux_to_bsd_domain(int domain) 348 { 349 350 switch (domain) { 351 case LINUX_AF_UNSPEC: 352 return (AF_UNSPEC); 353 case LINUX_AF_UNIX: 354 return (AF_LOCAL); 355 case LINUX_AF_INET: 356 return (AF_INET); 357 case LINUX_AF_INET6: 358 return (AF_INET6); 359 case LINUX_AF_AX25: 360 return (AF_CCITT); 361 case LINUX_AF_IPX: 362 return (AF_IPX); 363 case LINUX_AF_APPLETALK: 364 return (AF_APPLETALK); 365 } 366 return (-1); 367 } 368 369 int 370 bsd_to_linux_domain(int domain) 371 { 372 373 switch (domain) { 374 case AF_UNSPEC: 375 return (LINUX_AF_UNSPEC); 376 case AF_LOCAL: 377 return (LINUX_AF_UNIX); 378 case AF_INET: 379 return (LINUX_AF_INET); 380 case AF_INET6: 381 return (LINUX_AF_INET6); 382 case AF_CCITT: 383 return (LINUX_AF_AX25); 384 case AF_IPX: 385 return (LINUX_AF_IPX); 386 case AF_APPLETALK: 387 return (LINUX_AF_APPLETALK); 388 } 389 return (-1); 390 } 391 392 /* 393 * Based on the fact that: 394 * 1. Native and Linux storage of struct sockaddr 395 * and struct sockaddr_in6 are equal. 396 * 2. On Linux sa_family is the first member of all struct sockaddr. 397 */ 398 int 399 bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa, 400 socklen_t len) 401 { 402 struct l_sockaddr *kosa; 403 int error, bdom; 404 405 *lsa = NULL; 406 if (len < 2 || len > UCHAR_MAX) 407 return (EINVAL); 408 409 kosa = malloc(len, M_SONAME, M_WAITOK); 410 bcopy(sa, kosa, len); 411 412 bdom = bsd_to_linux_domain(sa->sa_family); 413 if (bdom == -1) { 414 error = EAFNOSUPPORT; 415 goto out; 416 } 417 418 kosa->sa_family = bdom; 419 *lsa = kosa; 420 return (0); 421 422 out: 423 free(kosa, M_SONAME); 424 return (error); 425 } 426 427 int 428 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap, 429 socklen_t *len) 430 { 431 struct sockaddr *sa; 432 struct l_sockaddr *kosa; 433 #ifdef INET6 434 struct sockaddr_in6 *sin6; 435 bool oldv6size; 436 #endif 437 char *name; 438 int salen, bdom, error, hdrlen, namelen; 439 440 if (*len < 2 || *len > UCHAR_MAX) 441 return (EINVAL); 442 443 salen = *len; 444 445 #ifdef INET6 446 oldv6size = false; 447 /* 448 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 449 * if it's a v4-mapped address, so reserve the proper space 450 * for it. 451 */ 452 if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { 453 salen += sizeof(uint32_t); 454 oldv6size = true; 455 } 456 #endif 457 458 kosa = malloc(salen, M_SONAME, M_WAITOK); 459 460 if ((error = copyin(osa, kosa, *len))) 461 goto out; 462 463 bdom = linux_to_bsd_domain(kosa->sa_family); 464 if (bdom == -1) { 465 error = EAFNOSUPPORT; 466 goto out; 467 } 468 469 #ifdef INET6 470 /* 471 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 472 * which lacks the scope id compared with RFC2553 one. If we detect 473 * the situation, reject the address and write a message to system log. 474 * 475 * Still accept addresses for which the scope id is not used. 476 */ 477 if (oldv6size) { 478 if (bdom == AF_INET6) { 479 sin6 = (struct sockaddr_in6 *)kosa; 480 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 481 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 482 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 483 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 484 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 485 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 486 sin6->sin6_scope_id = 0; 487 } else { 488 linux_msg(curthread, 489 "obsolete pre-RFC2553 sockaddr_in6 rejected"); 490 error = EINVAL; 491 goto out; 492 } 493 } else 494 salen -= sizeof(uint32_t); 495 } 496 #endif 497 if (bdom == AF_INET) { 498 if (salen < sizeof(struct sockaddr_in)) { 499 error = EINVAL; 500 goto out; 501 } 502 salen = sizeof(struct sockaddr_in); 503 } 504 505 if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { 506 hdrlen = offsetof(struct sockaddr_un, sun_path); 507 name = ((struct sockaddr_un *)kosa)->sun_path; 508 if (*name == '\0') { 509 /* 510 * Linux abstract namespace starts with a NULL byte. 511 * XXX We do not support abstract namespace yet. 512 */ 513 namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; 514 } else 515 namelen = strnlen(name, salen - hdrlen); 516 salen = hdrlen + namelen; 517 if (salen > sizeof(struct sockaddr_un)) { 518 error = ENAMETOOLONG; 519 goto out; 520 } 521 } 522 523 sa = (struct sockaddr *)kosa; 524 sa->sa_family = bdom; 525 sa->sa_len = salen; 526 527 *sap = sa; 528 *len = salen; 529 return (0); 530 531 out: 532 free(kosa, M_SONAME); 533 return (error); 534 } 535 536 void 537 linux_dev_shm_create(void) 538 { 539 int error; 540 541 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &dev_shm_cdev, 542 &dev_shm_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0, "shm/.mountpoint"); 543 if (error != 0) { 544 printf("%s: failed to create device node, error %d\n", 545 __func__, error); 546 } 547 } 548 549 void 550 linux_dev_shm_destroy(void) 551 { 552 553 destroy_dev(dev_shm_cdev); 554 } 555 556 int 557 bsd_to_linux_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 558 size_t mapcnt, int no_value) 559 { 560 int bsd_mask, bsd_value, linux_mask, linux_value; 561 int linux_ret; 562 size_t i; 563 bool applied; 564 565 applied = false; 566 linux_ret = 0; 567 for (i = 0; i < mapcnt; ++i) { 568 bsd_mask = bitmap[i].bsd_mask; 569 bsd_value = bitmap[i].bsd_value; 570 if (bsd_mask == 0) 571 bsd_mask = bsd_value; 572 573 linux_mask = bitmap[i].linux_mask; 574 linux_value = bitmap[i].linux_value; 575 if (linux_mask == 0) 576 linux_mask = linux_value; 577 578 /* 579 * If a mask larger than just the value is set, we explicitly 580 * want to make sure that only this bit we mapped within that 581 * mask is set. 582 */ 583 if ((value & bsd_mask) == bsd_value) { 584 linux_ret = (linux_ret & ~linux_mask) | linux_value; 585 applied = true; 586 } 587 } 588 589 if (!applied) 590 return (no_value); 591 return (linux_ret); 592 } 593 594 int 595 linux_to_bsd_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 596 size_t mapcnt, int no_value) 597 { 598 int bsd_mask, bsd_value, linux_mask, linux_value; 599 int bsd_ret; 600 size_t i; 601 bool applied; 602 603 applied = false; 604 bsd_ret = 0; 605 for (i = 0; i < mapcnt; ++i) { 606 bsd_mask = bitmap[i].bsd_mask; 607 bsd_value = bitmap[i].bsd_value; 608 if (bsd_mask == 0) 609 bsd_mask = bsd_value; 610 611 linux_mask = bitmap[i].linux_mask; 612 linux_value = bitmap[i].linux_value; 613 if (linux_mask == 0) 614 linux_mask = linux_value; 615 616 /* 617 * If a mask larger than just the value is set, we explicitly 618 * want to make sure that only this bit we mapped within that 619 * mask is set. 620 */ 621 if ((value & linux_mask) == linux_value) { 622 bsd_ret = (bsd_ret & ~bsd_mask) | bsd_value; 623 applied = true; 624 } 625 } 626 627 if (!applied) 628 return (no_value); 629 return (bsd_ret); 630 } 631 632 void 633 linux_to_bsd_poll_events(struct thread *td, int fd, short lev, 634 short *bev) 635 { 636 struct proc *p = td->td_proc; 637 struct filedesc *fdp; 638 struct file *fp; 639 int error; 640 short bits = 0; 641 642 if (lev & LINUX_POLLIN) 643 bits |= POLLIN; 644 if (lev & LINUX_POLLPRI) 645 bits |= POLLPRI; 646 if (lev & LINUX_POLLOUT) 647 bits |= POLLOUT; 648 if (lev & LINUX_POLLERR) 649 bits |= POLLERR; 650 if (lev & LINUX_POLLHUP) 651 bits |= POLLHUP; 652 if (lev & LINUX_POLLNVAL) 653 bits |= POLLNVAL; 654 if (lev & LINUX_POLLRDNORM) 655 bits |= POLLRDNORM; 656 if (lev & LINUX_POLLRDBAND) 657 bits |= POLLRDBAND; 658 if (lev & LINUX_POLLWRBAND) 659 bits |= POLLWRBAND; 660 if (lev & LINUX_POLLWRNORM) 661 bits |= POLLWRNORM; 662 663 if (lev & LINUX_POLLRDHUP) { 664 /* 665 * It seems that the Linux silencly ignores POLLRDHUP 666 * on non-socket file descriptors unlike FreeBSD, where 667 * events bits is more strictly checked (POLLSTANDARD). 668 */ 669 fdp = p->p_fd; 670 error = fget_unlocked(fdp, fd, &cap_no_rights, &fp); 671 if (error == 0) { 672 /* 673 * XXX. On FreeBSD POLLRDHUP applies only to 674 * stream sockets. 675 */ 676 if (fp->f_type == DTYPE_SOCKET) 677 bits |= POLLRDHUP; 678 fdrop(fp, td); 679 } 680 } 681 682 if (lev & LINUX_POLLMSG) 683 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLMSG, events(%d)", lev); 684 if (lev & LINUX_POLLREMOVE) 685 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLREMOVE, events(%d)", lev); 686 687 *bev = bits; 688 } 689 690 void 691 bsd_to_linux_poll_events(short bev, short *lev) 692 { 693 short bits = 0; 694 695 if (bev & POLLIN) 696 bits |= LINUX_POLLIN; 697 if (bev & POLLPRI) 698 bits |= LINUX_POLLPRI; 699 if (bev & (POLLOUT | POLLWRNORM)) 700 /* 701 * POLLWRNORM is equal to POLLOUT on FreeBSD, 702 * but not on Linux 703 */ 704 bits |= LINUX_POLLOUT; 705 if (bev & POLLERR) 706 bits |= LINUX_POLLERR; 707 if (bev & POLLHUP) 708 bits |= LINUX_POLLHUP; 709 if (bev & POLLNVAL) 710 bits |= LINUX_POLLNVAL; 711 if (bev & POLLRDNORM) 712 bits |= LINUX_POLLRDNORM; 713 if (bev & POLLRDBAND) 714 bits |= LINUX_POLLRDBAND; 715 if (bev & POLLWRBAND) 716 bits |= LINUX_POLLWRBAND; 717 if (bev & POLLRDHUP) 718 bits |= LINUX_POLLRDHUP; 719 720 *lev = bits; 721 } 722