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 /* 245 * Translate a FreeBSD interface name to a Linux interface name 246 * by interface name, and return the number of bytes copied to lxname. 247 */ 248 int 249 ifname_bsd_to_linux_name(const char *bsdname, char *lxname, size_t len) 250 { 251 struct epoch_tracker et; 252 struct ifnet *ifp; 253 int ret; 254 255 ret = 0; 256 CURVNET_SET(TD_TO_VNET(curthread)); 257 NET_EPOCH_ENTER(et); 258 ifp = ifunit(bsdname); 259 if (ifp != NULL) 260 ret = ifname_bsd_to_linux_ifp(ifp, lxname, len); 261 NET_EPOCH_EXIT(et); 262 CURVNET_RESTORE(); 263 return (ret); 264 } 265 266 /* 267 * Translate a FreeBSD interface name to a Linux interface name 268 * by interface index, and return the number of bytes copied to lxname. 269 */ 270 int 271 ifname_bsd_to_linux_idx(u_int idx, char *lxname, size_t len) 272 { 273 struct epoch_tracker et; 274 struct ifnet *ifp; 275 int ret; 276 277 ret = 0; 278 CURVNET_SET(TD_TO_VNET(curthread)); 279 NET_EPOCH_ENTER(et); 280 ifp = ifnet_byindex(idx); 281 if (ifp != NULL) 282 ret = ifname_bsd_to_linux_ifp(ifp, lxname, len); 283 NET_EPOCH_EXIT(et); 284 CURVNET_RESTORE(); 285 return (ret); 286 } 287 288 /* 289 * Translate a FreeBSD interface name to a Linux interface name, 290 * and return the number of bytes copied to lxname. 291 */ 292 int 293 ifname_bsd_to_linux_ifp(struct ifnet *ifp, char *lxname, size_t len) 294 { 295 struct ifnet *ifscan; 296 int unit; 297 298 NET_EPOCH_ASSERT(); 299 300 /* 301 * Linux loopback interface name is lo (not lo0), 302 * we translate lo to lo0, loX to loX. 303 */ 304 if (IFP_IS_LOOP(ifp) && strncmp(ifp->if_xname, "lo0", IFNAMSIZ) == 0) 305 return (strlcpy(lxname, "lo", len)); 306 307 /* Short-circuit non ethernet interfaces. */ 308 if (!IFP_IS_ETH(ifp) || linux_use_real_ifname(ifp)) 309 return (strlcpy(lxname, ifp->if_xname, len)); 310 311 /* Determine the (relative) unit number for ethernet interfaces. */ 312 unit = 0; 313 CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) { 314 if (ifscan == ifp) 315 return (snprintf(lxname, len, "eth%d", unit)); 316 if (IFP_IS_ETH(ifscan)) 317 unit++; 318 } 319 return (0); 320 } 321 322 /* 323 * Translate a Linux interface name to a FreeBSD interface name, 324 * and return the associated ifnet structure 325 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 326 * can point to the same buffer. 327 */ 328 struct ifnet * 329 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) 330 { 331 struct ifnet *ifp; 332 int len, unit; 333 char *ep; 334 int index; 335 bool is_eth, is_lo; 336 337 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 338 if (!isalpha(lxname[len]) || lxname[len] == '\0') 339 break; 340 if (len == 0 || len == LINUX_IFNAMSIZ) 341 return (NULL); 342 /* 343 * Linux loopback interface name is lo (not lo0), 344 * we translate lo to lo0, loX to loX. 345 */ 346 is_lo = (len == 2 && strncmp(lxname, "lo", LINUX_IFNAMSIZ) == 0); 347 unit = (int)strtoul(lxname + len, &ep, 10); 348 if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) && 349 is_lo == 0) 350 return (NULL); 351 index = 0; 352 is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); 353 354 CURVNET_SET(TD_TO_VNET(td)); 355 IFNET_RLOCK(); 356 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 357 /* 358 * Allow Linux programs to use FreeBSD names. Don't presume 359 * we never have an interface named "eth", so don't make 360 * the test optional based on is_eth. 361 */ 362 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) 363 break; 364 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 365 break; 366 if (is_lo && IFP_IS_LOOP(ifp)) 367 break; 368 } 369 IFNET_RUNLOCK(); 370 CURVNET_RESTORE(); 371 if (ifp != NULL && bsdname != NULL) 372 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); 373 return (ifp); 374 } 375 376 void 377 linux_ifflags(struct ifnet *ifp, short *flags) 378 { 379 unsigned short fl; 380 381 fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; 382 *flags = 0; 383 if (fl & IFF_UP) 384 *flags |= LINUX_IFF_UP; 385 if (fl & IFF_BROADCAST) 386 *flags |= LINUX_IFF_BROADCAST; 387 if (fl & IFF_DEBUG) 388 *flags |= LINUX_IFF_DEBUG; 389 if (fl & IFF_LOOPBACK) 390 *flags |= LINUX_IFF_LOOPBACK; 391 if (fl & IFF_POINTOPOINT) 392 *flags |= LINUX_IFF_POINTOPOINT; 393 if (fl & IFF_DRV_RUNNING) 394 *flags |= LINUX_IFF_RUNNING; 395 if (fl & IFF_NOARP) 396 *flags |= LINUX_IFF_NOARP; 397 if (fl & IFF_PROMISC) 398 *flags |= LINUX_IFF_PROMISC; 399 if (fl & IFF_ALLMULTI) 400 *flags |= LINUX_IFF_ALLMULTI; 401 if (fl & IFF_MULTICAST) 402 *flags |= LINUX_IFF_MULTICAST; 403 } 404 405 int 406 linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa) 407 { 408 struct ifaddr *ifa; 409 struct sockaddr_dl *sdl; 410 411 if (IFP_IS_LOOP(ifp)) { 412 bzero(lsa, sizeof(*lsa)); 413 lsa->sa_family = LINUX_ARPHRD_LOOPBACK; 414 return (0); 415 } 416 417 if (!IFP_IS_ETH(ifp)) 418 return (ENOENT); 419 420 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 421 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 422 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 423 (sdl->sdl_type == IFT_ETHER)) { 424 bzero(lsa, sizeof(*lsa)); 425 lsa->sa_family = LINUX_ARPHRD_ETHER; 426 bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); 427 return (0); 428 } 429 } 430 431 return (ENOENT); 432 } 433 434 int 435 linux_to_bsd_domain(int domain) 436 { 437 438 switch (domain) { 439 case LINUX_AF_UNSPEC: 440 return (AF_UNSPEC); 441 case LINUX_AF_UNIX: 442 return (AF_LOCAL); 443 case LINUX_AF_INET: 444 return (AF_INET); 445 case LINUX_AF_INET6: 446 return (AF_INET6); 447 case LINUX_AF_AX25: 448 return (AF_CCITT); 449 case LINUX_AF_IPX: 450 return (AF_IPX); 451 case LINUX_AF_APPLETALK: 452 return (AF_APPLETALK); 453 case LINUX_AF_NETLINK: 454 return (AF_NETLINK); 455 } 456 return (-1); 457 } 458 459 int 460 bsd_to_linux_domain(int domain) 461 { 462 463 switch (domain) { 464 case AF_UNSPEC: 465 return (LINUX_AF_UNSPEC); 466 case AF_LOCAL: 467 return (LINUX_AF_UNIX); 468 case AF_INET: 469 return (LINUX_AF_INET); 470 case AF_INET6: 471 return (LINUX_AF_INET6); 472 case AF_CCITT: 473 return (LINUX_AF_AX25); 474 case AF_IPX: 475 return (LINUX_AF_IPX); 476 case AF_APPLETALK: 477 return (LINUX_AF_APPLETALK); 478 case AF_NETLINK: 479 return (LINUX_AF_NETLINK); 480 } 481 return (-1); 482 } 483 484 /* 485 * Based on the fact that: 486 * 1. Native and Linux storage of struct sockaddr 487 * and struct sockaddr_in6 are equal. 488 * 2. On Linux sa_family is the first member of all struct sockaddr. 489 */ 490 int 491 bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa, 492 socklen_t len) 493 { 494 struct l_sockaddr *kosa; 495 int bdom; 496 497 *lsa = NULL; 498 if (len < 2 || len > UCHAR_MAX) 499 return (EINVAL); 500 bdom = bsd_to_linux_domain(sa->sa_family); 501 if (bdom == -1) 502 return (EAFNOSUPPORT); 503 504 kosa = malloc(len, M_LINUX, M_WAITOK); 505 bcopy(sa, kosa, len); 506 kosa->sa_family = bdom; 507 *lsa = kosa; 508 return (0); 509 } 510 511 int 512 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap, 513 socklen_t *len) 514 { 515 struct sockaddr *sa; 516 struct l_sockaddr *kosa; 517 #ifdef INET6 518 struct sockaddr_in6 *sin6; 519 bool oldv6size; 520 #endif 521 char *name; 522 int salen, bdom, error, hdrlen, namelen; 523 524 if (*len < 2 || *len > UCHAR_MAX) 525 return (EINVAL); 526 527 salen = *len; 528 529 #ifdef INET6 530 oldv6size = false; 531 /* 532 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 533 * if it's a v4-mapped address, so reserve the proper space 534 * for it. 535 */ 536 if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { 537 salen += sizeof(uint32_t); 538 oldv6size = true; 539 } 540 #endif 541 542 kosa = malloc(salen, M_SONAME, M_WAITOK); 543 544 if ((error = copyin(osa, kosa, *len))) 545 goto out; 546 547 bdom = linux_to_bsd_domain(kosa->sa_family); 548 if (bdom == -1) { 549 error = EAFNOSUPPORT; 550 goto out; 551 } 552 553 #ifdef INET6 554 /* 555 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 556 * which lacks the scope id compared with RFC2553 one. If we detect 557 * the situation, reject the address and write a message to system log. 558 * 559 * Still accept addresses for which the scope id is not used. 560 */ 561 if (oldv6size) { 562 if (bdom == AF_INET6) { 563 sin6 = (struct sockaddr_in6 *)kosa; 564 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 565 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 566 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 567 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 568 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 569 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 570 sin6->sin6_scope_id = 0; 571 } else { 572 linux_msg(curthread, 573 "obsolete pre-RFC2553 sockaddr_in6 rejected"); 574 error = EINVAL; 575 goto out; 576 } 577 } else 578 salen -= sizeof(uint32_t); 579 } 580 #endif 581 if (bdom == AF_INET) { 582 if (salen < sizeof(struct sockaddr_in)) { 583 error = EINVAL; 584 goto out; 585 } 586 salen = sizeof(struct sockaddr_in); 587 } 588 589 if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { 590 hdrlen = offsetof(struct sockaddr_un, sun_path); 591 name = ((struct sockaddr_un *)kosa)->sun_path; 592 if (*name == '\0') { 593 /* 594 * Linux abstract namespace starts with a NULL byte. 595 * XXX We do not support abstract namespace yet. 596 */ 597 namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; 598 } else 599 namelen = strnlen(name, salen - hdrlen); 600 salen = hdrlen + namelen; 601 if (salen > sizeof(struct sockaddr_un)) { 602 error = ENAMETOOLONG; 603 goto out; 604 } 605 } 606 607 if (bdom == AF_NETLINK) { 608 if (salen < sizeof(struct sockaddr_nl)) { 609 error = EINVAL; 610 goto out; 611 } 612 salen = sizeof(struct sockaddr_nl); 613 } 614 615 sa = (struct sockaddr *)kosa; 616 sa->sa_family = bdom; 617 sa->sa_len = salen; 618 619 *sap = sa; 620 *len = salen; 621 return (0); 622 623 out: 624 free(kosa, M_SONAME); 625 return (error); 626 } 627 628 void 629 linux_dev_shm_create(void) 630 { 631 int error; 632 633 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &dev_shm_cdev, 634 &dev_shm_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0, "shm/.mountpoint"); 635 if (error != 0) { 636 printf("%s: failed to create device node, error %d\n", 637 __func__, error); 638 } 639 } 640 641 void 642 linux_dev_shm_destroy(void) 643 { 644 645 destroy_dev(dev_shm_cdev); 646 } 647 648 int 649 bsd_to_linux_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 650 size_t mapcnt, int no_value) 651 { 652 int bsd_mask, bsd_value, linux_mask, linux_value; 653 int linux_ret; 654 size_t i; 655 bool applied; 656 657 applied = false; 658 linux_ret = 0; 659 for (i = 0; i < mapcnt; ++i) { 660 bsd_mask = bitmap[i].bsd_mask; 661 bsd_value = bitmap[i].bsd_value; 662 if (bsd_mask == 0) 663 bsd_mask = bsd_value; 664 665 linux_mask = bitmap[i].linux_mask; 666 linux_value = bitmap[i].linux_value; 667 if (linux_mask == 0) 668 linux_mask = linux_value; 669 670 /* 671 * If a mask larger than just the value is set, we explicitly 672 * want to make sure that only this bit we mapped within that 673 * mask is set. 674 */ 675 if ((value & bsd_mask) == bsd_value) { 676 linux_ret = (linux_ret & ~linux_mask) | linux_value; 677 applied = true; 678 } 679 } 680 681 if (!applied) 682 return (no_value); 683 return (linux_ret); 684 } 685 686 int 687 linux_to_bsd_bits_(int value, struct bsd_to_linux_bitmap *bitmap, 688 size_t mapcnt, int no_value) 689 { 690 int bsd_mask, bsd_value, linux_mask, linux_value; 691 int bsd_ret; 692 size_t i; 693 bool applied; 694 695 applied = false; 696 bsd_ret = 0; 697 for (i = 0; i < mapcnt; ++i) { 698 bsd_mask = bitmap[i].bsd_mask; 699 bsd_value = bitmap[i].bsd_value; 700 if (bsd_mask == 0) 701 bsd_mask = bsd_value; 702 703 linux_mask = bitmap[i].linux_mask; 704 linux_value = bitmap[i].linux_value; 705 if (linux_mask == 0) 706 linux_mask = linux_value; 707 708 /* 709 * If a mask larger than just the value is set, we explicitly 710 * want to make sure that only this bit we mapped within that 711 * mask is set. 712 */ 713 if ((value & linux_mask) == linux_value) { 714 bsd_ret = (bsd_ret & ~bsd_mask) | bsd_value; 715 applied = true; 716 } 717 } 718 719 if (!applied) 720 return (no_value); 721 return (bsd_ret); 722 } 723 724 void 725 linux_to_bsd_poll_events(struct thread *td, int fd, short lev, 726 short *bev) 727 { 728 struct file *fp; 729 int error; 730 short bits = 0; 731 732 if (lev & LINUX_POLLIN) 733 bits |= POLLIN; 734 if (lev & LINUX_POLLPRI) 735 bits |= POLLPRI; 736 if (lev & LINUX_POLLOUT) 737 bits |= POLLOUT; 738 if (lev & LINUX_POLLERR) 739 bits |= POLLERR; 740 if (lev & LINUX_POLLHUP) 741 bits |= POLLHUP; 742 if (lev & LINUX_POLLNVAL) 743 bits |= POLLNVAL; 744 if (lev & LINUX_POLLRDNORM) 745 bits |= POLLRDNORM; 746 if (lev & LINUX_POLLRDBAND) 747 bits |= POLLRDBAND; 748 if (lev & LINUX_POLLWRBAND) 749 bits |= POLLWRBAND; 750 if (lev & LINUX_POLLWRNORM) 751 bits |= POLLWRNORM; 752 753 if (lev & LINUX_POLLRDHUP) { 754 /* 755 * It seems that the Linux silencly ignores POLLRDHUP 756 * on non-socket file descriptors unlike FreeBSD, where 757 * events bits is more strictly checked (POLLSTANDARD). 758 */ 759 error = fget_unlocked(td, fd, &cap_no_rights, &fp); 760 if (error == 0) { 761 /* 762 * XXX. On FreeBSD POLLRDHUP applies only to 763 * stream sockets. 764 */ 765 if (fp->f_type == DTYPE_SOCKET) 766 bits |= POLLRDHUP; 767 fdrop(fp, td); 768 } 769 } 770 771 if (lev & LINUX_POLLMSG) 772 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLMSG, events(%d)", lev); 773 if (lev & LINUX_POLLREMOVE) 774 LINUX_RATELIMIT_MSG_OPT1("unsupported POLLREMOVE, events(%d)", lev); 775 776 *bev = bits; 777 } 778 779 void 780 bsd_to_linux_poll_events(short bev, short *lev) 781 { 782 short bits = 0; 783 784 if (bev & POLLIN) 785 bits |= LINUX_POLLIN; 786 if (bev & POLLPRI) 787 bits |= LINUX_POLLPRI; 788 if (bev & (POLLOUT | POLLWRNORM)) 789 /* 790 * POLLWRNORM is equal to POLLOUT on FreeBSD, 791 * but not on Linux 792 */ 793 bits |= LINUX_POLLOUT; 794 if (bev & POLLERR) 795 bits |= LINUX_POLLERR; 796 if (bev & POLLHUP) 797 bits |= LINUX_POLLHUP; 798 if (bev & POLLNVAL) 799 bits |= LINUX_POLLNVAL; 800 if (bev & POLLRDNORM) 801 bits |= LINUX_POLLRDNORM; 802 if (bev & POLLRDBAND) 803 bits |= LINUX_POLLRDBAND; 804 if (bev & POLLWRBAND) 805 bits |= LINUX_POLLWRBAND; 806 if (bev & POLLRDHUP) 807 bits |= LINUX_POLLRDHUP; 808 809 *lev = bits; 810 } 811 812 bool 813 linux_use_real_ifname(const struct ifnet *ifp) 814 { 815 816 return (use_real_ifnames); 817 } 818