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