1 /*- 2 * Copyright (c) 2015 Dmitry Chagin 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <opt_inet6.h> 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/ctype.h> 35 #include <sys/jail.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/signalvar.h> 39 #include <sys/socket.h> 40 #include <sys/socketvar.h> 41 42 #include <net/if.h> 43 #include <net/if_var.h> 44 #include <net/if_dl.h> 45 #include <net/if_types.h> 46 47 #include <sys/un.h> 48 #include <netinet/in.h> 49 50 #include <compat/linux/linux.h> 51 #include <compat/linux/linux_common.h> 52 #include <compat/linux/linux_util.h> 53 54 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ); 55 56 static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = { 57 LINUX_SIGHUP, /* SIGHUP */ 58 LINUX_SIGINT, /* SIGINT */ 59 LINUX_SIGQUIT, /* SIGQUIT */ 60 LINUX_SIGILL, /* SIGILL */ 61 LINUX_SIGTRAP, /* SIGTRAP */ 62 LINUX_SIGABRT, /* SIGABRT */ 63 0, /* SIGEMT */ 64 LINUX_SIGFPE, /* SIGFPE */ 65 LINUX_SIGKILL, /* SIGKILL */ 66 LINUX_SIGBUS, /* SIGBUS */ 67 LINUX_SIGSEGV, /* SIGSEGV */ 68 LINUX_SIGSYS, /* SIGSYS */ 69 LINUX_SIGPIPE, /* SIGPIPE */ 70 LINUX_SIGALRM, /* SIGALRM */ 71 LINUX_SIGTERM, /* SIGTERM */ 72 LINUX_SIGURG, /* SIGURG */ 73 LINUX_SIGSTOP, /* SIGSTOP */ 74 LINUX_SIGTSTP, /* SIGTSTP */ 75 LINUX_SIGCONT, /* SIGCONT */ 76 LINUX_SIGCHLD, /* SIGCHLD */ 77 LINUX_SIGTTIN, /* SIGTTIN */ 78 LINUX_SIGTTOU, /* SIGTTOU */ 79 LINUX_SIGIO, /* SIGIO */ 80 LINUX_SIGXCPU, /* SIGXCPU */ 81 LINUX_SIGXFSZ, /* SIGXFSZ */ 82 LINUX_SIGVTALRM,/* SIGVTALRM */ 83 LINUX_SIGPROF, /* SIGPROF */ 84 LINUX_SIGWINCH, /* SIGWINCH */ 85 0, /* SIGINFO */ 86 LINUX_SIGUSR1, /* SIGUSR1 */ 87 LINUX_SIGUSR2 /* SIGUSR2 */ 88 }; 89 90 static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = { 91 SIGHUP, /* LINUX_SIGHUP */ 92 SIGINT, /* LINUX_SIGINT */ 93 SIGQUIT, /* LINUX_SIGQUIT */ 94 SIGILL, /* LINUX_SIGILL */ 95 SIGTRAP, /* LINUX_SIGTRAP */ 96 SIGABRT, /* LINUX_SIGABRT */ 97 SIGBUS, /* LINUX_SIGBUS */ 98 SIGFPE, /* LINUX_SIGFPE */ 99 SIGKILL, /* LINUX_SIGKILL */ 100 SIGUSR1, /* LINUX_SIGUSR1 */ 101 SIGSEGV, /* LINUX_SIGSEGV */ 102 SIGUSR2, /* LINUX_SIGUSR2 */ 103 SIGPIPE, /* LINUX_SIGPIPE */ 104 SIGALRM, /* LINUX_SIGALRM */ 105 SIGTERM, /* LINUX_SIGTERM */ 106 SIGBUS, /* LINUX_SIGSTKFLT */ 107 SIGCHLD, /* LINUX_SIGCHLD */ 108 SIGCONT, /* LINUX_SIGCONT */ 109 SIGSTOP, /* LINUX_SIGSTOP */ 110 SIGTSTP, /* LINUX_SIGTSTP */ 111 SIGTTIN, /* LINUX_SIGTTIN */ 112 SIGTTOU, /* LINUX_SIGTTOU */ 113 SIGURG, /* LINUX_SIGURG */ 114 SIGXCPU, /* LINUX_SIGXCPU */ 115 SIGXFSZ, /* LINUX_SIGXFSZ */ 116 SIGVTALRM, /* LINUX_SIGVTALARM */ 117 SIGPROF, /* LINUX_SIGPROF */ 118 SIGWINCH, /* LINUX_SIGWINCH */ 119 SIGIO, /* LINUX_SIGIO */ 120 /* 121 * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal 122 * to the first unused FreeBSD signal number. Since Linux supports 123 * signals from 1 to 64 we are ok here as our SIGRTMIN = 65. 124 */ 125 SIGRTMIN, /* LINUX_SIGPWR */ 126 SIGSYS /* LINUX_SIGSYS */ 127 }; 128 129 /* 130 * Map Linux RT signals to the FreeBSD RT signals. 131 */ 132 static inline int 133 linux_to_bsd_rt_signal(int sig) 134 { 135 136 return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN); 137 } 138 139 static inline int 140 bsd_to_linux_rt_signal(int sig) 141 { 142 143 return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN); 144 } 145 146 int 147 linux_to_bsd_signal(int sig) 148 { 149 150 KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("invalid Linux signal %d\n", sig)); 151 152 if (sig < LINUX_SIGRTMIN) 153 return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]); 154 155 return (linux_to_bsd_rt_signal(sig)); 156 } 157 158 int 159 bsd_to_linux_signal(int sig) 160 { 161 162 if (sig <= LINUX_SIGTBLSZ) 163 return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]); 164 if (sig == SIGRTMIN) 165 return (LINUX_SIGPWR); 166 167 return (bsd_to_linux_rt_signal(sig)); 168 } 169 170 int 171 linux_to_bsd_sigaltstack(int lsa) 172 { 173 int bsa = 0; 174 175 if (lsa & LINUX_SS_DISABLE) 176 bsa |= SS_DISABLE; 177 /* 178 * Linux ignores SS_ONSTACK flag for ss 179 * parameter while FreeBSD prohibits it. 180 */ 181 return (bsa); 182 } 183 184 int 185 bsd_to_linux_sigaltstack(int bsa) 186 { 187 int lsa = 0; 188 189 if (bsa & SS_DISABLE) 190 lsa |= LINUX_SS_DISABLE; 191 if (bsa & SS_ONSTACK) 192 lsa |= LINUX_SS_ONSTACK; 193 return (lsa); 194 } 195 196 void 197 linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) 198 { 199 int b, l; 200 201 SIGEMPTYSET(*bss); 202 for (l = 1; l <= LINUX_SIGRTMAX; l++) { 203 if (LINUX_SIGISMEMBER(*lss, l)) { 204 b = linux_to_bsd_signal(l); 205 if (b) 206 SIGADDSET(*bss, b); 207 } 208 } 209 } 210 211 void 212 bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) 213 { 214 int b, l; 215 216 LINUX_SIGEMPTYSET(*lss); 217 for (b = 1; b <= SIGRTMAX; b++) { 218 if (SIGISMEMBER(*bss, b)) { 219 l = bsd_to_linux_signal(b); 220 if (l) 221 LINUX_SIGADDSET(*lss, l); 222 } 223 } 224 } 225 226 /* 227 * Translate a Linux interface name to a FreeBSD interface name, 228 * and return the associated ifnet structure 229 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 230 * can point to the same buffer. 231 */ 232 struct ifnet * 233 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) 234 { 235 struct ifnet *ifp; 236 int len, unit; 237 char *ep; 238 int index; 239 bool is_eth, is_lo; 240 241 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 242 if (!isalpha(lxname[len]) || lxname[len] == '\0') 243 break; 244 if (len == 0 || len == LINUX_IFNAMSIZ) 245 return (NULL); 246 /* Linux loopback interface name is lo (not lo0) */ 247 is_lo = (len == 2 && strncmp(lxname, "lo", len) == 0); 248 unit = (int)strtoul(lxname + len, &ep, 10); 249 if ((ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) && 250 is_lo == 0) 251 return (NULL); 252 index = 0; 253 is_eth = (len == 3 && strncmp(lxname, "eth", len) == 0); 254 255 CURVNET_SET(TD_TO_VNET(td)); 256 IFNET_RLOCK(); 257 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 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 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) 264 break; 265 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 266 break; 267 if (is_lo && IFP_IS_LOOP(ifp)) 268 break; 269 } 270 IFNET_RUNLOCK(); 271 CURVNET_RESTORE(); 272 if (ifp != NULL && bsdname != NULL) 273 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); 274 return (ifp); 275 } 276 277 void 278 linux_ifflags(struct ifnet *ifp, short *flags) 279 { 280 unsigned short fl; 281 282 fl = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; 283 *flags = 0; 284 if (fl & IFF_UP) 285 *flags |= LINUX_IFF_UP; 286 if (fl & IFF_BROADCAST) 287 *flags |= LINUX_IFF_BROADCAST; 288 if (fl & IFF_DEBUG) 289 *flags |= LINUX_IFF_DEBUG; 290 if (fl & IFF_LOOPBACK) 291 *flags |= LINUX_IFF_LOOPBACK; 292 if (fl & IFF_POINTOPOINT) 293 *flags |= LINUX_IFF_POINTOPOINT; 294 if (fl & IFF_DRV_RUNNING) 295 *flags |= LINUX_IFF_RUNNING; 296 if (fl & IFF_NOARP) 297 *flags |= LINUX_IFF_NOARP; 298 if (fl & IFF_PROMISC) 299 *flags |= LINUX_IFF_PROMISC; 300 if (fl & IFF_ALLMULTI) 301 *flags |= LINUX_IFF_ALLMULTI; 302 if (fl & IFF_MULTICAST) 303 *flags |= LINUX_IFF_MULTICAST; 304 } 305 306 int 307 linux_ifhwaddr(struct ifnet *ifp, struct l_sockaddr *lsa) 308 { 309 struct ifaddr *ifa; 310 struct sockaddr_dl *sdl; 311 312 if (IFP_IS_LOOP(ifp)) { 313 bzero(lsa, sizeof(*lsa)); 314 lsa->sa_family = LINUX_ARPHRD_LOOPBACK; 315 return (0); 316 } 317 318 if (!IFP_IS_ETH(ifp)) 319 return (ENOENT); 320 321 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 322 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 323 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 324 (sdl->sdl_type == IFT_ETHER)) { 325 bzero(lsa, sizeof(*lsa)); 326 lsa->sa_family = LINUX_ARPHRD_ETHER; 327 bcopy(LLADDR(sdl), lsa->sa_data, LINUX_IFHWADDRLEN); 328 return (0); 329 } 330 } 331 332 return (ENOENT); 333 } 334 335 int 336 linux_to_bsd_domain(int domain) 337 { 338 339 switch (domain) { 340 case LINUX_AF_UNSPEC: 341 return (AF_UNSPEC); 342 case LINUX_AF_UNIX: 343 return (AF_LOCAL); 344 case LINUX_AF_INET: 345 return (AF_INET); 346 case LINUX_AF_INET6: 347 return (AF_INET6); 348 case LINUX_AF_AX25: 349 return (AF_CCITT); 350 case LINUX_AF_IPX: 351 return (AF_IPX); 352 case LINUX_AF_APPLETALK: 353 return (AF_APPLETALK); 354 } 355 return (-1); 356 } 357 358 int 359 bsd_to_linux_domain(int domain) 360 { 361 362 switch (domain) { 363 case AF_UNSPEC: 364 return (LINUX_AF_UNSPEC); 365 case AF_LOCAL: 366 return (LINUX_AF_UNIX); 367 case AF_INET: 368 return (LINUX_AF_INET); 369 case AF_INET6: 370 return (LINUX_AF_INET6); 371 case AF_CCITT: 372 return (LINUX_AF_AX25); 373 case AF_IPX: 374 return (LINUX_AF_IPX); 375 case AF_APPLETALK: 376 return (LINUX_AF_APPLETALK); 377 } 378 return (-1); 379 } 380 381 /* 382 * Based on the fact that: 383 * 1. Native and Linux storage of struct sockaddr 384 * and struct sockaddr_in6 are equal. 385 * 2. On Linux sa_family is the first member of all struct sockaddr. 386 */ 387 int 388 bsd_to_linux_sockaddr(const struct sockaddr *sa, struct l_sockaddr **lsa, 389 socklen_t len) 390 { 391 struct l_sockaddr *kosa; 392 int error, bdom; 393 394 *lsa = NULL; 395 if (len < 2 || len > UCHAR_MAX) 396 return (EINVAL); 397 398 kosa = malloc(len, M_SONAME, M_WAITOK); 399 bcopy(sa, kosa, len); 400 401 bdom = bsd_to_linux_domain(sa->sa_family); 402 if (bdom == -1) { 403 error = EAFNOSUPPORT; 404 goto out; 405 } 406 407 kosa->sa_family = bdom; 408 *lsa = kosa; 409 return (0); 410 411 out: 412 free(kosa, M_SONAME); 413 return (error); 414 } 415 416 int 417 linux_to_bsd_sockaddr(const struct l_sockaddr *osa, struct sockaddr **sap, 418 socklen_t *len) 419 { 420 struct sockaddr *sa; 421 struct l_sockaddr *kosa; 422 #ifdef INET6 423 struct sockaddr_in6 *sin6; 424 bool oldv6size; 425 #endif 426 char *name; 427 int salen, bdom, error, hdrlen, namelen; 428 429 if (*len < 2 || *len > UCHAR_MAX) 430 return (EINVAL); 431 432 salen = *len; 433 434 #ifdef INET6 435 oldv6size = false; 436 /* 437 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it 438 * if it's a v4-mapped address, so reserve the proper space 439 * for it. 440 */ 441 if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { 442 salen += sizeof(uint32_t); 443 oldv6size = true; 444 } 445 #endif 446 447 kosa = malloc(salen, M_SONAME, M_WAITOK); 448 449 if ((error = copyin(osa, kosa, *len))) 450 goto out; 451 452 bdom = linux_to_bsd_domain(kosa->sa_family); 453 if (bdom == -1) { 454 error = EAFNOSUPPORT; 455 goto out; 456 } 457 458 #ifdef INET6 459 /* 460 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, 461 * which lacks the scope id compared with RFC2553 one. If we detect 462 * the situation, reject the address and write a message to system log. 463 * 464 * Still accept addresses for which the scope id is not used. 465 */ 466 if (oldv6size) { 467 if (bdom == AF_INET6) { 468 sin6 = (struct sockaddr_in6 *)kosa; 469 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 470 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 471 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 472 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && 473 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 474 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { 475 sin6->sin6_scope_id = 0; 476 } else { 477 linux_msg(curthread, 478 "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); 479 error = EINVAL; 480 goto out; 481 } 482 } else 483 salen -= sizeof(uint32_t); 484 } 485 #endif 486 if (bdom == AF_INET) { 487 if (salen < sizeof(struct sockaddr_in)) { 488 error = EINVAL; 489 goto out; 490 } 491 salen = sizeof(struct sockaddr_in); 492 } 493 494 if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { 495 hdrlen = offsetof(struct sockaddr_un, sun_path); 496 name = ((struct sockaddr_un *)kosa)->sun_path; 497 if (*name == '\0') { 498 /* 499 * Linux abstract namespace starts with a NULL byte. 500 * XXX We do not support abstract namespace yet. 501 */ 502 namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; 503 } else 504 namelen = strnlen(name, salen - hdrlen); 505 salen = hdrlen + namelen; 506 if (salen > sizeof(struct sockaddr_un)) { 507 error = ENAMETOOLONG; 508 goto out; 509 } 510 } 511 512 sa = (struct sockaddr *)kosa; 513 sa->sa_family = bdom; 514 sa->sa_len = salen; 515 516 *sap = sa; 517 *len = salen; 518 return (0); 519 520 out: 521 free(kosa, M_SONAME); 522 return (error); 523 } 524