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