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