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 #ifdef AF_LINK 316 const struct sockaddr_dl *sdl; 317 #ifdef IFLR_ACTIVE 318 struct if_laddrreq iflr = { .flags = IFLR_PREFIX }; 319 int link_fd; 320 #endif 321 #elif AF_PACKET 322 const struct sockaddr_ll *sll; 323 #endif 324 #if defined(SIOCGIFPRIORITY) || defined(SIOCGIFHWADDR) 325 struct ifreq ifr; 326 #endif 327 328 if ((ifs = malloc(sizeof(*ifs))) == NULL) { 329 logerr(__func__); 330 return NULL; 331 } 332 if (getifaddrs(ifaddrs) == -1) { 333 logerr(__func__); 334 free(ifs); 335 return NULL; 336 } 337 TAILQ_INIT(ifs); 338 339 #ifdef IFLR_ACTIVE 340 link_fd = xsocket(PF_LINK, SOCK_DGRAM | SOCK_CLOEXEC, 0); 341 if (link_fd == -1) { 342 logerr(__func__); 343 free(ifs); 344 return NULL; 345 } 346 #endif 347 348 for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { 349 if (ifa->ifa_addr != NULL) { 350 #ifdef AF_LINK 351 if (ifa->ifa_addr->sa_family != AF_LINK) 352 continue; 353 #elif AF_PACKET 354 if (ifa->ifa_addr->sa_family != AF_PACKET) 355 continue; 356 #endif 357 } 358 if (if_nametospec(ifa->ifa_name, &spec) != 0) 359 continue; 360 361 /* It's possible for an interface to have >1 AF_LINK. 362 * For our purposes, we use the first one. */ 363 TAILQ_FOREACH(ifp, ifs, next) { 364 if (strcmp(ifp->name, spec.devname) == 0) 365 break; 366 } 367 if (ifp) 368 continue; 369 370 if (argc > 0) { 371 for (i = 0; i < argc; i++) { 372 if (strcmp(argv[i], spec.devname) == 0) 373 break; 374 } 375 active = (i == argc) ? IF_INACTIVE : IF_ACTIVE_USER; 376 } else { 377 /* -1 means we're discovering against a specific 378 * interface, but we still need the below rules 379 * to apply. */ 380 if (argc == -1 && strcmp(argv[0], spec.devname) != 0) 381 continue; 382 active = ctx->options & DHCPCD_INACTIVE ? 383 IF_INACTIVE: IF_ACTIVE_USER; 384 } 385 386 for (i = 0; i < ctx->ifdc; i++) 387 if (fnmatch(ctx->ifdv[i], spec.devname, 0) == 0) 388 break; 389 if (i < ctx->ifdc) 390 active = IF_INACTIVE; 391 for (i = 0; i < ctx->ifc; i++) 392 if (fnmatch(ctx->ifv[i], spec.devname, 0) == 0) 393 break; 394 if (ctx->ifc && i == ctx->ifc) 395 active = IF_INACTIVE; 396 for (i = 0; i < ctx->ifac; i++) 397 if (fnmatch(ctx->ifav[i], spec.devname, 0) == 0) 398 break; 399 if (ctx->ifac && i == ctx->ifac) 400 active = IF_INACTIVE; 401 402 #ifdef PLUGIN_DEV 403 /* Ensure that the interface name has settled */ 404 if (!dev_initialized(ctx, spec.devname)) 405 continue; 406 #endif 407 408 /* Don't allow loopback or pointopoint unless explicit */ 409 if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) { 410 if ((argc == 0 || argc == -1) && 411 ctx->ifac == 0 && !if_hasconf(ctx, spec.devname)) 412 active = IF_INACTIVE; 413 } 414 415 if (if_vimaster(ctx, spec.devname) == 1) { 416 logfunc_t *logfunc = argc != 0 ? logerrx : logdebugx; 417 logfunc("%s: is a Virtual Interface Master, skipping", 418 spec.devname); 419 continue; 420 } 421 422 ifp = calloc(1, sizeof(*ifp)); 423 if (ifp == NULL) { 424 logerr(__func__); 425 break; 426 } 427 ifp->ctx = ctx; 428 strlcpy(ifp->name, spec.devname, sizeof(ifp->name)); 429 ifp->flags = ifa->ifa_flags; 430 431 if (ifa->ifa_addr != NULL) { 432 #ifdef AF_LINK 433 sdl = (const void *)ifa->ifa_addr; 434 435 #ifdef IFLR_ACTIVE 436 /* We need to check for active address */ 437 strlcpy(iflr.iflr_name, ifp->name, 438 sizeof(iflr.iflr_name)); 439 memcpy(&iflr.addr, ifa->ifa_addr, 440 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 441 iflr.flags = IFLR_PREFIX; 442 iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY; 443 if (ioctl(link_fd, SIOCGLIFADDR, &iflr) == -1 || 444 !(iflr.flags & IFLR_ACTIVE)) 445 { 446 if_free(ifp); 447 continue; 448 } 449 #endif 450 451 ifp->index = sdl->sdl_index; 452 switch(sdl->sdl_type) { 453 #ifdef IFT_BRIDGE 454 case IFT_BRIDGE: /* FALLTHROUGH */ 455 #endif 456 #ifdef IFT_PPP 457 case IFT_PPP: /* FALLTHROUGH */ 458 #endif 459 #ifdef IFT_PROPVIRTUAL 460 case IFT_PROPVIRTUAL: 461 #endif 462 #if defined(IFT_BRIDGE) || defined(IFT_PPP) || defined(IFT_PROPVIRTUAL) 463 /* Don't allow unless explicit */ 464 if ((argc == 0 || argc == -1) && 465 ctx->ifac == 0 && active && 466 !if_hasconf(ctx, ifp->name)) 467 { 468 logdebugx("%s: ignoring due to" 469 " interface type and" 470 " no config", 471 ifp->name); 472 active = IF_INACTIVE; 473 } 474 __fallthrough; /* Appease gcc-7 */ 475 /* FALLTHROUGH */ 476 #endif 477 #ifdef IFT_L2VLAN 478 case IFT_L2VLAN: /* FALLTHROUGH */ 479 #endif 480 #ifdef IFT_L3IPVLAN 481 case IFT_L3IPVLAN: /* FALLTHROUGH */ 482 #endif 483 case IFT_ETHER: 484 ifp->family = ARPHRD_ETHER; 485 break; 486 #ifdef IFT_IEEE1394 487 case IFT_IEEE1394: 488 ifp->family = ARPHRD_IEEE1394; 489 break; 490 #endif 491 #ifdef IFT_INFINIBAND 492 case IFT_INFINIBAND: 493 ifp->family = ARPHRD_INFINIBAND; 494 break; 495 #endif 496 default: 497 /* Don't allow unless explicit */ 498 if ((argc == 0 || argc == -1) && 499 ctx->ifac == 0 && 500 !if_hasconf(ctx, ifp->name)) 501 active = IF_INACTIVE; 502 if (active) 503 logwarnx("%s: unsupported" 504 " interface type %.2x", 505 ifp->name, sdl->sdl_type); 506 /* Pretend it's ethernet */ 507 ifp->family = ARPHRD_ETHER; 508 break; 509 } 510 ifp->hwlen = sdl->sdl_alen; 511 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 512 #elif AF_PACKET 513 sll = (const void *)ifa->ifa_addr; 514 ifp->index = (unsigned int)sll->sll_ifindex; 515 ifp->family = sll->sll_hatype; 516 ifp->hwlen = sll->sll_halen; 517 if (ifp->hwlen != 0) 518 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 519 #endif 520 } 521 #ifdef SIOCGIFHWADDR 522 else { 523 /* This is a huge bug in getifaddrs(3) as there 524 * is no reason why this can't be returned in 525 * ifa_addr. */ 526 memset(&ifr, 0, sizeof(ifr)); 527 strlcpy(ifr.ifr_name, ifa->ifa_name, 528 sizeof(ifr.ifr_name)); 529 if (ioctl(ctx->pf_inet_fd, SIOCGIFHWADDR, &ifr) == -1) 530 logerr("%s: SIOCGIFHWADDR", ifa->ifa_name); 531 ifp->family = ifr.ifr_hwaddr.sa_family; 532 if (ioctl(ctx->pf_inet_fd, SIOCGIFINDEX, &ifr) == -1) 533 logerr("%s: SIOCGIFINDEX", ifa->ifa_name); 534 ifp->index = (unsigned int)ifr.ifr_ifindex; 535 } 536 #endif 537 538 /* Ensure hardware address is valid. */ 539 if (!if_valid_hwaddr(ifp->hwaddr, ifp->hwlen)) 540 ifp->hwlen = 0; 541 542 /* We only work on ethernet by default */ 543 if (ifp->family != ARPHRD_ETHER) { 544 if ((argc == 0 || argc == -1) && 545 ctx->ifac == 0 && !if_hasconf(ctx, ifp->name)) 546 active = IF_INACTIVE; 547 switch (ifp->family) { 548 case ARPHRD_IEEE1394: 549 case ARPHRD_INFINIBAND: 550 #ifdef ARPHRD_LOOPBACK 551 case ARPHRD_LOOPBACK: 552 #endif 553 #ifdef ARPHRD_PPP 554 case ARPHRD_PPP: 555 #endif 556 #ifdef ARPHRD_NONE 557 case ARPHRD_NONE: 558 #endif 559 /* We don't warn for supported families */ 560 break; 561 562 /* IFT already checked */ 563 #ifndef AF_LINK 564 default: 565 if (active) 566 logwarnx("%s: unsupported" 567 " interface family %.2x", 568 ifp->name, ifp->family); 569 break; 570 #endif 571 } 572 } 573 574 if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) { 575 /* Handle any platform init for the interface */ 576 if (active != IF_INACTIVE && if_init(ifp) == -1) { 577 logerr("%s: if_init", ifp->name); 578 if_free(ifp); 579 continue; 580 } 581 } 582 583 ifp->vlanid = if_vlanid(ifp); 584 585 #ifdef SIOCGIFPRIORITY 586 /* Respect the interface priority */ 587 memset(&ifr, 0, sizeof(ifr)); 588 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 589 if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0) 590 ifp->metric = (unsigned int)ifr.ifr_metric; 591 if_getssid(ifp); 592 #else 593 /* We reserve the 100 range for virtual interfaces, if and when 594 * we can work them out. */ 595 ifp->metric = 200 + ifp->index; 596 if (if_getssid(ifp) != -1) { 597 ifp->wireless = true; 598 ifp->metric += 100; 599 } 600 #endif 601 602 ifp->active = active; 603 if (ifp->active) 604 ifp->carrier = if_carrier(ifp); 605 else 606 ifp->carrier = LINK_UNKNOWN; 607 TAILQ_INSERT_TAIL(ifs, ifp, next); 608 } 609 610 #ifdef IFLR_ACTIVE 611 close(link_fd); 612 #endif 613 return ifs; 614 } 615 616 /* Decode bge0:1 as dev = bge, ppa = 0 and lun = 1 */ 617 int 618 if_nametospec(const char *ifname, struct if_spec *spec) 619 { 620 char *ep; 621 int e; 622 623 if (ifname == NULL || *ifname == '\0' || 624 strlcpy(spec->ifname, ifname, sizeof(spec->ifname)) >= 625 sizeof(spec->ifname) || 626 strlcpy(spec->drvname, ifname, sizeof(spec->drvname)) >= 627 sizeof(spec->drvname)) 628 { 629 errno = EINVAL; 630 return -1; 631 } 632 ep = strchr(spec->drvname, ':'); 633 if (ep) { 634 spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e); 635 if (e != 0) { 636 errno = e; 637 return -1; 638 } 639 *ep-- = '\0'; 640 } else { 641 spec->lun = -1; 642 ep = spec->drvname + strlen(spec->drvname) - 1; 643 } 644 strlcpy(spec->devname, spec->drvname, sizeof(spec->devname)); 645 while (ep > spec->drvname && isdigit((int)*ep)) 646 ep--; 647 if (*ep++ == ':') { 648 errno = EINVAL; 649 return -1; 650 } 651 spec->ppa = (int)strtoi(ep, NULL, 10, 0, INT_MAX, &e); 652 if (e != 0) 653 spec->ppa = -1; 654 *ep = '\0'; 655 656 return 0; 657 } 658 659 static struct interface * 660 if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name) 661 { 662 663 if (ifaces != NULL) { 664 struct if_spec spec; 665 struct interface *ifp; 666 667 if (name && if_nametospec(name, &spec) == -1) 668 return NULL; 669 670 TAILQ_FOREACH(ifp, ifaces, next) { 671 if ((name && strcmp(ifp->name, spec.devname) == 0) || 672 (!name && ifp->index == idx)) 673 return ifp; 674 } 675 } 676 677 errno = ENXIO; 678 return NULL; 679 } 680 681 struct interface * 682 if_find(struct if_head *ifaces, const char *name) 683 { 684 685 return if_findindexname(ifaces, 0, name); 686 } 687 688 struct interface * 689 if_findindex(struct if_head *ifaces, unsigned int idx) 690 { 691 692 return if_findindexname(ifaces, idx, NULL); 693 } 694 695 struct interface * 696 if_loopback(struct dhcpcd_ctx *ctx) 697 { 698 struct interface *ifp; 699 700 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 701 if (ifp->flags & IFF_LOOPBACK) 702 return ifp; 703 } 704 return NULL; 705 } 706 707 int 708 if_domtu(const struct interface *ifp, short int mtu) 709 { 710 int r; 711 struct ifreq ifr; 712 713 #ifdef __sun 714 if (mtu == 0) 715 return if_mtu_os(ifp); 716 #endif 717 718 memset(&ifr, 0, sizeof(ifr)); 719 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 720 ifr.ifr_mtu = mtu; 721 r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 722 if (r == -1) 723 return -1; 724 return ifr.ifr_mtu; 725 } 726 727 #ifdef ALIAS_ADDR 728 int 729 if_makealias(char *alias, size_t alias_len, const char *ifname, int lun) 730 { 731 732 if (lun == 0) 733 return strlcpy(alias, ifname, alias_len); 734 return snprintf(alias, alias_len, "%s:%u", ifname, lun); 735 } 736 #endif 737 738 struct interface * 739 if_findifpfromcmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, int *hoplimit) 740 { 741 struct cmsghdr *cm; 742 unsigned int ifindex = 0; 743 struct interface *ifp; 744 #if defined(INET) && defined(IP_PKTINFO) 745 struct in_pktinfo ipi; 746 #endif 747 #ifdef INET6 748 struct in6_pktinfo ipi6; 749 #else 750 UNUSED(hoplimit); 751 #endif 752 753 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(msg); 754 cm; 755 cm = (struct cmsghdr *)CMSG_NXTHDR(msg, cm)) 756 { 757 #if defined(INET) && defined(IP_PKTINFO) 758 if (cm->cmsg_level == IPPROTO_IP) { 759 switch(cm->cmsg_type) { 760 case IP_PKTINFO: 761 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi))) 762 continue; 763 memcpy(&ipi, CMSG_DATA(cm), sizeof(ipi)); 764 ifindex = (unsigned int)ipi.ipi_ifindex; 765 break; 766 } 767 } 768 #endif 769 #ifdef INET6 770 if (cm->cmsg_level == IPPROTO_IPV6) { 771 switch(cm->cmsg_type) { 772 case IPV6_PKTINFO: 773 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi6))) 774 continue; 775 memcpy(&ipi6, CMSG_DATA(cm), sizeof(ipi6)); 776 ifindex = (unsigned int)ipi6.ipi6_ifindex; 777 break; 778 case IPV6_HOPLIMIT: 779 if (cm->cmsg_len != CMSG_LEN(sizeof(int))) 780 continue; 781 if (hoplimit == NULL) 782 break; 783 memcpy(hoplimit, CMSG_DATA(cm), sizeof(int)); 784 break; 785 } 786 } 787 #endif 788 } 789 790 /* Find the receiving interface */ 791 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 792 if (ifp->index == ifindex) 793 break; 794 } 795 if (ifp == NULL) 796 errno = ESRCH; 797 return ifp; 798 } 799 800 int 801 xsocket(int domain, int type, int protocol) 802 { 803 int s; 804 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 805 int xflags, xtype = type; 806 #endif 807 #ifdef SO_RERROR 808 int on; 809 #endif 810 811 #ifndef HAVE_SOCK_CLOEXEC 812 if (xtype & SOCK_CLOEXEC) 813 type &= ~SOCK_CLOEXEC; 814 #endif 815 #ifndef HAVE_SOCK_NONBLOCK 816 if (xtype & SOCK_NONBLOCK) 817 type &= ~SOCK_NONBLOCK; 818 #endif 819 820 if ((s = socket(domain, type, protocol)) == -1) 821 return -1; 822 823 #ifndef HAVE_SOCK_CLOEXEC 824 if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 || 825 fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)) 826 goto out; 827 #endif 828 #ifndef HAVE_SOCK_NONBLOCK 829 if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 || 830 fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)) 831 goto out; 832 #endif 833 834 #ifdef SO_RERROR 835 /* Tell recvmsg(2) to return ENOBUFS if the receiving socket overflows. */ 836 on = 1; 837 if (setsockopt(s, SOL_SOCKET, SO_RERROR, &on, sizeof(on)) == -1) 838 logerr("%s: SO_RERROR", __func__); 839 #endif 840 841 return s; 842 843 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) 844 out: 845 close(s); 846 return -1; 847 #endif 848 } 849