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