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 bdom; 404 405 *lsa = NULL; 406 if (len < 2 || len > UCHAR_MAX) 407 return (EINVAL); 408 bdom = bsd_to_linux_domain(sa->sa_family); 409 if (bdom == -1) 410 return (EAFNOSUPPORT); 411 412 kosa = malloc(len, M_SONAME, M_WAITOK); 413 bcopy(sa, kosa, len); 414 kosa->sa_family = bdom; 415 *lsa = kosa; 416 return (0); 417 } 418 419 int 420 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap, 421 socklen_t *len) 422 { 423 struct sockaddr *sa; 424 struct l_sockaddr *kosa; 425 #ifdef INET6 426 struct sockaddr_in6 *sin6; 427 bool oldv6size; 428 #endif 429 char *name; 430 int salen, bdom, error, hdrlen, namelen; 431 432 if (*len < 2 || *len > UCHAR_MAX) 433 return (EINVAL); 434 435 salen = *len; 436 437 #ifdef INET6 438 oldv6size = false; 439 /* 440 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 441 * if it's a v4-mapped address, so reserve the proper space 442 * for it. 443 */ 444 if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { 445 salen += sizeof(uint32_t); 446 oldv6size = true; 447 } 448 #endif 449 450 kosa = malloc(salen, M_SONAME, M_WAITOK); 451 452 if ((error = copyin(osa, kosa, *len))) 453 goto out; 454 455 bdom = linux_to_bsd_domain(kosa->sa_family); 456 if (bdom == -1) { 457 error = EAFNOSUPPORT; 458 goto out; 459 } 460 461 #ifdef INET6 462 /* 463 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 464 * which lacks the scope id compared with RFC2553 one. If we detect 465 * the situation, reject the address and write a message to system log. 466 * 467 * Still accept addresses for which the scope id is not used. 468 */ 469 if (oldv6size) { 470 if (bdom == AF_INET6) { 471 sin6 = (struct sockaddr_in6 *)kosa; 472 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 473 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 474 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 475 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 476 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 477 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 478 sin6->sin6_scope_id = 0; 479 } else { 480 linux_msg(curthread, 481 "obsolete pre-RFC2553 sockaddr_in6 rejected"); 482 error = EINVAL; 483 goto out; 484 } 485 } else 486 salen -= sizeof(uint32_t); 487 } 488 #endif 489 if (bdom == AF_INET) { 490 if (salen < sizeof(struct sockaddr_in)) { 491 error = EINVAL; 492 goto out; 493 } 494 salen = sizeof(struct sockaddr_in); 495 } 496 497 if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { 498 hdrlen = offsetof(struct sockaddr_un, sun_path); 499 name = ((struct sockaddr_un *)kosa)->sun_path; 500 if (*name == '\0') { 501 /* 502 * Linux abstract namespace starts with a NULL byte. 503 * XXX We do not support abstract namespace yet. 504 */ 505 namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; 506 } else 507 namelen = strnlen(name, salen - hdrlen); 508 salen = hdrlen + namelen; 509 if (salen > sizeof(struct sockaddr_un)) { 510 error = ENAMETOOLONG; 511 goto out; 512 } 513 } 514 515 sa = (struct sockaddr *)kosa; 516 sa->sa_family = bdom; 517 sa->sa_len = salen; 518 519 *sap = sa; 520 *len = salen; 521 return (0); 522 523 out: 524 free(kosa, M_SONAME); 525 return (error); 526 } 527 528 void 529 linux_dev_shm_create(void) 530 { 531 int error; 532 533 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &dev_shm_cdev, 534 &dev_shm_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0, "shm/.mountpoint"); 535 if (error != 0) { 536 printf("%s: failed to create device node, error %d\n", 537 __func__, error); 538 } 539 } 540 541 void 542 linux_dev_shm_destroy(void) 543 { 544 545 destroy_dev(dev_shm_cdev); 546 } 547 548 int 549 bsd_to_linux_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 550 size_t mapcnt, int no_value) 551 { 552 int bsd_mask, bsd_value, linux_mask, linux_value; 553 int linux_ret; 554 size_t i; 555 bool applied; 556 557 applied = false; 558 linux_ret = 0; 559 for (i = 0; i < mapcnt; ++i) { 560 bsd_mask = bitmap[i].bsd_mask; 561 bsd_value = bitmap[i].bsd_value; 562 if (bsd_mask == 0) 563 bsd_mask = bsd_value; 564 565 linux_mask = bitmap[i].linux_mask; 566 linux_value = bitmap[i].linux_value; 567 if (linux_mask == 0) 568 linux_mask = linux_value; 569 570 /* 571 * If a mask larger than just the value is set, we explicitly 572 * want to make sure that only this bit we mapped within that 573 * mask is set. 574 */ 575 if ((value & bsd_mask) == bsd_value) { 576 linux_ret = (linux_ret & ~linux_mask) | linux_value; 577 applied = true; 578 } 579 } 580 581 if (!applied) 582 return (no_value); 583 return (linux_ret); 584 } 585 586 int 587 linux_to_bsd_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 588 size_t mapcnt, int no_value) 589 { 590 int bsd_mask, bsd_value, linux_mask, linux_value; 591 int bsd_ret; 592 size_t i; 593 bool applied; 594 595 applied = false; 596 bsd_ret = 0; 597 for (i = 0; i < mapcnt; ++i) { 598 bsd_mask = bitmap[i].bsd_mask; 599 bsd_value = bitmap[i].bsd_value; 600 if (bsd_mask == 0) 601 bsd_mask = bsd_value; 602 603 linux_mask = bitmap[i].linux_mask; 604 linux_value = bitmap[i].linux_value; 605 if (linux_mask == 0) 606 linux_mask = linux_value; 607 608 /* 609 * If a mask larger than just the value is set, we explicitly 610 * want to make sure that only this bit we mapped within that 611 * mask is set. 612 */ 613 if ((value & linux_mask) == linux_value) { 614 bsd_ret = (bsd_ret & ~bsd_mask) | bsd_value; 615 applied = true; 616 } 617 } 618 619 if (!applied) 620 return (no_value); 621 return (bsd_ret); 622 } 623 624 void 625 linux_to_bsd_poll_events(struct thread *td, int fd, short lev, 626 short *bev) 627 { 628 struct file *fp; 629 int error; 630 short bits = 0; 631 632 if (lev & LINUX_POLLIN) 633 bits |= POLLIN; 634 if (lev & LINUX_POLLPRI) 635 bits |= POLLPRI; 636 if (lev & LINUX_POLLOUT) 637 bits |= POLLOUT; 638 if (lev & LINUX_POLLERR) 639 bits |= POLLERR; 640 if (lev & LINUX_POLLHUP) 641 bits |= POLLHUP; 642 if (lev & LINUX_POLLNVAL) 643 bits |= POLLNVAL; 644 if (lev & LINUX_POLLRDNORM) 645 bits |= POLLRDNORM; 646 if (lev & LINUX_POLLRDBAND) 647 bits |= POLLRDBAND; 648 if (lev & LINUX_POLLWRBAND) 649 bits |= POLLWRBAND; 650 if (lev & LINUX_POLLWRNORM) 651 bits |= POLLWRNORM; 652 653 if (lev & LINUX_POLLRDHUP) { 654 /* 655 * It seems that the Linux silencly ignores POLLRDHUP 656 * on non-socket file descriptors unlike FreeBSD, where 657 * events bits is more strictly checked (POLLSTANDARD). 658 */ 659 error = fget_unlocked(td, fd, &cap_no_rights, &fp); 660 if (error == 0) { 661 /* 662 * XXX. On FreeBSD POLLRDHUP applies only to 663 * stream sockets. 664 */ 665 if (fp->f_type == DTYPE_SOCKET) 666 bits |= POLLRDHUP; 667 fdrop(fp, td); 668 } 669 } 670 671 if (lev & LINUX_POLLMSG) 672 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLMSG, events(%d)", lev); 673 if (lev & LINUX_POLLREMOVE) 674 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLREMOVE, events(%d)", lev); 675 676 *bev = bits; 677 } 678 679 void 680 bsd_to_linux_poll_events(short bev, short *lev) 681 { 682 short bits = 0; 683 684 if (bev & POLLIN) 685 bits |= LINUX_POLLIN; 686 if (bev & POLLPRI) 687 bits |= LINUX_POLLPRI; 688 if (bev & (POLLOUT | POLLWRNORM)) 689 /* 690 * POLLWRNORM is equal to POLLOUT on FreeBSD, 691 * but not on Linux 692 */ 693 bits |= LINUX_POLLOUT; 694 if (bev & POLLERR) 695 bits |= LINUX_POLLERR; 696 if (bev & POLLHUP) 697 bits |= LINUX_POLLHUP; 698 if (bev & POLLNVAL) 699 bits |= LINUX_POLLNVAL; 700 if (bev & POLLRDNORM) 701 bits |= LINUX_POLLRDNORM; 702 if (bev & POLLRDBAND) 703 bits |= LINUX_POLLRDBAND; 704 if (bev & POLLWRBAND) 705 bits |= LINUX_POLLWRBAND; 706 if (bev & POLLRDHUP) 707 bits |= LINUX_POLLRDHUP; 708 709 *lev = bits; 710 } 711