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