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