if.c revision 1.1.1.13
1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2019 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#ifdef IPV4LL 82 ipv4ll_free(ifp); 83#endif 84#ifdef INET 85 dhcp_free(ifp); 86 ipv4_free(ifp); 87#endif 88#ifdef DHCP6 89 dhcp6_free(ifp); 90#endif 91#ifdef INET6 92 ipv6nd_free(ifp); 93 ipv6_free(ifp); 94#endif 95 rt_freeif(ifp); 96 free_options(ifp->ctx, ifp->options); 97 free(ifp); 98} 99 100int 101if_opensockets(struct dhcpcd_ctx *ctx) 102{ 103 104 if (if_opensockets_os(ctx) == -1) 105 return -1; 106 107 /* We use this socket for some operations without INET. */ 108 ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 109 if (ctx->pf_inet_fd == -1) 110 return -1; 111 112 return 0; 113} 114 115void 116if_closesockets(struct dhcpcd_ctx *ctx) 117{ 118 119 if (ctx->pf_inet_fd != -1) 120 close(ctx->pf_inet_fd); 121 122 if (ctx->priv) { 123 if_closesockets_os(ctx); 124 free(ctx->priv); 125 } 126} 127 128int 129if_getflags(struct interface *ifp) 130{ 131 struct ifreq ifr = { .ifr_flags = 0 }; 132 133 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 134 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) 135 return -1; 136 ifp->flags = (unsigned int)ifr.ifr_flags; 137 return 0; 138} 139 140int 141if_setflag(struct interface *ifp, short flag) 142{ 143 struct ifreq ifr = { .ifr_flags = 0 }; 144 short f; 145 146 if (if_getflags(ifp) == -1) 147 return -1; 148 149 f = (short)ifp->flags; 150 if ((f & flag) == flag) 151 return 0; 152 153 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 154 ifr.ifr_flags = f | flag; 155 if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1) 156 return -1; 157 158 ifp->flags = (unsigned int)ifr.ifr_flags; 159 return 0; 160} 161 162static int 163if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname) 164{ 165 int i; 166 167 for (i = 0; i < ctx->ifcc; i++) { 168 if (strcmp(ctx->ifcv[i], ifname) == 0) 169 return 1; 170 } 171 return 0; 172} 173 174void 175if_markaddrsstale(struct if_head *ifs) 176{ 177 struct interface *ifp; 178 179 TAILQ_FOREACH(ifp, ifs, next) { 180#ifdef INET 181 ipv4_markaddrsstale(ifp); 182#endif 183#ifdef INET6 184 ipv6_markaddrsstale(ifp, 0); 185#endif 186 } 187} 188 189void 190if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, 191 struct ifaddrs **ifaddrs) 192{ 193 struct ifaddrs *ifa; 194 struct interface *ifp; 195#ifdef INET 196 const struct sockaddr_in *addr, *net, *brd; 197#endif 198#ifdef INET6 199 struct sockaddr_in6 *sin6, *net6; 200#endif 201 int addrflags; 202 203 for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { 204 if (ifa->ifa_addr == NULL) 205 continue; 206 if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL) 207 continue; 208#ifdef HAVE_IFADDRS_ADDRFLAGS 209 addrflags = (int)ifa->ifa_addrflags; 210#endif 211 switch(ifa->ifa_addr->sa_family) { 212#ifdef INET 213 case AF_INET: 214 addr = (void *)ifa->ifa_addr; 215 net = (void *)ifa->ifa_netmask; 216 if (ifa->ifa_flags & IFF_POINTOPOINT) 217 brd = (void *)ifa->ifa_dstaddr; 218 else 219 brd = (void *)ifa->ifa_broadaddr; 220#ifndef HAVE_IFADDRS_ADDRFLAGS 221 addrflags = if_addrflags(ifp, &addr->sin_addr, 222 ifa->ifa_name); 223 if (addrflags == -1) { 224 if (errno != EEXIST && errno != EADDRNOTAVAIL) 225 logerr("%s: if_addrflags", __func__); 226 continue; 227 } 228#endif 229 ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, 230 &addr->sin_addr, &net->sin_addr, 231 brd ? &brd->sin_addr : NULL, addrflags, 0); 232 break; 233#endif 234#ifdef INET6 235 case AF_INET6: 236 sin6 = (void *)ifa->ifa_addr; 237 net6 = (void *)ifa->ifa_netmask; 238#ifdef __KAME__ 239 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 240 /* Remove the scope from the address */ 241 sin6->sin6_addr.s6_addr[2] = 242 sin6->sin6_addr.s6_addr[3] = '\0'; 243#endif 244#ifndef HAVE_IFADDRS_ADDRFLAGS 245 addrflags = if_addrflags6(ifp, &sin6->sin6_addr, 246 ifa->ifa_name); 247 if (addrflags == -1) { 248 if (errno != EEXIST && errno != EADDRNOTAVAIL) 249 logerr("%s: if_addrflags6", __func__); 250 continue; 251 } 252#endif 253 ipv6_handleifa(ctx, RTM_NEWADDR, ifs, 254 ifa->ifa_name, &sin6->sin6_addr, 255 ipv6_prefixlen(&net6->sin6_addr), addrflags, 0); 256 break; 257#endif 258 } 259 } 260 261 freeifaddrs(*ifaddrs); 262 *ifaddrs = NULL; 263} 264 265void 266if_deletestaleaddrs(struct if_head *ifs) 267{ 268 struct interface *ifp; 269 270 TAILQ_FOREACH(ifp, ifs, next) { 271#ifdef INET 272 ipv4_deletestaleaddrs(ifp); 273#endif 274#ifdef INET6 275 ipv6_deletestaleaddrs(ifp); 276#endif 277 } 278} 279 280bool 281if_valid_hwaddr(const uint8_t *hwaddr, size_t hwlen) 282{ 283 size_t i; 284 bool all_zeros, all_ones; 285 286 all_zeros = all_ones = true; 287 for (i = 0; i < hwlen; i++) { 288 if (hwaddr[i] != 0x00) 289 all_zeros = false; 290 if (hwaddr[i] != 0xff) 291 all_ones = false; 292 if (!all_zeros && !all_ones) 293 return true; 294 } 295 return false; 296} 297 298struct if_head * 299if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, 300 int argc, char * const *argv) 301{ 302 struct ifaddrs *ifa; 303 int i; 304 unsigned int active; 305 struct if_head *ifs; 306 struct interface *ifp; 307 struct if_spec spec; 308#ifdef AF_LINK 309 const struct sockaddr_dl *sdl; 310#ifdef SIOCGIFPRIORITY 311 struct ifreq ifr; 312#endif 313#ifdef IFLR_ACTIVE 314 struct if_laddrreq iflr = { .flags = IFLR_PREFIX }; 315 int link_fd; 316#endif 317 318#elif AF_PACKET 319 const struct sockaddr_ll *sll; 320#endif 321 322 if ((ifs = malloc(sizeof(*ifs))) == NULL) { 323 logerr(__func__); 324 return NULL; 325 } 326 if (getifaddrs(ifaddrs) == -1) { 327 logerr(__func__); 328 free(ifs); 329 return NULL; 330 } 331 TAILQ_INIT(ifs); 332 333#ifdef IFLR_ACTIVE 334 link_fd = xsocket(PF_LINK, SOCK_DGRAM | SOCK_CLOEXEC, 0); 335 if (link_fd == -1) { 336 logerr(__func__); 337 free(ifs); 338 return NULL; 339 } 340#endif 341 342 for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { 343 if (ifa->ifa_addr != NULL) { 344#ifdef AF_LINK 345 if (ifa->ifa_addr->sa_family != AF_LINK) 346 continue; 347#elif AF_PACKET 348 if (ifa->ifa_addr->sa_family != AF_PACKET) 349 continue; 350#endif 351 } 352 if (if_nametospec(ifa->ifa_name, &spec) != 0) 353 continue; 354 355 /* It's possible for an interface to have >1 AF_LINK. 356 * For our purposes, we use the first one. */ 357 TAILQ_FOREACH(ifp, ifs, next) { 358 if (strcmp(ifp->name, spec.devname) == 0) 359 break; 360 } 361 if (ifp) 362 continue; 363 364 if (argc > 0) { 365 for (i = 0; i < argc; i++) { 366 if (strcmp(argv[i], spec.devname) == 0) 367 break; 368 } 369 active = (i == argc) ? IF_INACTIVE : IF_ACTIVE_USER; 370 } else { 371 /* -1 means we're discovering against a specific 372 * interface, but we still need the below rules 373 * to apply. */ 374 if (argc == -1 && strcmp(argv[0], spec.devname) != 0) 375 continue; 376 active = ctx->options & DHCPCD_INACTIVE ? 377 IF_INACTIVE: IF_ACTIVE_USER; 378 } 379 380 for (i = 0; i < ctx->ifdc; i++) 381 if (fnmatch(ctx->ifdv[i], spec.devname, 0) == 0) 382 break; 383 if (i < ctx->ifdc) 384 active = IF_INACTIVE; 385 for (i = 0; i < ctx->ifc; i++) 386 if (fnmatch(ctx->ifv[i], spec.devname, 0) == 0) 387 break; 388 if (ctx->ifc && i == ctx->ifc) 389 active = IF_INACTIVE; 390 for (i = 0; i < ctx->ifac; i++) 391 if (fnmatch(ctx->ifav[i], spec.devname, 0) == 0) 392 break; 393 if (ctx->ifac && i == ctx->ifac) 394 active = IF_INACTIVE; 395 396#ifdef PLUGIN_DEV 397 /* Ensure that the interface name has settled */ 398 if (!dev_initialized(ctx, spec.devname)) 399 continue; 400#endif 401 402 /* Don't allow loopback or pointopoint unless explicit */ 403 if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) { 404 if ((argc == 0 || argc == -1) && 405 ctx->ifac == 0 && !if_hasconf(ctx, spec.devname)) 406 active = IF_INACTIVE; 407 } 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 ifp = calloc(1, sizeof(*ifp)); 417 if (ifp == NULL) { 418 logerr(__func__); 419 break; 420 } 421 ifp->ctx = ctx; 422 strlcpy(ifp->name, spec.devname, sizeof(ifp->name)); 423 ifp->flags = ifa->ifa_flags; 424 425 if (ifa->ifa_addr != NULL) { 426#ifdef AF_LINK 427 sdl = (const void *)ifa->ifa_addr; 428 429#ifdef IFLR_ACTIVE 430 /* We need to check for active address */ 431 strlcpy(iflr.iflr_name, ifp->name, 432 sizeof(iflr.iflr_name)); 433 memcpy(&iflr.addr, ifa->ifa_addr, 434 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 435 iflr.flags = IFLR_PREFIX; 436 iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY; 437 if (ioctl(link_fd, SIOCGLIFADDR, &iflr) == -1 || 438 !(iflr.flags & IFLR_ACTIVE)) 439 { 440 if_free(ifp); 441 continue; 442 } 443#endif 444 445 ifp->index = sdl->sdl_index; 446 switch(sdl->sdl_type) { 447#ifdef IFT_BRIDGE 448 case IFT_BRIDGE: /* FALLTHROUGH */ 449#endif 450#ifdef IFT_PPP 451 case IFT_PPP: /* FALLTHROUGH */ 452#endif 453#ifdef IFT_PROPVIRTUAL 454 case IFT_PROPVIRTUAL: 455#endif 456#if defined(IFT_BRIDGE) || defined(IFT_PPP) || defined(IFT_PROPVIRTUAL) 457 /* Don't allow unless explicit */ 458 if ((argc == 0 || argc == -1) && 459 ctx->ifac == 0 && active && 460 !if_hasconf(ctx, ifp->name)) 461 { 462 logdebugx("%s: ignoring due to" 463 " interface type and" 464 " no config", 465 ifp->name); 466 active = IF_INACTIVE; 467 } 468 __fallthrough; /* Appease gcc-7 */ 469 /* FALLTHROUGH */ 470#endif 471#ifdef IFT_L2VLAN 472 case IFT_L2VLAN: /* FALLTHROUGH */ 473#endif 474#ifdef IFT_L3IPVLAN 475 case IFT_L3IPVLAN: /* FALLTHROUGH */ 476#endif 477 case IFT_ETHER: 478 ifp->family = ARPHRD_ETHER; 479 break; 480#ifdef IFT_IEEE1394 481 case IFT_IEEE1394: 482 ifp->family = ARPHRD_IEEE1394; 483 break; 484#endif 485#ifdef IFT_INFINIBAND 486 case IFT_INFINIBAND: 487 ifp->family = ARPHRD_INFINIBAND; 488 break; 489#endif 490 default: 491 /* Don't allow unless explicit */ 492 if ((argc == 0 || argc == -1) && 493 ctx->ifac == 0 && 494 !if_hasconf(ctx, ifp->name)) 495 active = IF_INACTIVE; 496 if (active) 497 logwarnx("%s: unsupported" 498 " interface type %.2x", 499 ifp->name, sdl->sdl_type); 500 /* Pretend it's ethernet */ 501 ifp->family = ARPHRD_ETHER; 502 break; 503 } 504 ifp->hwlen = sdl->sdl_alen; 505 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 506#elif AF_PACKET 507 sll = (const void *)ifa->ifa_addr; 508 ifp->index = (unsigned int)sll->sll_ifindex; 509 ifp->family = sll->sll_hatype; 510 ifp->hwlen = sll->sll_halen; 511 if (ifp->hwlen != 0) 512 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 513#endif 514 } 515#ifdef __linux__ 516 /* PPP addresses on Linux don't have hardware addresses */ 517 else 518 ifp->index = if_nametoindex(ifp->name); 519#endif 520 521 /* Ensure hardware address is valid. */ 522 if (!if_valid_hwaddr(ifp->hwaddr, ifp->hwlen)) 523 ifp->hwlen = 0; 524 525 /* We only work on ethernet by default */ 526 if (ifp->family != ARPHRD_ETHER) { 527 if ((argc == 0 || argc == -1) && 528 ctx->ifac == 0 && !if_hasconf(ctx, ifp->name)) 529 active = IF_INACTIVE; 530 switch (ifp->family) { 531 case ARPHRD_IEEE1394: 532 case ARPHRD_INFINIBAND: 533#ifdef ARPHRD_LOOPBACK 534 case ARPHRD_LOOPBACK: 535#endif 536#ifdef ARPHRD_PPP 537 case ARPHRD_PPP: 538#endif 539 /* We don't warn for supported families */ 540 break; 541 542/* IFT already checked */ 543#ifndef AF_LINK 544 default: 545 if (active) 546 logwarnx("%s: unsupported" 547 " interface family %.2x", 548 ifp->name, ifp->family); 549 break; 550#endif 551 } 552 } 553 554 if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) { 555 /* Handle any platform init for the interface */ 556 if (active != IF_INACTIVE && if_init(ifp) == -1) { 557 logerr("%s: if_init", ifp->name); 558 if_free(ifp); 559 continue; 560 } 561 } 562 563 ifp->vlanid = if_vlanid(ifp); 564 565#ifdef SIOCGIFPRIORITY 566 /* Respect the interface priority */ 567 memset(&ifr, 0, sizeof(ifr)); 568 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 569 if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0) 570 ifp->metric = (unsigned int)ifr.ifr_metric; 571 if_getssid(ifp); 572#else 573 /* We reserve the 100 range for virtual interfaces, if and when 574 * we can work them out. */ 575 ifp->metric = 200 + ifp->index; 576 if (if_getssid(ifp) != -1) { 577 ifp->wireless = true; 578 ifp->metric += 100; 579 } 580#endif 581 582 ifp->active = active; 583 if (ifp->active) 584 ifp->carrier = if_carrier(ifp); 585 else 586 ifp->carrier = LINK_UNKNOWN; 587 TAILQ_INSERT_TAIL(ifs, ifp, next); 588 } 589 590#ifdef IFLR_ACTIVE 591 close(link_fd); 592#endif 593 return ifs; 594} 595 596/* Decode bge0:1 as dev = bge, ppa = 0 and lun = 1 */ 597int 598if_nametospec(const char *ifname, struct if_spec *spec) 599{ 600 char *ep; 601 int e; 602 603 if (ifname == NULL || *ifname == '\0' || 604 strlcpy(spec->ifname, ifname, sizeof(spec->ifname)) >= 605 sizeof(spec->ifname) || 606 strlcpy(spec->drvname, ifname, sizeof(spec->drvname)) >= 607 sizeof(spec->drvname)) 608 { 609 errno = EINVAL; 610 return -1; 611 } 612 ep = strchr(spec->drvname, ':'); 613 if (ep) { 614 spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e); 615 if (e != 0) { 616 errno = e; 617 return -1; 618 } 619 *ep-- = '\0'; 620 } else { 621 spec->lun = -1; 622 ep = spec->drvname + strlen(spec->drvname) - 1; 623 } 624 strlcpy(spec->devname, spec->drvname, sizeof(spec->devname)); 625 while (ep > spec->drvname && isdigit((int)*ep)) 626 ep--; 627 if (*ep++ == ':') { 628 errno = EINVAL; 629 return -1; 630 } 631 spec->ppa = (int)strtoi(ep, NULL, 10, 0, INT_MAX, &e); 632 if (e != 0) 633 spec->ppa = -1; 634 *ep = '\0'; 635 636 return 0; 637} 638 639static struct interface * 640if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name) 641{ 642 643 if (ifaces != NULL) { 644 struct if_spec spec; 645 struct interface *ifp; 646 647 if (name && if_nametospec(name, &spec) == -1) 648 return NULL; 649 650 TAILQ_FOREACH(ifp, ifaces, next) { 651 if ((name && strcmp(ifp->name, spec.devname) == 0) || 652 (!name && ifp->index == idx)) 653 return ifp; 654 } 655 } 656 657 errno = ENXIO; 658 return NULL; 659} 660 661struct interface * 662if_find(struct if_head *ifaces, const char *name) 663{ 664 665 return if_findindexname(ifaces, 0, name); 666} 667 668struct interface * 669if_findindex(struct if_head *ifaces, unsigned int idx) 670{ 671 672 return if_findindexname(ifaces, idx, NULL); 673} 674 675struct interface * 676if_loopback(struct dhcpcd_ctx *ctx) 677{ 678 struct interface *ifp; 679 680 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 681 if (ifp->flags & IFF_LOOPBACK) 682 return ifp; 683 } 684 return NULL; 685} 686 687int 688if_domtu(const struct interface *ifp, short int mtu) 689{ 690 int r; 691 struct ifreq ifr; 692 693#ifdef __sun 694 if (mtu == 0) 695 return if_mtu_os(ifp); 696#endif 697 698 memset(&ifr, 0, sizeof(ifr)); 699 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 700 ifr.ifr_mtu = mtu; 701 r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 702 if (r == -1) 703 return -1; 704 return ifr.ifr_mtu; 705} 706 707/* Interface comparer for working out ordering. */ 708static int 709if_cmp(const struct interface *si, const struct interface *ti) 710{ 711#ifdef INET 712 int r; 713#endif 714 715 /* Check active first */ 716 if (si->active > ti->active) 717 return -1; 718 if (si->active < ti->active) 719 return 1; 720 721 /* Check carrier status next */ 722 if (si->carrier > ti->carrier) 723 return -1; 724 if (si->carrier < ti->carrier) 725 return 1; 726#ifdef INET 727 if (D_STATE_RUNNING(si) && !D_STATE_RUNNING(ti)) 728 return -1; 729 if (!D_STATE_RUNNING(si) && D_STATE_RUNNING(ti)) 730 return 1; 731#endif 732#ifdef INET6 733 if (RS_STATE_RUNNING(si) && !RS_STATE_RUNNING(ti)) 734 return -1; 735 if (!RS_STATE_RUNNING(si) && RS_STATE_RUNNING(ti)) 736 return 1; 737#endif 738#ifdef DHCP6 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#endif 744 745#ifdef INET 746 /* Special attention needed here due to states and IPv4LL. */ 747 if ((r = ipv4_ifcmp(si, ti)) != 0) 748 return r; 749#endif 750 751 /* Finally, metric */ 752 if (si->metric < ti->metric) 753 return -1; 754 if (si->metric > ti->metric) 755 return 1; 756 return 0; 757} 758 759#ifdef ALIAS_ADDR 760int 761if_makealias(char *alias, size_t alias_len, const char *ifname, int lun) 762{ 763 764 if (lun == 0) 765 return strlcpy(alias, ifname, alias_len); 766 return snprintf(alias, alias_len, "%s:%u", ifname, lun); 767} 768#endif 769 770/* Sort the interfaces into a preferred order - best first, worst last. */ 771void 772if_sortinterfaces(struct dhcpcd_ctx *ctx) 773{ 774 struct if_head sorted; 775 struct interface *ifp, *ift; 776 777 if (ctx->ifaces == NULL || 778 (ifp = TAILQ_FIRST(ctx->ifaces)) == NULL || 779 TAILQ_NEXT(ifp, next) == NULL) 780 return; 781 782 TAILQ_INIT(&sorted); 783 TAILQ_REMOVE(ctx->ifaces, ifp, next); 784 TAILQ_INSERT_HEAD(&sorted, ifp, next); 785 while ((ifp = TAILQ_FIRST(ctx->ifaces))) { 786 TAILQ_REMOVE(ctx->ifaces, ifp, next); 787 TAILQ_FOREACH(ift, &sorted, next) { 788 if (if_cmp(ifp, ift) == -1) { 789 TAILQ_INSERT_BEFORE(ift, ifp, next); 790 break; 791 } 792 } 793 if (ift == NULL) 794 TAILQ_INSERT_TAIL(&sorted, ifp, next); 795 } 796 TAILQ_CONCAT(ctx->ifaces, &sorted, next); 797} 798 799struct interface * 800if_findifpfromcmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, int *hoplimit) 801{ 802 struct cmsghdr *cm; 803 unsigned int ifindex = 0; 804 struct interface *ifp; 805#if defined(INET) && defined(IP_PKTINFO) 806 struct in_pktinfo ipi; 807#endif 808#ifdef INET6 809 struct in6_pktinfo ipi6; 810#else 811 UNUSED(hoplimit); 812#endif 813 814 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(msg); 815 cm; 816 cm = (struct cmsghdr *)CMSG_NXTHDR(msg, cm)) 817 { 818#if defined(INET) && defined(IP_PKTINFO) 819 if (cm->cmsg_level == IPPROTO_IP) { 820 switch(cm->cmsg_type) { 821 case IP_PKTINFO: 822 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi))) 823 continue; 824 memcpy(&ipi, CMSG_DATA(cm), sizeof(ipi)); 825 ifindex = (unsigned int)ipi.ipi_ifindex; 826 break; 827 } 828 } 829#endif 830#ifdef INET6 831 if (cm->cmsg_level == IPPROTO_IPV6) { 832 switch(cm->cmsg_type) { 833 case IPV6_PKTINFO: 834 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi6))) 835 continue; 836 memcpy(&ipi6, CMSG_DATA(cm), sizeof(ipi6)); 837 ifindex = (unsigned int)ipi6.ipi6_ifindex; 838 break; 839 case IPV6_HOPLIMIT: 840 if (cm->cmsg_len != CMSG_LEN(sizeof(int))) 841 continue; 842 if (hoplimit == NULL) 843 break; 844 memcpy(hoplimit, CMSG_DATA(cm), sizeof(int)); 845 break; 846 } 847 } 848#endif 849 } 850 851 /* Find the receiving interface */ 852 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 853 if (ifp->index == ifindex) 854 break; 855 } 856 if (ifp == NULL) 857 errno = ESRCH; 858 return ifp; 859} 860 861int 862xsocket(int domain, int type, int protocol) 863{ 864 int s; 865#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 866 int xflags, xtype = type; 867#endif 868#ifdef SO_RERROR 869 int on; 870#endif 871 872#ifndef HAVE_SOCK_CLOEXEC 873 if (xtype & SOCK_CLOEXEC) 874 type &= ~SOCK_CLOEXEC; 875#endif 876#ifndef HAVE_SOCK_NONBLOCK 877 if (xtype & SOCK_NONBLOCK) 878 type &= ~SOCK_NONBLOCK; 879#endif 880 881 if ((s = socket(domain, type, protocol)) == -1) 882 return -1; 883 884#ifndef HAVE_SOCK_CLOEXEC 885 if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 || 886 fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)) 887 goto out; 888#endif 889#ifndef HAVE_SOCK_NONBLOCK 890 if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 || 891 fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)) 892 goto out; 893#endif 894 895#ifdef SO_RERROR 896 /* Tell recvmsg(2) to return ENOBUFS if the receiving socket overflows. */ 897 on = 1; 898 if (setsockopt(s, SOL_SOCKET, SO_RERROR, &on, sizeof(on)) == -1) 899 logerr("%s: SO_RERROR", __func__); 900#endif 901 902 return s; 903 904#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 905out: 906 close(s); 907 return -1; 908#endif 909} 910