1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * dhcpcd - DHCP client daemon 4 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name> 5 * All rights reserved 6 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/ioctl.h> 32 #include <sys/socket.h> 33 34 #include "config.h" 35 36 #include <net/if.h> 37 #include <net/if_arp.h> 38 #include <netinet/in.h> 39 #ifdef AF_LINK 40 # include <net/if_dl.h> 41 # include <net/if_types.h> 42 # include <netinet/in_var.h> 43 # undef AF_PACKET /* Newer Illumos defines this */ 44 #endif 45 #ifdef AF_PACKET 46 # include <netpacket/packet.h> 47 #endif 48 #ifdef SIOCGIFMEDIA 49 # include <net/if_media.h> 50 #endif 51 #include <net/route.h> 52 53 #include <ctype.h> 54 #include <errno.h> 55 #include <ifaddrs.h> 56 #include <inttypes.h> 57 #include <fnmatch.h> 58 #include <stddef.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <unistd.h> 63 64 #include "common.h" 65 #include "dev.h" 66 #include "dhcp.h" 67 #include "dhcp6.h" 68 #include "if.h" 69 #include "if-options.h" 70 #include "ipv4.h" 71 #include "ipv4ll.h" 72 #include "ipv6nd.h" 73 #include "logerr.h" 74 75 #ifdef __sun 76 /* It has the ioctl, but the member is missing from the struct? 77 * No matter, our getifaddrs foo in if-sun.c will DTRT. */ 78 #undef SIOCGIFHWADDR 79 #endif 80 81 void 82 if_free(struct interface *ifp) 83 { 84 85 if (ifp == NULL) 86 return; 87 #ifdef IPV4LL 88 ipv4ll_free(ifp); 89 #endif 90 #ifdef INET 91 dhcp_free(ifp); 92 ipv4_free(ifp); 93 #endif 94 #ifdef DHCP6 95 dhcp6_free(ifp); 96 #endif 97 #ifdef INET6 98 ipv6nd_free(ifp); 99 ipv6_free(ifp); 100 #endif 101 rt_freeif(ifp); 102 free_options(ifp->ctx, ifp->options); 103 free(ifp); 104 } 105 106 int 107 if_opensockets(struct dhcpcd_ctx *ctx) 108 { 109 110 if (if_opensockets_os(ctx) == -1) 111 return -1; 112 113 /* We use this socket for some operations without INET. */ 114 ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 115 if (ctx->pf_inet_fd == -1) 116 return -1; 117 118 return 0; 119 } 120 121 void 122 if_closesockets(struct dhcpcd_ctx *ctx) 123 { 124 125 if (ctx->pf_inet_fd != -1) 126 close(ctx->pf_inet_fd); 127 128 if (ctx->priv) { 129 if_closesockets_os(ctx); 130 free(ctx->priv); 131 } 132 } 133 134 int 135 if_getflags(struct interface *ifp) 136 { 137 struct ifreq ifr = { .ifr_flags = 0 }; 138 139 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 140 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) 141 return -1; 142 ifp->flags = (unsigned int)ifr.ifr_flags; 143 return 0; 144 } 145 146 int 147 if_setflag(struct interface *ifp, short flag) 148 { 149 struct ifreq ifr = { .ifr_flags = 0 }; 150 short f; 151 152 if (if_getflags(ifp) == -1) 153 return -1; 154 155 f = (short)ifp->flags; 156 if ((f & flag) == flag) 157 return 0; 158 159 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 160 ifr.ifr_flags = f | flag; 161 if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1) 162 return -1; 163 164 ifp->flags = (unsigned int)ifr.ifr_flags; 165 return 0; 166 } 167 168 static int 169 if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname) 170 { 171 int i; 172 173 for (i = 0; i < ctx->ifcc; i++) { 174 if (strcmp(ctx->ifcv[i], ifname) == 0) 175 return 1; 176 } 177 return 0; 178 } 179 180 void 181 if_markaddrsstale(struct if_head *ifs) 182 { 183 struct interface *ifp; 184 185 TAILQ_FOREACH(ifp, ifs, next) { 186 #ifdef INET 187 ipv4_markaddrsstale(ifp); 188 #endif 189 #ifdef INET6 190 ipv6_markaddrsstale(ifp, 0); 191 #endif 192 } 193 } 194 195 void 196 if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, 197 struct ifaddrs **ifaddrs) 198 { 199 struct ifaddrs *ifa; 200 struct interface *ifp; 201 #ifdef INET 202 const struct sockaddr_in *addr, *net, *brd; 203 #endif 204 #ifdef INET6 205 struct sockaddr_in6 *sin6, *net6; 206 #endif 207 int addrflags; 208 209 for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { 210 if (ifa->ifa_addr == NULL) 211 continue; 212 if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL) 213 continue; 214 #ifdef HAVE_IFADDRS_ADDRFLAGS 215 addrflags = (int)ifa->ifa_addrflags; 216 #endif 217 switch(ifa->ifa_addr->sa_family) { 218 #ifdef INET 219 case AF_INET: 220 addr = (void *)ifa->ifa_addr; 221 net = (void *)ifa->ifa_netmask; 222 if (ifa->ifa_flags & IFF_POINTOPOINT) 223 brd = (void *)ifa->ifa_dstaddr; 224 else 225 brd = (void *)ifa->ifa_broadaddr; 226 #ifndef HAVE_IFADDRS_ADDRFLAGS 227 addrflags = if_addrflags(ifp, &addr->sin_addr, 228 ifa->ifa_name); 229 if (addrflags == -1) { 230 if (errno != EEXIST && errno != EADDRNOTAVAIL) 231 logerr("%s: if_addrflags", __func__); 232 continue; 233 } 234 #endif 235 ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, 236 &addr->sin_addr, &net->sin_addr, 237 brd ? &brd->sin_addr : NULL, addrflags, 0); 238 break; 239 #endif 240 #ifdef INET6 241 case AF_INET6: 242 sin6 = (void *)ifa->ifa_addr; 243 net6 = (void *)ifa->ifa_netmask; 244 245 #ifdef __KAME__ 246 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 247 /* Remove the scope from the address */ 248 sin6->sin6_addr.s6_addr[2] = 249 sin6->sin6_addr.s6_addr[3] = '\0'; 250 #endif 251 #ifndef HAVE_IFADDRS_ADDRFLAGS 252 addrflags = if_addrflags6(ifp, &sin6->sin6_addr, 253 ifa->ifa_name); 254 if (addrflags == -1) { 255 if (errno != EEXIST && errno != EADDRNOTAVAIL) 256 logerr("%s: if_addrflags6", __func__); 257 continue; 258 } 259 #endif 260 ipv6_handleifa(ctx, RTM_NEWADDR, ifs, 261 ifa->ifa_name, &sin6->sin6_addr, 262 ipv6_prefixlen(&net6->sin6_addr), addrflags, 0); 263 break; 264 #endif 265 } 266 } 267 268 freeifaddrs(*ifaddrs); 269 *ifaddrs = NULL; 270 } 271 272 void 273 if_deletestaleaddrs(struct if_head *ifs) 274 { 275 struct interface *ifp; 276 277 TAILQ_FOREACH(ifp, ifs, next) { 278 #ifdef INET 279 ipv4_deletestaleaddrs(ifp); 280 #endif 281 #ifdef INET6 282 ipv6_deletestaleaddrs(ifp); 283 #endif 284 } 285 } 286 287 bool 288 if_valid_hwaddr(const uint8_t *hwaddr, size_t hwlen) 289 { 290 size_t i; 291 bool all_zeros, all_ones; 292 293 all_zeros = all_ones = true; 294 for (i = 0; i < hwlen; i++) { 295 if (hwaddr[i] != 0x00) 296 all_zeros = false; 297 if (hwaddr[i] != 0xff) 298 all_ones = false; 299 if (!all_zeros && !all_ones) 300 return true; 301 } 302 return false; 303 } 304 305 struct if_head * 306 if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, 307 int argc, char * const *argv) 308 { 309 struct ifaddrs *ifa; 310 int i; 311 unsigned int active; 312 struct if_head *ifs; 313 struct interface *ifp; 314 struct if_spec spec; 315 bool if_noconf; 316 #ifdef AF_LINK 317 const struct sockaddr_dl *sdl; 318 #ifdef IFLR_ACTIVE 319 struct if_laddrreq iflr = { .flags = IFLR_PREFIX }; 320 int link_fd; 321 #endif 322 #elif AF_PACKET 323 const struct sockaddr_ll *sll; 324 #endif 325 #if defined(SIOCGIFPRIORITY) || defined(SIOCGIFHWADDR) 326 struct ifreq ifr; 327 #endif 328 329 if ((ifs = malloc(sizeof(*ifs))) == NULL) { 330 logerr(__func__); 331 return NULL; 332 } 333 if (getifaddrs(ifaddrs) == -1) { 334 logerr(__func__); 335 free(ifs); 336 return NULL; 337 } 338 TAILQ_INIT(ifs); 339 340 #ifdef IFLR_ACTIVE 341 link_fd = xsocket(PF_LINK, SOCK_DGRAM | SOCK_CLOEXEC, 0); 342 if (link_fd == -1) { 343 logerr(__func__); 344 free(ifs); 345 return NULL; 346 } 347 #endif 348 349 for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { 350 if (ifa->ifa_addr != NULL) { 351 #ifdef AF_LINK 352 if (ifa->ifa_addr->sa_family != AF_LINK) 353 continue; 354 #elif AF_PACKET 355 if (ifa->ifa_addr->sa_family != AF_PACKET) 356 continue; 357 #endif 358 } 359 if (if_nametospec(ifa->ifa_name, &spec) != 0) 360 continue; 361 362 /* It's possible for an interface to have >1 AF_LINK. 363 * For our purposes, we use the first one. */ 364 TAILQ_FOREACH(ifp, ifs, next) { 365 if (strcmp(ifp->name, spec.devname) == 0) 366 break; 367 } 368 if (ifp) 369 continue; 370 371 if (argc > 0) { 372 for (i = 0; i < argc; i++) { 373 if (strcmp(argv[i], spec.devname) == 0) 374 break; 375 } 376 active = (i == argc) ? IF_INACTIVE : IF_ACTIVE_USER; 377 } else { 378 /* -1 means we're discovering against a specific 379 * interface, but we still need the below rules 380 * to apply. */ 381 if (argc == -1 && strcmp(argv[0], spec.devname) != 0) 382 continue; 383 active = ctx->options & DHCPCD_INACTIVE ? 384 IF_INACTIVE: IF_ACTIVE_USER; 385 } 386 387 for (i = 0; i < ctx->ifdc; i++) 388 if (fnmatch(ctx->ifdv[i], spec.devname, 0) == 0) 389 break; 390 if (i < ctx->ifdc) 391 active = IF_INACTIVE; 392 for (i = 0; i < ctx->ifc; i++) 393 if (fnmatch(ctx->ifv[i], spec.devname, 0) == 0) 394 break; 395 if (ctx->ifc && i == ctx->ifc) 396 active = IF_INACTIVE; 397 for (i = 0; i < ctx->ifac; i++) 398 if (fnmatch(ctx->ifav[i], spec.devname, 0) == 0) 399 break; 400 if (ctx->ifac && i == ctx->ifac) 401 active = IF_INACTIVE; 402 403 #ifdef PLUGIN_DEV 404 /* Ensure that the interface name has settled */ 405 if (!dev_initialized(ctx, spec.devname)) 406 continue; 407 #endif 408 409 if (if_vimaster(ctx, spec.devname) == 1) { 410 logfunc_t *logfunc = argc != 0 ? logerrx : logdebugx; 411 logfunc("%s: is a Virtual Interface Master, skipping", 412 spec.devname); 413 continue; 414 } 415 416 if_noconf = ((argc == 0 || argc == -1) && ctx->ifac == 0 && 417 !if_hasconf(ctx, spec.devname)); 418 419 /* Don't allow loopback or pointopoint unless explicit. 420 * Don't allow some reserved interface names unless explicit. */ 421 if (if_noconf) { 422 if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT) || 423 if_ignore(ctx, spec.devname)) 424 active = IF_INACTIVE; 425 } 426 427 ifp = calloc(1, sizeof(*ifp)); 428 if (ifp == NULL) { 429 logerr(__func__); 430 break; 431 } 432 ifp->ctx = ctx; 433 strlcpy(ifp->name, spec.devname, sizeof(ifp->name)); 434 ifp->flags = ifa->ifa_flags; 435 436 if (ifa->ifa_addr != NULL) { 437 #ifdef AF_LINK 438 sdl = (const void *)ifa->ifa_addr; 439 440 #ifdef IFLR_ACTIVE 441 /* We need to check for active address */ 442 strlcpy(iflr.iflr_name, ifp->name, 443 sizeof(iflr.iflr_name)); 444 memcpy(&iflr.addr, ifa->ifa_addr, 445 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 446 iflr.flags = IFLR_PREFIX; 447 iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY; 448 if (ioctl(link_fd, SIOCGLIFADDR, &iflr) == -1 || 449 !(iflr.flags & IFLR_ACTIVE)) 450 { 451 if_free(ifp); 452 continue; 453 } 454 #endif 455 456 ifp->index = sdl->sdl_index; 457 switch(sdl->sdl_type) { 458 #ifdef IFT_BRIDGE 459 case IFT_BRIDGE: /* FALLTHROUGH */ 460 #endif 461 #ifdef IFT_PROPVIRTUAL 462 case IFT_PROPVIRTUAL: /* FALLTHROUGH */ 463 #endif 464 #ifdef IFT_TUNNEL 465 case IFT_TUNNEL: /* FALLTHROUGH */ 466 #endif 467 case IFT_PPP: 468 /* Don't allow unless explicit */ 469 if (if_noconf) { 470 logdebugx("%s: ignoring due to" 471 " interface type and" 472 " no config", 473 ifp->name); 474 active = IF_INACTIVE; 475 } 476 __fallthrough; /* appease gcc */ 477 /* FALLTHROUGH */ 478 #ifdef IFT_L2VLAN 479 case IFT_L2VLAN: /* FALLTHROUGH */ 480 #endif 481 #ifdef IFT_L3IPVLAN 482 case IFT_L3IPVLAN: /* FALLTHROUGH */ 483 #endif 484 case IFT_ETHER: 485 ifp->family = ARPHRD_ETHER; 486 break; 487 #ifdef IFT_IEEE1394 488 case IFT_IEEE1394: 489 ifp->family = ARPHRD_IEEE1394; 490 break; 491 #endif 492 #ifdef IFT_INFINIBAND 493 case IFT_INFINIBAND: 494 ifp->family = ARPHRD_INFINIBAND; 495 break; 496 #endif 497 default: 498 /* Don't allow unless explicit */ 499 if (if_noconf) 500 active = IF_INACTIVE; 501 if (active) 502 logwarnx("%s: unsupported" 503 " interface type 0x%.2x", 504 ifp->name, sdl->sdl_type); 505 /* Pretend it's ethernet */ 506 ifp->family = ARPHRD_ETHER; 507 break; 508 } 509 ifp->hwlen = sdl->sdl_alen; 510 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 511 #elif AF_PACKET 512 sll = (const void *)ifa->ifa_addr; 513 ifp->index = (unsigned int)sll->sll_ifindex; 514 ifp->family = sll->sll_hatype; 515 ifp->hwlen = sll->sll_halen; 516 if (ifp->hwlen != 0) 517 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 518 #endif 519 } 520 #ifdef SIOCGIFHWADDR 521 else { 522 /* This is a huge bug in getifaddrs(3) as there 523 * is no reason why this can't be returned in 524 * ifa_addr. */ 525 memset(&ifr, 0, sizeof(ifr)); 526 strlcpy(ifr.ifr_name, ifa->ifa_name, 527 sizeof(ifr.ifr_name)); 528 if (ioctl(ctx->pf_inet_fd, SIOCGIFHWADDR, &ifr) == -1) 529 logerr("%s: SIOCGIFHWADDR", ifa->ifa_name); 530 ifp->family = ifr.ifr_hwaddr.sa_family; 531 if (ioctl(ctx->pf_inet_fd, SIOCGIFINDEX, &ifr) == -1) 532 logerr("%s: SIOCGIFINDEX", ifa->ifa_name); 533 ifp->index = (unsigned int)ifr.ifr_ifindex; 534 } 535 #endif 536 537 /* Ensure hardware address is valid. */ 538 if (!if_valid_hwaddr(ifp->hwaddr, ifp->hwlen)) 539 ifp->hwlen = 0; 540 541 /* We only work on ethernet by default */ 542 if (ifp->family != ARPHRD_ETHER) { 543 if ((argc == 0 || argc == -1) && 544 ctx->ifac == 0 && !if_hasconf(ctx, ifp->name)) 545 active = IF_INACTIVE; 546 switch (ifp->family) { 547 case ARPHRD_IEEE1394: 548 case ARPHRD_INFINIBAND: 549 #ifdef ARPHRD_LOOPBACK 550 case ARPHRD_LOOPBACK: 551 #endif 552 #ifdef ARPHRD_PPP 553 case ARPHRD_PPP: 554 #endif 555 #ifdef ARPHRD_NONE 556 case ARPHRD_NONE: 557 #endif 558 /* We don't warn for supported families */ 559 break; 560 561 /* IFT already checked */ 562 #ifndef AF_LINK 563 default: 564 if (active) 565 logwarnx("%s: unsupported" 566 " interface family 0x%.2x", 567 ifp->name, ifp->family); 568 break; 569 #endif 570 } 571 } 572 573 if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) { 574 /* Handle any platform init for the interface */ 575 if (active != IF_INACTIVE && if_init(ifp) == -1) { 576 logerr("%s: if_init", ifp->name); 577 if_free(ifp); 578 continue; 579 } 580 } 581 582 ifp->vlanid = if_vlanid(ifp); 583 584 #ifdef SIOCGIFPRIORITY 585 /* Respect the interface priority */ 586 memset(&ifr, 0, sizeof(ifr)); 587 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 588 if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0) 589 ifp->metric = (unsigned int)ifr.ifr_metric; 590 if_getssid(ifp); 591 #else 592 /* We reserve the 100 range for virtual interfaces, if and when 593 * we can work them out. */ 594 ifp->metric = 200 + ifp->index; 595 if (if_getssid(ifp) != -1) { 596 ifp->wireless = true; 597 ifp->metric += 100; 598 } 599 #endif 600 601 ifp->active = active; 602 if (ifp->active) 603 ifp->carrier = if_carrier(ifp); 604 else 605 ifp->carrier = LINK_UNKNOWN; 606 TAILQ_INSERT_TAIL(ifs, ifp, next); 607 } 608 609 #ifdef IFLR_ACTIVE 610 close(link_fd); 611 #endif 612 return ifs; 613 } 614 615 /* Decode bge0:1 as dev = bge, ppa = 0 and lun = 1 */ 616 int 617 if_nametospec(const char *ifname, struct if_spec *spec) 618 { 619 char *ep; 620 int e; 621 622 if (ifname == NULL || *ifname == '\0' || 623 strlcpy(spec->ifname, ifname, sizeof(spec->ifname)) >= 624 sizeof(spec->ifname) || 625 strlcpy(spec->drvname, ifname, sizeof(spec->drvname)) >= 626 sizeof(spec->drvname)) 627 { 628 errno = EINVAL; 629 return -1; 630 } 631 ep = strchr(spec->drvname, ':'); 632 if (ep) { 633 spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e); 634 if (e != 0) { 635 errno = e; 636 return -1; 637 } 638 *ep-- = '\0'; 639 } else { 640 spec->lun = -1; 641 ep = spec->drvname + strlen(spec->drvname) - 1; 642 } 643 strlcpy(spec->devname, spec->drvname, sizeof(spec->devname)); 644 while (ep > spec->drvname && isdigit((int)*ep)) 645 ep--; 646 if (*ep++ == ':') { 647 errno = EINVAL; 648 return -1; 649 } 650 spec->ppa = (int)strtoi(ep, NULL, 10, 0, INT_MAX, &e); 651 if (e != 0) 652 spec->ppa = -1; 653 *ep = '\0'; 654 655 return 0; 656 } 657 658 static struct interface * 659 if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name) 660 { 661 662 if (ifaces != NULL) { 663 struct if_spec spec; 664 struct interface *ifp; 665 666 if (name && if_nametospec(name, &spec) == -1) 667 return NULL; 668 669 TAILQ_FOREACH(ifp, ifaces, next) { 670 if ((name && strcmp(ifp->name, spec.devname) == 0) || 671 (!name && ifp->index == idx)) 672 return ifp; 673 } 674 } 675 676 errno = ENXIO; 677 return NULL; 678 } 679 680 struct interface * 681 if_find(struct if_head *ifaces, const char *name) 682 { 683 684 return if_findindexname(ifaces, 0, name); 685 } 686 687 struct interface * 688 if_findindex(struct if_head *ifaces, unsigned int idx) 689 { 690 691 return if_findindexname(ifaces, idx, NULL); 692 } 693 694 struct interface * 695 if_loopback(struct dhcpcd_ctx *ctx) 696 { 697 struct interface *ifp; 698 699 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 700 if (ifp->flags & IFF_LOOPBACK) 701 return ifp; 702 } 703 return NULL; 704 } 705 706 int 707 if_domtu(const struct interface *ifp, short int mtu) 708 { 709 int r; 710 struct ifreq ifr; 711 712 #ifdef __sun 713 if (mtu == 0) 714 return if_mtu_os(ifp); 715 #endif 716 717 memset(&ifr, 0, sizeof(ifr)); 718 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 719 ifr.ifr_mtu = mtu; 720 r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 721 if (r == -1) 722 return -1; 723 return ifr.ifr_mtu; 724 } 725 726 #ifdef ALIAS_ADDR 727 int 728 if_makealias(char *alias, size_t alias_len, const char *ifname, int lun) 729 { 730 731 if (lun == 0) 732 return strlcpy(alias, ifname, alias_len); 733 return snprintf(alias, alias_len, "%s:%u", ifname, lun); 734 } 735 #endif 736 737 struct interface * 738 if_findifpfromcmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, int *hoplimit) 739 { 740 struct cmsghdr *cm; 741 unsigned int ifindex = 0; 742 struct interface *ifp; 743 #ifdef INET 744 #ifdef IP_RECVIF 745 struct sockaddr_dl sdl; 746 #else 747 struct in_pktinfo ipi; 748 #endif 749 #endif 750 #ifdef INET6 751 struct in6_pktinfo ipi6; 752 #else 753 UNUSED(hoplimit); 754 #endif 755 756 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(msg); 757 cm; 758 cm = (struct cmsghdr *)CMSG_NXTHDR(msg, cm)) 759 { 760 #ifdef INET 761 if (cm->cmsg_level == IPPROTO_IP) { 762 switch(cm->cmsg_type) { 763 #ifdef IP_RECVIF 764 case IP_RECVIF: 765 if (cm->cmsg_len < 766 offsetof(struct sockaddr_dl, sdl_index) + 767 sizeof(sdl.sdl_index)) 768 continue; 769 memcpy(&sdl, CMSG_DATA(cm), 770 MIN(sizeof(sdl), cm->cmsg_len)); 771 ifindex = sdl.sdl_index; 772 break; 773 #else 774 case IP_PKTINFO: 775 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi))) 776 continue; 777 memcpy(&ipi, CMSG_DATA(cm), sizeof(ipi)); 778 ifindex = (unsigned int)ipi.ipi_ifindex; 779 break; 780 #endif 781 } 782 } 783 #endif 784 #ifdef INET6 785 if (cm->cmsg_level == IPPROTO_IPV6) { 786 switch(cm->cmsg_type) { 787 case IPV6_PKTINFO: 788 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi6))) 789 continue; 790 memcpy(&ipi6, CMSG_DATA(cm), sizeof(ipi6)); 791 ifindex = (unsigned int)ipi6.ipi6_ifindex; 792 break; 793 case IPV6_HOPLIMIT: 794 if (cm->cmsg_len != CMSG_LEN(sizeof(int))) 795 continue; 796 if (hoplimit == NULL) 797 break; 798 memcpy(hoplimit, CMSG_DATA(cm), sizeof(int)); 799 break; 800 } 801 } 802 #endif 803 } 804 805 /* Find the receiving interface */ 806 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 807 if (ifp->index == ifindex) 808 break; 809 } 810 if (ifp == NULL) 811 errno = ESRCH; 812 return ifp; 813 } 814 815 int 816 xsocket(int domain, int type, int protocol) 817 { 818 int s; 819 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 820 int xflags, xtype = type; 821 #endif 822 #ifdef SO_RERROR 823 int on; 824 #endif 825 826 #ifndef HAVE_SOCK_CLOEXEC 827 if (xtype & SOCK_CLOEXEC) 828 type &= ~SOCK_CLOEXEC; 829 #endif 830 #ifndef HAVE_SOCK_NONBLOCK 831 if (xtype & SOCK_NONBLOCK) 832 type &= ~SOCK_NONBLOCK; 833 #endif 834 835 if ((s = socket(domain, type, protocol)) == -1) 836 return -1; 837 838 #ifndef HAVE_SOCK_CLOEXEC 839 if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 || 840 fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)) 841 goto out; 842 #endif 843 #ifndef HAVE_SOCK_NONBLOCK 844 if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 || 845 fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)) 846 goto out; 847 #endif 848 849 #ifdef SO_RERROR 850 /* Tell recvmsg(2) to return ENOBUFS if the receiving socket overflows. */ 851 on = 1; 852 if (setsockopt(s, SOL_SOCKET, SO_RERROR, &on, sizeof(on)) == -1) 853 logerr("%s: SO_RERROR", __func__); 854 #endif 855 856 return s; 857 858 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 859 out: 860 close(s); 861 return -1; 862 #endif 863 } 864