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