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