if.c revision 1.1.1.4
1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2017 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 75void 76if_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->options); 89 free(ifp); 90} 91 92int 93if_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 113void 114if_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 130int 131if_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 159int 160if_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 181static int 182if_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 193static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, 194 struct ifaddrs *ifaddrs) 195{ 196 struct ifaddrs *ifa; 197 struct interface *ifp; 198#ifdef INET 199 const struct sockaddr_in *addr, *net, *brd; 200#endif 201#ifdef INET6 202 struct sockaddr_in6 *sin6, *net6; 203#endif 204 int addrflags; 205 206 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 207 if (ifa->ifa_addr == NULL) 208 continue; 209 if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL) 210 continue; 211#ifdef HAVE_IFADDRS_ADDRFLAGS 212 addrflags = (int)ifa->ifa_addrflags; 213#endif 214 switch(ifa->ifa_addr->sa_family) { 215#ifdef INET 216 case AF_INET: 217 addr = (void *)ifa->ifa_addr; 218 net = (void *)ifa->ifa_netmask; 219 if (ifa->ifa_flags & IFF_POINTOPOINT) 220 brd = (void *)ifa->ifa_dstaddr; 221 else 222 brd = (void *)ifa->ifa_broadaddr; 223#ifndef HAVE_IFADDRS_ADDRFLAGS 224 addrflags = if_addrflags(ifp, &addr->sin_addr, 225 ifa->ifa_name); 226 if (addrflags == -1) { 227 if (errno != EEXIST) 228 logerr("%s: if_addrflags: %s", 229 __func__, 230 inet_ntoa(addr->sin_addr)); 231 continue; 232 } 233#endif 234 ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, 235 &addr->sin_addr, &net->sin_addr, 236 brd ? &brd->sin_addr : NULL, addrflags); 237 break; 238#endif 239#ifdef INET6 240 case AF_INET6: 241 sin6 = (void *)ifa->ifa_addr; 242 net6 = (void *)ifa->ifa_netmask; 243#ifdef __KAME__ 244 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 245 /* Remove the scope from the address */ 246 sin6->sin6_addr.s6_addr[2] = 247 sin6->sin6_addr.s6_addr[3] = '\0'; 248#endif 249#ifndef HAVE_IFADDRS_ADDRFLAGS 250 addrflags = if_addrflags6(ifp, &sin6->sin6_addr, 251 ifa->ifa_name); 252 if (addrflags == -1) { 253 if (errno != EEXIST) 254 logerr("%s: if_addrflags6", __func__); 255 continue; 256 } 257#endif 258 ipv6_handleifa(ctx, RTM_NEWADDR, ifs, 259 ifa->ifa_name, &sin6->sin6_addr, 260 ipv6_prefixlen(&net6->sin6_addr), addrflags); 261 break; 262#endif 263 } 264 } 265} 266 267bool 268if_valid_hwaddr(const uint8_t *hwaddr, size_t hwlen) 269{ 270 size_t i; 271 bool all_zeros, all_ones; 272 273 all_zeros = all_ones = true; 274 for (i = 0; i < hwlen; i++) { 275 if (hwaddr[i] != 0x00) 276 all_zeros = false; 277 if (hwaddr[i] != 0xff) 278 all_ones = false; 279 if (!all_zeros && !all_ones) 280 return true; 281 } 282 return false; 283} 284 285struct if_head * 286if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) 287{ 288 struct ifaddrs *ifaddrs, *ifa; 289 int i; 290 unsigned int active; 291 struct if_head *ifs; 292 struct interface *ifp; 293 struct if_spec spec; 294#ifdef AF_LINK 295 const struct sockaddr_dl *sdl; 296#ifdef SIOCGIFPRIORITY 297 struct ifreq ifr; 298#endif 299#ifdef IFLR_ACTIVE 300 struct if_laddrreq iflr; 301#endif 302 303#ifdef IFLR_ACTIVE 304 memset(&iflr, 0, sizeof(iflr)); 305#endif 306#elif AF_PACKET 307 const struct sockaddr_ll *sll; 308#endif 309 310 if (getifaddrs(&ifaddrs) == -1) 311 return NULL; 312 313 if ((ifs = malloc(sizeof(*ifs))) == NULL) 314 goto failed; 315 TAILQ_INIT(ifs); 316 317 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 318 if (ifa->ifa_addr != NULL) { 319#ifdef AF_LINK 320 if (ifa->ifa_addr->sa_family != AF_LINK) 321 continue; 322#elif AF_PACKET 323 if (ifa->ifa_addr->sa_family != AF_PACKET) 324 continue; 325#endif 326 } 327 if (if_nametospec(ifa->ifa_name, &spec) != 0) 328 continue; 329 330 /* It's possible for an interface to have >1 AF_LINK. 331 * For our purposes, we use the first one. */ 332 TAILQ_FOREACH(ifp, ifs, next) { 333 if (strcmp(ifp->name, spec.devname) == 0) 334 break; 335 } 336 if (ifp) 337 continue; 338 339 if (argc > 0) { 340 for (i = 0; i < argc; i++) { 341 if (strcmp(argv[i], spec.devname) == 0) 342 break; 343 } 344 active = (i == argc) ? IF_INACTIVE : IF_ACTIVE_USER; 345 } else { 346 /* -1 means we're discovering against a specific 347 * interface, but we still need the below rules 348 * to apply. */ 349 if (argc == -1 && strcmp(argv[0], spec.devname) != 0) 350 continue; 351 active = ctx->options & DHCPCD_INACTIVE ? 352 IF_INACTIVE: IF_ACTIVE_USER; 353 } 354 355 for (i = 0; i < ctx->ifdc; i++) 356 if (!fnmatch(ctx->ifdv[i], spec.devname, 0)) 357 break; 358 if (i < ctx->ifdc) 359 active = IF_INACTIVE; 360 for (i = 0; i < ctx->ifac; i++) 361 if (!fnmatch(ctx->ifav[i], spec.devname, 0)) 362 break; 363 if (ctx->ifac && i == ctx->ifac) 364 active = IF_INACTIVE; 365 366#ifdef PLUGIN_DEV 367 /* Ensure that the interface name has settled */ 368 if (!dev_initialized(ctx, spec.devname)) 369 continue; 370#endif 371 372 /* Don't allow loopback or pointopoint unless explicit */ 373 if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) { 374 if ((argc == 0 || argc == -1) && 375 ctx->ifac == 0 && !if_hasconf(ctx, spec.devname)) 376 active = IF_INACTIVE; 377 } 378 379 if (if_vimaster(ctx, spec.devname) == 1) { 380 logfunc_t *logfunc = argc != 0 ? logerrx : logdebugx; 381 logfunc("%s: is a Virtual Interface Master, skipping", 382 spec.devname); 383 continue; 384 } 385 386 ifp = calloc(1, sizeof(*ifp)); 387 if (ifp == NULL) { 388 logerr(__func__); 389 break; 390 } 391 ifp->ctx = ctx; 392 strlcpy(ifp->name, spec.devname, sizeof(ifp->name)); 393 ifp->flags = ifa->ifa_flags; 394 395 if (ifa->ifa_addr != NULL) { 396#ifdef AF_LINK 397 sdl = (const void *)ifa->ifa_addr; 398 399#ifdef IFLR_ACTIVE 400 /* We need to check for active address */ 401 strlcpy(iflr.iflr_name, ifp->name, 402 sizeof(iflr.iflr_name)); 403 memcpy(&iflr.addr, ifa->ifa_addr, 404 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 405 iflr.flags = IFLR_PREFIX; 406 iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY; 407 if (ioctl(ctx->pf_link_fd, SIOCGLIFADDR, &iflr) == -1 || 408 !(iflr.flags & IFLR_ACTIVE)) 409 { 410 if_free(ifp); 411 continue; 412 } 413#endif 414 415 ifp->index = sdl->sdl_index; 416 switch(sdl->sdl_type) { 417#ifdef IFT_BRIDGE 418 case IFT_BRIDGE: /* FALLTHROUGH */ 419#endif 420#ifdef IFT_PPP 421 case IFT_PPP: /* FALLTHROUGH */ 422#endif 423#ifdef IFT_PROPVIRTUAL 424 case IFT_PROPVIRTUAL: /* FALLTHROUGH */ 425#endif 426#if defined(IFT_BRIDGE) || defined(IFT_PPP) || defined(IFT_PROPVIRTUAL) 427 /* Don't allow unless explicit */ 428 if ((argc == 0 || argc == -1) && 429 ctx->ifac == 0 && active && 430 !if_hasconf(ctx, ifp->name)) 431 { 432 logdebugx("%s: ignoring due to" 433 " interface type and" 434 " no config", 435 ifp->name); 436 active = IF_INACTIVE; 437 } 438 /* FALLTHROUGH */ 439#endif 440#ifdef IFT_L2VLAN 441 case IFT_L2VLAN: /* FALLTHROUGH */ 442#endif 443#ifdef IFT_L3IPVLAN 444 case IFT_L3IPVLAN: /* FALLTHROUGH */ 445#endif 446 case IFT_ETHER: 447 ifp->family = ARPHRD_ETHER; 448 break; 449#ifdef IFT_IEEE1394 450 case IFT_IEEE1394: 451 ifp->family = ARPHRD_IEEE1394; 452 break; 453#endif 454#ifdef IFT_INFINIBAND 455 case IFT_INFINIBAND: 456 ifp->family = ARPHRD_INFINIBAND; 457 break; 458#endif 459 default: 460 /* Don't allow unless explicit */ 461 if ((argc == 0 || argc == -1) && 462 ctx->ifac == 0 && 463 !if_hasconf(ctx, ifp->name)) 464 active = IF_INACTIVE; 465 if (active) 466 logwarnx("%s: unsupported" 467 " interface type %.2x", 468 ifp->name, sdl->sdl_type); 469 /* Pretend it's ethernet */ 470 ifp->family = ARPHRD_ETHER; 471 break; 472 } 473 ifp->hwlen = sdl->sdl_alen; 474 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 475#elif AF_PACKET 476 sll = (const void *)ifa->ifa_addr; 477 ifp->index = (unsigned int)sll->sll_ifindex; 478 ifp->family = sll->sll_hatype; 479 ifp->hwlen = sll->sll_halen; 480 if (ifp->hwlen != 0) 481 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 482#endif 483 } 484#ifdef __linux__ 485 /* PPP addresses on Linux don't have hardware addresses */ 486 else 487 ifp->index = if_nametoindex(ifp->name); 488#endif 489 490 /* Ensure hardware address is valid. */ 491 if (!if_valid_hwaddr(ifp->hwaddr, ifp->hwlen)) 492 ifp->hwlen = 0; 493 494 /* We only work on ethernet by default */ 495 if (ifp->family != ARPHRD_ETHER) { 496 if ((argc == 0 || argc == -1) && 497 ctx->ifac == 0 && !if_hasconf(ctx, ifp->name)) 498 active = IF_INACTIVE; 499 switch (ifp->family) { 500 case ARPHRD_IEEE1394: 501 case ARPHRD_INFINIBAND: 502#ifdef ARPHRD_LOOPBACK 503 case ARPHRD_LOOPBACK: 504#endif 505#ifdef ARPHRD_PPP 506 case ARPHRD_PPP: 507#endif 508 /* We don't warn for supported families */ 509 break; 510 511/* IFT already checked */ 512#ifndef AF_LINK 513 default: 514 if (active) 515 logwarnx("%s: unsupported" 516 " interface family %.2x", 517 ifp->name, ifp->family); 518 break; 519#endif 520 } 521 } 522 523 if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) { 524 /* Handle any platform init for the interface */ 525 if (active != IF_INACTIVE && if_init(ifp) == -1) { 526 logerr("%s: if_init", ifp->name); 527 if_free(ifp); 528 continue; 529 } 530 531 /* Ensure that the MTU is big enough for DHCP */ 532 if (if_getmtu(ifp) < MTU_MIN && active && 533 if_setmtu(ifp, MTU_MIN) == -1) 534 { 535 logerr("%s: if_setmtu", ifp->name); 536 if_free(ifp); 537 continue; 538 } 539 } 540 541 ifp->vlanid = if_vlanid(ifp); 542 543#ifdef SIOCGIFPRIORITY 544 /* Respect the interface priority */ 545 memset(&ifr, 0, sizeof(ifr)); 546 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 547 if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0) 548 ifp->metric = (unsigned int)ifr.ifr_metric; 549 if_getssid(ifp); 550#else 551 /* We reserve the 100 range for virtual interfaces, if and when 552 * we can work them out. */ 553 ifp->metric = 200 + ifp->index; 554 if (if_getssid(ifp) != -1) { 555 ifp->wireless = 1; 556 ifp->metric += 100; 557 } 558#endif 559 560 ifp->active = active; 561 if (ifp->active) 562 ifp->carrier = if_carrier(ifp); 563 else 564 ifp->carrier = LINK_UNKNOWN; 565 TAILQ_INSERT_TAIL(ifs, ifp, next); 566 } 567 568 if_learnaddrs(ctx, ifs, ifaddrs); 569failed: 570 freeifaddrs(ifaddrs); 571 return ifs; 572} 573 574/* Decode bge0:1 as dev = bge, ppa = 0 and lun = 1 */ 575int 576if_nametospec(const char *ifname, struct if_spec *spec) 577{ 578 char *ep; 579 int e; 580 581 if (ifname == NULL || *ifname == '\0' || 582 strlcpy(spec->ifname, ifname, sizeof(spec->ifname)) >= 583 sizeof(spec->ifname) || 584 strlcpy(spec->drvname, ifname, sizeof(spec->drvname)) >= 585 sizeof(spec->drvname)) 586 { 587 errno = EINVAL; 588 return -1; 589 } 590 ep = strchr(spec->drvname, ':'); 591 if (ep) { 592 spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e); 593 if (e != 0) { 594 errno = e; 595 return -1; 596 } 597 *ep-- = '\0'; 598 } else { 599 spec->lun = -1; 600 ep = spec->drvname + strlen(spec->drvname) - 1; 601 } 602 strlcpy(spec->devname, spec->drvname, sizeof(spec->devname)); 603 while (ep > spec->drvname && isdigit((int)*ep)) 604 ep--; 605 if (*ep++ == ':') { 606 errno = EINVAL; 607 return -1; 608 } 609 spec->ppa = (int)strtoi(ep, NULL, 10, 0, INT_MAX, &e); 610 if (e != 0) 611 spec->ppa = -1; 612 *ep = '\0'; 613 614 return 0; 615} 616 617static struct interface * 618if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name) 619{ 620 621 if (ifaces != NULL) { 622 struct if_spec spec; 623 struct interface *ifp; 624 625 if (name && if_nametospec(name, &spec) == -1) 626 return NULL; 627 628 TAILQ_FOREACH(ifp, ifaces, next) { 629 if ((name && strcmp(ifp->name, spec.devname) == 0) || 630 (!name && ifp->index == idx)) 631 return ifp; 632 } 633 } 634 635 errno = ENXIO; 636 return NULL; 637} 638 639struct interface * 640if_find(struct if_head *ifaces, const char *name) 641{ 642 643 return if_findindexname(ifaces, 0, name); 644} 645 646struct interface * 647if_findindex(struct if_head *ifaces, unsigned int idx) 648{ 649 650 return if_findindexname(ifaces, idx, NULL); 651} 652 653struct interface * 654if_loopback(struct dhcpcd_ctx *ctx) 655{ 656 struct interface *ifp; 657 658 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 659 if (ifp->flags & IFF_LOOPBACK) 660 return ifp; 661 } 662 return NULL; 663} 664 665int 666if_domtu(const struct interface *ifp, short int mtu) 667{ 668 int r; 669 struct ifreq ifr; 670 671 memset(&ifr, 0, sizeof(ifr)); 672 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 673 ifr.ifr_mtu = mtu; 674 r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 675 if (r == -1) 676 return -1; 677 return ifr.ifr_mtu; 678} 679 680/* Interface comparer for working out ordering. */ 681static int 682if_cmp(const struct interface *si, const struct interface *ti) 683{ 684#ifdef INET 685 int r; 686#endif 687 688 /* Check active first */ 689 if (si->active > ti->active) 690 return -1; 691 if (si->active < ti->active) 692 return 1; 693 694 /* Check carrier status next */ 695 if (si->carrier > ti->carrier) 696 return -1; 697 if (si->carrier < ti->carrier) 698 return 1; 699 700 if (D_STATE_RUNNING(si) && !D_STATE_RUNNING(ti)) 701 return -1; 702 if (!D_STATE_RUNNING(si) && D_STATE_RUNNING(ti)) 703 return 1; 704 if (RS_STATE_RUNNING(si) && !RS_STATE_RUNNING(ti)) 705 return -1; 706 if (!RS_STATE_RUNNING(si) && RS_STATE_RUNNING(ti)) 707 return 1; 708 if (D6_STATE_RUNNING(si) && !D6_STATE_RUNNING(ti)) 709 return -1; 710 if (!D6_STATE_RUNNING(si) && D6_STATE_RUNNING(ti)) 711 return 1; 712 713#ifdef INET 714 /* Special attention needed here due to states and IPv4LL. */ 715 if ((r = ipv4_ifcmp(si, ti)) != 0) 716 return r; 717#endif 718 719 /* Finally, metric */ 720 if (si->metric < ti->metric) 721 return -1; 722 if (si->metric > ti->metric) 723 return 1; 724 return 0; 725} 726 727/* Sort the interfaces into a preferred order - best first, worst last. */ 728void 729if_sortinterfaces(struct dhcpcd_ctx *ctx) 730{ 731 struct if_head sorted; 732 struct interface *ifp, *ift; 733 734 if (ctx->ifaces == NULL || 735 (ifp = TAILQ_FIRST(ctx->ifaces)) == NULL || 736 TAILQ_NEXT(ifp, next) == NULL) 737 return; 738 739 TAILQ_INIT(&sorted); 740 TAILQ_REMOVE(ctx->ifaces, ifp, next); 741 TAILQ_INSERT_HEAD(&sorted, ifp, next); 742 while ((ifp = TAILQ_FIRST(ctx->ifaces))) { 743 TAILQ_REMOVE(ctx->ifaces, ifp, next); 744 TAILQ_FOREACH(ift, &sorted, next) { 745 if (if_cmp(ifp, ift) == -1) { 746 TAILQ_INSERT_BEFORE(ift, ifp, next); 747 break; 748 } 749 } 750 if (ift == NULL) 751 TAILQ_INSERT_TAIL(&sorted, ifp, next); 752 } 753 TAILQ_CONCAT(ctx->ifaces, &sorted, next); 754} 755 756int 757xsocket(int domain, int type, int protocol) 758{ 759 int s; 760#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 761 int xflags, xtype = type; 762#endif 763 764#ifndef HAVE_SOCK_CLOEXEC 765 if (xtype & SOCK_CLOEXEC) 766 type &= ~SOCK_CLOEXEC; 767#endif 768#ifndef HAVE_SOCK_NONBLOCK 769 if (xtype & SOCK_NONBLOCK) 770 type &= ~SOCK_NONBLOCK; 771#endif 772 773 if ((s = socket(domain, type, protocol)) == -1) 774 return -1; 775 776#ifndef HAVE_SOCK_CLOEXEC 777 if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 || 778 fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)) 779 goto out; 780#endif 781#ifndef HAVE_SOCK_NONBLOCK 782 if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 || 783 fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)) 784 goto out; 785#endif 786 787 return s; 788 789#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 790out: 791 close(s); 792 return -1; 793#endif 794} 795