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