xref: /dragonfly/contrib/dhcpcd/src/if.c (revision 89656a4e)
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 }
944