"Fossies" - the Fresh Open Source Software Archive

Member "dhcpcd-9.4.1/src/if.c" (22 Oct 2021, 23664 Bytes) of package /linux/misc/dhcpcd-9.4.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "if.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.4.0_vs_9.4.1.

    1 /* SPDX-License-Identifier: BSD-2-Clause */
    2 /*
    3  * dhcpcd - DHCP client daemon
    4  * Copyright (c) 2006-2021 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 <fcntl.h> /* Needs to be here for old Linux */
   35 
   36 #include "config.h"
   37 
   38 #include <net/if.h>
   39 #include <net/if_arp.h>
   40 #include <netinet/in.h>
   41 #ifdef AF_LINK
   42 #  include <net/if_dl.h>
   43 #  include <net/if_types.h>
   44 #  include <netinet/in_var.h>
   45 #  undef AF_PACKET  /* Newer Illumos defines this */
   46 #endif
   47 #ifdef AF_PACKET
   48 #  include <netpacket/packet.h>
   49 #endif
   50 #ifdef SIOCGIFMEDIA
   51 #  include <net/if_media.h>
   52 #endif
   53 #include <net/route.h>
   54 
   55 #include <ctype.h>
   56 #include <errno.h>
   57 #include <ifaddrs.h>
   58 #include <inttypes.h>
   59 #include <fnmatch.h>
   60 #include <stddef.h>
   61 #include <stdio.h>
   62 #include <stdlib.h>
   63 #include <string.h>
   64 #include <syslog.h>
   65 #include <unistd.h>
   66 
   67 #define ELOOP_QUEUE ELOOP_IF
   68 #include "common.h"
   69 #include "eloop.h"
   70 #include "dev.h"
   71 #include "dhcp.h"
   72 #include "dhcp6.h"
   73 #include "if.h"
   74 #include "if-options.h"
   75 #include "ipv4.h"
   76 #include "ipv4ll.h"
   77 #include "ipv6nd.h"
   78 #include "logerr.h"
   79 #include "privsep.h"
   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 #ifdef IFLR_ACTIVE
  114     ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  115     if (ctx->pf_link_fd == -1)
  116         return -1;
  117 #ifdef HAVE_CAPSICUM
  118     if (ps_rights_limit_ioctl(ctx->pf_link_fd) == -1)
  119         return -1;
  120 #endif
  121 #endif
  122 
  123     /* We use this socket for some operations without INET. */
  124     ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  125     if (ctx->pf_inet_fd == -1)
  126         return -1;
  127 
  128     return 0;
  129 }
  130 
  131 void
  132 if_closesockets(struct dhcpcd_ctx *ctx)
  133 {
  134 
  135     if (ctx->pf_inet_fd != -1)
  136         close(ctx->pf_inet_fd);
  137 #ifdef PF_LINK
  138     if (ctx->pf_link_fd != -1)
  139         close(ctx->pf_link_fd);
  140 #endif
  141 
  142     if (ctx->priv) {
  143         if_closesockets_os(ctx);
  144         free(ctx->priv);
  145     }
  146 }
  147 
  148 int
  149 if_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data, size_t len)
  150 {
  151 
  152 #ifdef PRIVSEP
  153     if (ctx->options & DHCPCD_PRIVSEP)
  154         return (int)ps_root_ioctl(ctx, req, data, len);
  155 #endif
  156     return ioctl(ctx->pf_inet_fd, req, data, len);
  157 }
  158 
  159 int
  160 if_getflags(struct interface *ifp)
  161 {
  162     struct ifreq ifr = { .ifr_flags = 0 };
  163 
  164     strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
  165     if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
  166         return -1;
  167     ifp->flags = (unsigned int)ifr.ifr_flags;
  168     return 0;
  169 }
  170 
  171 int
  172 if_setflag(struct interface *ifp, short setflag, short unsetflag)
  173 {
  174     struct ifreq ifr = { .ifr_flags = 0 };
  175     short oflags;
  176 
  177     strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
  178     if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
  179         return -1;
  180 
  181     oflags = ifr.ifr_flags;
  182     ifr.ifr_flags |= setflag;
  183     ifr.ifr_flags &= (short)~unsetflag;
  184     if (ifr.ifr_flags != oflags &&
  185         if_ioctl(ifp->ctx, SIOCSIFFLAGS, &ifr, sizeof(ifr)) == -1)
  186         return -1;
  187 
  188     /*
  189      * Do NOT set ifp->flags here.
  190      * We need to listen for flag updates from the kernel as they
  191      * need to sync with carrier.
  192      */
  193     return 0;
  194 }
  195 
  196 bool
  197 if_is_link_up(const struct interface *ifp)
  198 {
  199 
  200     return ifp->flags & IFF_UP &&
  201         (ifp->carrier != LINK_DOWN ||
  202          (ifp->options != NULL && !(ifp->options->options & DHCPCD_LINK)));
  203 }
  204 
  205 int
  206 if_randomisemac(struct interface *ifp)
  207 {
  208     uint32_t randnum;
  209     size_t hwlen = ifp->hwlen, rlen = 0;
  210     uint8_t buf[HWADDR_LEN], *bp = buf, *rp = (uint8_t *)&randnum;
  211     char sbuf[HWADDR_LEN * 3];
  212     int retval;
  213 
  214     if (hwlen == 0) {
  215         errno = ENOTSUP;
  216         return -1;
  217     }
  218     if (hwlen > sizeof(buf)) {
  219         errno = ENOBUFS;
  220         return -1;
  221     }
  222 
  223     for (; hwlen != 0; hwlen--) {
  224         if (rlen == 0) {
  225             randnum = arc4random();
  226             rp = (uint8_t *)&randnum;
  227             rlen = sizeof(randnum);
  228         }
  229         *bp++ = *rp++;
  230         rlen--;
  231     }
  232 
  233     /* Unicast address and locally administered. */
  234     buf[0] &= 0xFC;
  235     buf[0] |= 0x02;
  236 
  237     logdebugx("%s: hardware address randomised to %s",
  238         ifp->name,
  239         hwaddr_ntoa(buf, ifp->hwlen, sbuf, sizeof(sbuf)));
  240     retval = if_setmac(ifp, buf, ifp->hwlen);
  241     if (retval == 0)
  242         memcpy(ifp->hwaddr, buf, ifp->hwlen);
  243     return retval;
  244 }
  245 
  246 static int
  247 if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname)
  248 {
  249     int i;
  250 
  251     for (i = 0; i < ctx->ifcc; i++) {
  252         if (strcmp(ctx->ifcv[i], ifname) == 0)
  253             return 1;
  254     }
  255     return 0;
  256 }
  257 
  258 void
  259 if_markaddrsstale(struct if_head *ifs)
  260 {
  261     struct interface *ifp;
  262 
  263     TAILQ_FOREACH(ifp, ifs, next) {
  264 #ifdef INET
  265         ipv4_markaddrsstale(ifp);
  266 #endif
  267 #ifdef INET6
  268         ipv6_markaddrsstale(ifp, 0);
  269 #endif
  270     }
  271 }
  272 
  273 void
  274 if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
  275     struct ifaddrs **ifaddrs)
  276 {
  277     struct ifaddrs *ifa;
  278     struct interface *ifp;
  279 #ifdef INET
  280     const struct sockaddr_in *addr, *net, *brd;
  281 #endif
  282 #ifdef INET6
  283     struct sockaddr_in6 *sin6, *net6;
  284 #endif
  285     int addrflags;
  286 
  287     for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) {
  288         if (ifa->ifa_addr == NULL)
  289             continue;
  290         if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL)
  291             continue;
  292 #ifdef HAVE_IFADDRS_ADDRFLAGS
  293         addrflags = (int)ifa->ifa_addrflags;
  294 #endif
  295         switch(ifa->ifa_addr->sa_family) {
  296 #ifdef INET
  297         case AF_INET:
  298             addr = (void *)ifa->ifa_addr;
  299             net = (void *)ifa->ifa_netmask;
  300             if (ifa->ifa_flags & IFF_POINTOPOINT)
  301                 brd = (void *)ifa->ifa_dstaddr;
  302             else
  303                 brd = (void *)ifa->ifa_broadaddr;
  304 #ifndef HAVE_IFADDRS_ADDRFLAGS
  305             addrflags = if_addrflags(ifp, &addr->sin_addr,
  306                 ifa->ifa_name);
  307             if (addrflags == -1) {
  308                 if (errno != EEXIST && errno != EADDRNOTAVAIL) {
  309                     char dbuf[INET_ADDRSTRLEN];
  310                     const char *dbp;
  311 
  312                     dbp = inet_ntop(AF_INET, &addr->sin_addr,
  313                         dbuf, sizeof(dbuf));
  314                     logerr("%s: if_addrflags: %s%%%s",
  315                         __func__, dbp, ifp->name);
  316                 }
  317                 continue;
  318             }
  319 #endif
  320             ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
  321                 &addr->sin_addr, &net->sin_addr,
  322                 brd ? &brd->sin_addr : NULL, addrflags, 0);
  323             break;
  324 #endif
  325 #ifdef INET6
  326         case AF_INET6:
  327             sin6 = (void *)ifa->ifa_addr;
  328             net6 = (void *)ifa->ifa_netmask;
  329 
  330 #ifdef __KAME__
  331             if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
  332                 /* Remove the scope from the address */
  333                 sin6->sin6_addr.s6_addr[2] =
  334                     sin6->sin6_addr.s6_addr[3] = '\0';
  335 #endif
  336 #ifndef HAVE_IFADDRS_ADDRFLAGS
  337             addrflags = if_addrflags6(ifp, &sin6->sin6_addr,
  338                 ifa->ifa_name);
  339             if (addrflags == -1) {
  340                 if (errno != EEXIST && errno != EADDRNOTAVAIL) {
  341                     char dbuf[INET6_ADDRSTRLEN];
  342                     const char *dbp;
  343 
  344                     dbp = inet_ntop(AF_INET6, &sin6->sin6_addr,
  345                         dbuf, sizeof(dbuf));
  346                     logerr("%s: if_addrflags6: %s%%%s",
  347                         __func__, dbp, ifp->name);
  348                 }
  349                 continue;
  350             }
  351 #endif
  352             ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
  353                 ifa->ifa_name, &sin6->sin6_addr,
  354                 ipv6_prefixlen(&net6->sin6_addr), addrflags, 0);
  355             break;
  356 #endif
  357         }
  358     }
  359 
  360 #ifdef PRIVSEP_GETIFADDRS
  361     if (IN_PRIVSEP(ctx))
  362         free(*ifaddrs);
  363     else
  364 #endif
  365         freeifaddrs(*ifaddrs);
  366     *ifaddrs = NULL;
  367 }
  368 
  369 void
  370 if_deletestaleaddrs(struct if_head *ifs)
  371 {
  372     struct interface *ifp;
  373 
  374     TAILQ_FOREACH(ifp, ifs, next) {
  375 #ifdef INET
  376         ipv4_deletestaleaddrs(ifp);
  377 #endif
  378 #ifdef INET6
  379         ipv6_deletestaleaddrs(ifp);
  380 #endif
  381     }
  382 }
  383 
  384 bool
  385 if_valid_hwaddr(const uint8_t *hwaddr, size_t hwlen)
  386 {
  387     size_t i;
  388     bool all_zeros, all_ones;
  389 
  390     all_zeros = all_ones = true;
  391     for (i = 0; i < hwlen; i++) {
  392         if (hwaddr[i] != 0x00)
  393             all_zeros = false;
  394         if (hwaddr[i] != 0xff)
  395             all_ones = false;
  396         if (!all_zeros && !all_ones)
  397             return true;
  398     }
  399     return false;
  400 }
  401 
  402 #if defined(AF_PACKET) && !defined(AF_LINK)
  403 static unsigned int
  404 if_check_arphrd(struct interface *ifp, unsigned int active, bool if_noconf)
  405 {
  406 
  407     switch(ifp->hwtype) {
  408     case ARPHRD_ETHER:  /* FALLTHROUGH */
  409     case ARPHRD_IEEE1394:   /* FALLTHROUGH */
  410     case ARPHRD_INFINIBAND: /* FALLTHROUGH */
  411     case ARPHRD_NONE:   /* FALLTHROUGH */
  412         break;
  413     case ARPHRD_LOOPBACK:
  414     case ARPHRD_PPP:
  415         if (if_noconf && active) {
  416             logdebugx("%s: ignoring due to interface type and"
  417                 " no config",
  418                 ifp->name);
  419             active = IF_INACTIVE;
  420         }
  421         break;
  422     default:
  423         if (active) {
  424             int i;
  425 
  426             if (if_noconf)
  427                 active = IF_INACTIVE;
  428             i = active ? LOG_WARNING : LOG_DEBUG;
  429             logmessage(i, "%s: unsupported"
  430                 " interface type 0x%.2x",
  431                 ifp->name, ifp->hwtype);
  432         }
  433         break;
  434     }
  435 
  436     return active;
  437 }
  438 #endif
  439 
  440 struct if_head *
  441 if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
  442     int argc, char * const *argv)
  443 {
  444     struct ifaddrs *ifa;
  445     int i;
  446     unsigned int active;
  447     struct if_head *ifs;
  448     struct interface *ifp;
  449     struct if_spec spec;
  450     bool if_noconf;
  451 #ifdef AF_LINK
  452     const struct sockaddr_dl *sdl;
  453 #ifdef IFLR_ACTIVE
  454     struct if_laddrreq iflr = { .flags = IFLR_PREFIX };
  455 #endif
  456 #elif defined(AF_PACKET)
  457     const struct sockaddr_ll *sll;
  458 #endif
  459 #if defined(SIOCGIFPRIORITY)
  460     struct ifreq ifr;
  461 #endif
  462 
  463     if ((ifs = malloc(sizeof(*ifs))) == NULL) {
  464         logerr(__func__);
  465         return NULL;
  466     }
  467     TAILQ_INIT(ifs);
  468 
  469 #ifdef PRIVSEP_GETIFADDRS
  470     if (ctx->options & DHCPCD_PRIVSEP) {
  471         if (ps_root_getifaddrs(ctx, ifaddrs) == -1) {
  472             logerr("ps_root_getifaddrs");
  473             free(ifs);
  474             return NULL;
  475         }
  476     } else
  477 #endif
  478     if (getifaddrs(ifaddrs) == -1) {
  479         logerr("getifaddrs");
  480         free(ifs);
  481         return NULL;
  482     }
  483 
  484     for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) {
  485         if (ifa->ifa_addr != NULL) {
  486 #ifdef AF_LINK
  487             if (ifa->ifa_addr->sa_family != AF_LINK)
  488                 continue;
  489 #elif defined(AF_PACKET)
  490             if (ifa->ifa_addr->sa_family != AF_PACKET)
  491                 continue;
  492 #endif
  493         }
  494         if (if_nametospec(ifa->ifa_name, &spec) != 0)
  495             continue;
  496 
  497         /* It's possible for an interface to have >1 AF_LINK.
  498          * For our purposes, we use the first one. */
  499         TAILQ_FOREACH(ifp, ifs, next) {
  500             if (strcmp(ifp->name, spec.devname) == 0)
  501                 break;
  502         }
  503         if (ifp)
  504             continue;
  505 
  506         if (argc > 0) {
  507             for (i = 0; i < argc; i++) {
  508                 if (strcmp(argv[i], spec.devname) == 0)
  509                     break;
  510             }
  511             active = (i == argc) ? IF_INACTIVE : IF_ACTIVE_USER;
  512         } else {
  513             /* -1 means we're discovering against a specific
  514              * interface, but we still need the below rules
  515              * to apply. */
  516             if (argc == -1 && strcmp(argv[0], spec.devname) != 0)
  517                 continue;
  518             active = ctx->options & DHCPCD_INACTIVE ?
  519                 IF_INACTIVE: IF_ACTIVE_USER;
  520         }
  521 
  522         for (i = 0; i < ctx->ifdc; i++)
  523             if (fnmatch(ctx->ifdv[i], spec.devname, 0) == 0)
  524                 break;
  525         if (i < ctx->ifdc)
  526             active = IF_INACTIVE;
  527         for (i = 0; i < ctx->ifc; i++)
  528             if (fnmatch(ctx->ifv[i], spec.devname, 0) == 0)
  529                 break;
  530         if (ctx->ifc && i == ctx->ifc)
  531             active = IF_INACTIVE;
  532         for (i = 0; i < ctx->ifac; i++)
  533             if (fnmatch(ctx->ifav[i], spec.devname, 0) == 0)
  534                 break;
  535         if (ctx->ifac && i == ctx->ifac)
  536             active = IF_INACTIVE;
  537 
  538 #ifdef PLUGIN_DEV
  539         /* Ensure that the interface name has settled */
  540         if (!dev_initialised(ctx, spec.devname)) {
  541             logdebugx("%s: waiting for interface to initialise",
  542                 spec.devname);
  543             continue;
  544         }
  545 #endif
  546 
  547         if (if_vimaster(ctx, spec.devname) == 1) {
  548             int loglevel = argc != 0 ? LOG_ERR : LOG_DEBUG;
  549             logmessage(loglevel,
  550                 "%s: is a Virtual Interface Master, skipping",
  551                 spec.devname);
  552             continue;
  553         }
  554 
  555         if_noconf = ((argc == 0 || argc == -1) && ctx->ifac == 0 &&
  556             !if_hasconf(ctx, spec.devname));
  557 
  558         /* Don't allow some reserved interface names unless explicit. */
  559         if (if_noconf && if_ignore(ctx, spec.devname)) {
  560             logdebugx("%s: ignoring due to interface type and"
  561                 " no config", spec.devname);
  562             active = IF_INACTIVE;
  563         }
  564 
  565         ifp = calloc(1, sizeof(*ifp));
  566         if (ifp == NULL) {
  567             logerr(__func__);
  568             break;
  569         }
  570         ifp->ctx = ctx;
  571         strlcpy(ifp->name, spec.devname, sizeof(ifp->name));
  572         ifp->flags = ifa->ifa_flags;
  573 
  574         if (ifa->ifa_addr != NULL) {
  575 #ifdef AF_LINK
  576             sdl = (const void *)ifa->ifa_addr;
  577 
  578 #ifdef IFLR_ACTIVE
  579             /* We need to check for active address */
  580             strlcpy(iflr.iflr_name, ifp->name,
  581                 sizeof(iflr.iflr_name));
  582             memcpy(&iflr.addr, ifa->ifa_addr,
  583                 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
  584             iflr.flags = IFLR_PREFIX;
  585             iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY;
  586             if (ioctl(ctx->pf_link_fd, SIOCGLIFADDR, &iflr) == -1 ||
  587                 !(iflr.flags & IFLR_ACTIVE))
  588             {
  589                 if_free(ifp);
  590                 continue;
  591             }
  592 #endif
  593 
  594             ifp->index = sdl->sdl_index;
  595             switch(sdl->sdl_type) {
  596 #ifdef IFT_BRIDGE
  597             case IFT_BRIDGE: /* FALLTHROUGH */
  598 #endif
  599 #ifdef IFT_PROPVIRTUAL
  600             case IFT_PROPVIRTUAL: /* FALLTHROUGH */
  601 #endif
  602 #ifdef IFT_TUNNEL
  603             case IFT_TUNNEL: /* FALLTHROUGH */
  604 #endif
  605             case IFT_LOOP: /* FALLTHROUGH */
  606             case IFT_PPP:
  607                 /* Don't allow unless explicit */
  608                 if (if_noconf && active) {
  609                     logdebugx("%s: ignoring due to"
  610                         " interface type and"
  611                         " no config",
  612                         ifp->name);
  613                     active = IF_INACTIVE;
  614                 }
  615                 __fallthrough; /* appease gcc */
  616                 /* FALLTHROUGH */
  617 #ifdef IFT_L2VLAN
  618             case IFT_L2VLAN: /* FALLTHROUGH */
  619 #endif
  620 #ifdef IFT_L3IPVLAN
  621             case IFT_L3IPVLAN: /* FALLTHROUGH */
  622 #endif
  623             case IFT_ETHER:
  624                 ifp->hwtype = ARPHRD_ETHER;
  625                 break;
  626 #ifdef IFT_IEEE1394
  627             case IFT_IEEE1394:
  628                 ifp->hwtype = ARPHRD_IEEE1394;
  629                 break;
  630 #endif
  631 #ifdef IFT_INFINIBAND
  632             case IFT_INFINIBAND:
  633                 ifp->hwtype = ARPHRD_INFINIBAND;
  634                 break;
  635 #endif
  636             default:
  637                 /* Don't allow unless explicit */
  638                 if (active) {
  639                     if (if_noconf)
  640                         active = IF_INACTIVE;
  641                     i = active ? LOG_WARNING : LOG_DEBUG;
  642                     logmessage(i, "%s: unsupported"
  643                         " interface type 0x%.2x",
  644                         ifp->name, sdl->sdl_type);
  645                 }
  646                 /* Pretend it's ethernet */
  647                 ifp->hwtype = ARPHRD_ETHER;
  648                 break;
  649             }
  650             ifp->hwlen = sdl->sdl_alen;
  651             memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
  652 #elif defined(AF_PACKET)
  653             sll = (const void *)ifa->ifa_addr;
  654             ifp->index = (unsigned int)sll->sll_ifindex;
  655             ifp->hwtype = sll->sll_hatype;
  656             ifp->hwlen = sll->sll_halen;
  657             if (ifp->hwlen != 0)
  658                 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
  659             active = if_check_arphrd(ifp, active, if_noconf);
  660 #endif
  661         }
  662 #ifdef __linux__
  663         else {
  664             struct ifreq ifr = { .ifr_flags = 0 };
  665 
  666             /* This is a huge bug in getifaddrs(3) as there
  667              * is no reason why this can't be returned in
  668              * ifa_addr. */
  669             strlcpy(ifr.ifr_name, ifa->ifa_name,
  670                 sizeof(ifr.ifr_name));
  671             if (ioctl(ctx->pf_inet_fd, SIOCGIFHWADDR, &ifr) == -1)
  672                 logerr("%s: SIOCGIFHWADDR", ifa->ifa_name);
  673             ifp->hwtype = ifr.ifr_hwaddr.sa_family;
  674             if (ioctl(ctx->pf_inet_fd, SIOCGIFINDEX, &ifr) == -1)
  675                 logerr("%s: SIOCGIFINDEX", ifa->ifa_name);
  676             ifp->index = (unsigned int)ifr.ifr_ifindex;
  677             if_check_arphrd(ifp, active, if_noconf);
  678         }
  679 #endif
  680 
  681         if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) {
  682             /* Handle any platform init for the interface */
  683             if (active != IF_INACTIVE && if_init(ifp) == -1) {
  684                 logerr("%s: if_init", ifp->name);
  685                 if_free(ifp);
  686                 continue;
  687             }
  688         }
  689 
  690         ifp->vlanid = if_vlanid(ifp);
  691 
  692 #ifdef SIOCGIFPRIORITY
  693         /* Respect the interface priority */
  694         memset(&ifr, 0, sizeof(ifr));
  695         strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
  696         if (pioctl(ctx, SIOCGIFPRIORITY, &ifr, sizeof(ifr)) == 0)
  697             ifp->metric = (unsigned int)ifr.ifr_metric;
  698         if_getssid(ifp);
  699 #else
  700         /* Leave a low portion for user config */
  701         ifp->metric = RTMETRIC_BASE + ifp->index;
  702         if (if_getssid(ifp) != -1) {
  703             ifp->wireless = true;
  704             ifp->metric += RTMETRIC_WIRELESS;
  705         }
  706 #endif
  707 
  708         ifp->active = active;
  709         ifp->carrier = if_carrier(ifp, ifa->ifa_data);
  710         TAILQ_INSERT_TAIL(ifs, ifp, next);
  711     }
  712 
  713     return ifs;
  714 }
  715 
  716 /*
  717  * eth0.100:2 OR eth0i100:2 (seems to be NetBSD xvif(4) only)
  718  *
  719  * drvname == eth
  720  * devname == eth0.100 OR eth0i100
  721  * ppa = 0
  722  * lun = 2
  723  */
  724 int
  725 if_nametospec(const char *ifname, struct if_spec *spec)
  726 {
  727     char *ep, *pp;
  728     int e;
  729 
  730     if (ifname == NULL || *ifname == '\0' ||
  731         strlcpy(spec->ifname, ifname, sizeof(spec->ifname)) >=
  732         sizeof(spec->ifname) ||
  733         strlcpy(spec->drvname, ifname, sizeof(spec->drvname)) >=
  734         sizeof(spec->drvname))
  735     {
  736         errno = EINVAL;
  737         return -1;
  738     }
  739 
  740     /* :N is an alias */
  741     ep = strchr(spec->drvname, ':');
  742     if (ep) {
  743         spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e);
  744         if (e != 0) {
  745             errno = e;
  746             return -1;
  747         }
  748         *ep = '\0';
  749 #ifdef __sun
  750         ep--;
  751 #endif
  752     } else {
  753         spec->lun = -1;
  754 #ifdef __sun
  755         ep = spec->drvname + strlen(spec->drvname) - 1;
  756 #endif
  757     }
  758 
  759     strlcpy(spec->devname, spec->drvname, sizeof(spec->devname));
  760 #ifdef __sun
  761     /* Solaris has numbers in the driver name, such as e1000g */
  762     while (ep > spec->drvname && isdigit((int)*ep))
  763         ep--;
  764     if (*ep++ == ':') {
  765         errno = EINVAL;
  766         return -1;
  767     }
  768 #else
  769     /* BSD and Linux no not have numbers in the driver name */
  770     for (ep = spec->drvname; *ep != '\0' && !isdigit((int)*ep); ep++) {
  771         if (*ep == ':') {
  772             errno = EINVAL;
  773             return -1;
  774         }
  775     }
  776 #endif
  777     spec->ppa = (int)strtoi(ep, &pp, 10, 0, INT_MAX, &e);
  778     *ep = '\0';
  779 
  780 #ifndef __sun
  781     /*
  782      * . is used for VLAN style names
  783      * i is used on NetBSD for xvif interfaces
  784      */
  785     if (pp != NULL && (*pp == '.' || *pp == 'i')) {
  786         spec->vlid = (int)strtoi(pp + 1, NULL, 10, 0, INT_MAX, &e);
  787         if (e)
  788             spec->vlid = -1;
  789     } else
  790 #endif
  791         spec->vlid = -1;
  792 
  793     return 0;
  794 }
  795 
  796 static struct interface *
  797 if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name)
  798 {
  799 
  800     if (ifaces != NULL) {
  801         struct if_spec spec;
  802         struct interface *ifp;
  803 
  804         if (name && if_nametospec(name, &spec) == -1)
  805             return NULL;
  806 
  807         TAILQ_FOREACH(ifp, ifaces, next) {
  808             if ((name && strcmp(ifp->name, spec.devname) == 0) ||
  809                 (!name && ifp->index == idx))
  810                 return ifp;
  811         }
  812     }
  813 
  814     errno = ENXIO;
  815     return NULL;
  816 }
  817 
  818 struct interface *
  819 if_find(struct if_head *ifaces, const char *name)
  820 {
  821 
  822     return if_findindexname(ifaces, 0, name);
  823 }
  824 
  825 struct interface *
  826 if_findindex(struct if_head *ifaces, unsigned int idx)
  827 {
  828 
  829     return if_findindexname(ifaces, idx, NULL);
  830 }
  831 
  832 struct interface *
  833 if_loopback(struct dhcpcd_ctx *ctx)
  834 {
  835     struct interface *ifp;
  836 
  837     TAILQ_FOREACH(ifp, ctx->ifaces, next) {
  838         if (ifp->flags & IFF_LOOPBACK)
  839             return ifp;
  840     }
  841     return NULL;
  842 }
  843 
  844 int
  845 if_domtu(const struct interface *ifp, short int mtu)
  846 {
  847     int r;
  848     struct ifreq ifr;
  849 
  850 #ifdef __sun
  851     if (mtu == 0)
  852         return if_mtu_os(ifp);
  853 #endif
  854 
  855     memset(&ifr, 0, sizeof(ifr));
  856     strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
  857     ifr.ifr_mtu = mtu;
  858     if (mtu != 0)
  859         r = if_ioctl(ifp->ctx, SIOCSIFMTU, &ifr, sizeof(ifr));
  860     else
  861         r = pioctl(ifp->ctx, SIOCGIFMTU, &ifr, sizeof(ifr));
  862 
  863     if (r == -1)
  864         return -1;
  865     return ifr.ifr_mtu;
  866 }
  867 
  868 #ifdef ALIAS_ADDR
  869 int
  870 if_makealias(char *alias, size_t alias_len, const char *ifname, int lun)
  871 {
  872 
  873     if (lun == 0)
  874         return strlcpy(alias, ifname, alias_len);
  875     return snprintf(alias, alias_len, "%s:%u", ifname, lun);
  876 }
  877 #endif
  878 
  879 struct interface *
  880 if_findifpfromcmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, int *hoplimit)
  881 {
  882     struct cmsghdr *cm;
  883     unsigned int ifindex = 0;
  884     struct interface *ifp;
  885 #ifdef INET
  886 #ifdef IP_RECVIF
  887     struct sockaddr_dl sdl;
  888 #else
  889     struct in_pktinfo ipi;
  890 #endif
  891 #endif
  892 #ifdef INET6
  893     struct in6_pktinfo ipi6;
  894 #else
  895     UNUSED(hoplimit);
  896 #endif
  897 
  898     for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(msg);
  899          cm;
  900          cm = (struct cmsghdr *)CMSG_NXTHDR(msg, cm))
  901     {
  902 #ifdef INET
  903         if (cm->cmsg_level == IPPROTO_IP) {
  904             switch(cm->cmsg_type) {
  905 #ifdef IP_RECVIF
  906             case IP_RECVIF:
  907                 if (cm->cmsg_len <
  908                     offsetof(struct sockaddr_dl, sdl_index) +
  909                     sizeof(sdl.sdl_index))
  910                     continue;
  911                 memcpy(&sdl, CMSG_DATA(cm),
  912                     MIN(sizeof(sdl), cm->cmsg_len));
  913                 ifindex = sdl.sdl_index;
  914                 break;
  915 #else
  916             case IP_PKTINFO:
  917                 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi)))
  918                     continue;
  919                 memcpy(&ipi, CMSG_DATA(cm), sizeof(ipi));
  920                 ifindex = (unsigned int)ipi.ipi_ifindex;
  921                 break;
  922 #endif
  923             }
  924         }
  925 #endif
  926 #ifdef INET6
  927         if (cm->cmsg_level == IPPROTO_IPV6) {
  928             switch(cm->cmsg_type) {
  929             case IPV6_PKTINFO:
  930                 if (cm->cmsg_len != CMSG_LEN(sizeof(ipi6)))
  931                     continue;
  932                 memcpy(&ipi6, CMSG_DATA(cm), sizeof(ipi6));
  933                 ifindex = (unsigned int)ipi6.ipi6_ifindex;
  934                 break;
  935             case IPV6_HOPLIMIT:
  936                 if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
  937                     continue;
  938                 if (hoplimit == NULL)
  939                     break;
  940                 memcpy(hoplimit, CMSG_DATA(cm), sizeof(int));
  941                 break;
  942             }
  943         }
  944 #endif
  945     }
  946 
  947     /* Find the receiving interface */
  948     TAILQ_FOREACH(ifp, ctx->ifaces, next) {
  949         if (ifp->index == ifindex)
  950             break;
  951     }
  952     if (ifp == NULL)
  953         errno = ESRCH;
  954     return ifp;
  955 }
  956 
  957 int
  958 xsocket(int domain, int type, int protocol)
  959 {
  960     int s;
  961 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
  962     int xflags, xtype = type;
  963 #endif
  964 
  965 #ifndef HAVE_SOCK_CLOEXEC
  966     if (xtype & SOCK_CLOEXEC)
  967         type &= ~SOCK_CLOEXEC;
  968 #endif
  969 #ifndef HAVE_SOCK_NONBLOCK
  970     if (xtype & SOCK_NONBLOCK)
  971         type &= ~SOCK_NONBLOCK;
  972 #endif
  973 
  974     if ((s = socket(domain, type, protocol)) == -1)
  975         return -1;
  976 
  977 #ifndef HAVE_SOCK_CLOEXEC
  978     if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 ||
  979         fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1))
  980         goto out;
  981 #endif
  982 #ifndef HAVE_SOCK_NONBLOCK
  983     if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 ||
  984         fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1))
  985         goto out;
  986 #endif
  987 
  988     return s;
  989 
  990 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
  991 out:
  992     close(s);
  993     return -1;
  994 #endif
  995 }
  996 
  997 int
  998 xsocketpair(int domain, int type, int protocol, int fd[2])
  999 {
 1000     int s;
 1001 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
 1002     int xflags, xtype = type;
 1003 #endif
 1004 
 1005 #ifndef HAVE_SOCK_CLOEXEC
 1006     if (xtype & SOCK_CLOEXEC)
 1007         type &= ~SOCK_CLOEXEC;
 1008 #endif
 1009 #ifndef HAVE_SOCK_NONBLOCK
 1010     if (xtype & SOCK_NONBLOCK)
 1011         type &= ~SOCK_NONBLOCK;
 1012 #endif
 1013 
 1014     if ((s = socketpair(domain, type, protocol, fd)) == -1)
 1015         return -1;
 1016 
 1017 #ifndef HAVE_SOCK_CLOEXEC
 1018     if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(fd[0], F_GETFD)) == -1 ||
 1019         fcntl(fd[0], F_SETFD, xflags | FD_CLOEXEC) == -1))
 1020         goto out;
 1021     if ((xtype & SOCK_CLOEXEC) && ((xflags = fcntl(fd[1], F_GETFD)) == -1 ||
 1022         fcntl(fd[1], F_SETFD, xflags | FD_CLOEXEC) == -1))
 1023         goto out;
 1024 #endif
 1025 #ifndef HAVE_SOCK_NONBLOCK
 1026     if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(fd[0], F_GETFL)) == -1 ||
 1027         fcntl(fd[0], F_SETFL, xflags | O_NONBLOCK) == -1))
 1028         goto out;
 1029     if ((xtype & SOCK_NONBLOCK) && ((xflags = fcntl(fd[1], F_GETFL)) == -1 ||
 1030         fcntl(fd[1], F_SETFL, xflags | O_NONBLOCK) == -1))
 1031         goto out;
 1032 #endif
 1033 
 1034     return s;
 1035 
 1036 #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
 1037 out:
 1038     close(fd[0]);
 1039     close(fd[1]);
 1040     return -1;
 1041 #endif
 1042 }