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