xref: /netbsd/external/bsd/dhcpcd/dist/src/if-bsd.c (revision ae1d8458)
1 /*
2  * BSD interface driver for dhcpcd
3  * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
4  * All rights reserved
5 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/ioctl.h>
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/sysctl.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/uio.h>
36 #include <sys/utsname.h>
37 
38 #include "config.h"
39 
40 #include <arpa/inet.h>
41 #include <net/bpf.h>
42 #include <net/if.h>
43 #include <net/if_dl.h>
44 #include <net/if_media.h>
45 #include <net/route.h>
46 #include <netinet/if_ether.h>
47 #include <netinet/in.h>
48 #include <netinet/in_var.h>
49 #include <netinet6/in6_var.h>
50 #include <netinet6/nd6.h>
51 #ifdef __NetBSD__
52 #include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */
53 #else
54 #include <net/if_vlan_var.h>
55 #endif
56 #ifdef __DragonFly__
57 #  include <netproto/802_11/ieee80211_ioctl.h>
58 #elif __APPLE__
59   /* FIXME: Add apple includes so we can work out SSID */
60 #else
61 #  include <net80211/ieee80211.h>
62 #  include <net80211/ieee80211_ioctl.h>
63 #endif
64 
65 #include <assert.h>
66 #include <errno.h>
67 #include <fcntl.h>
68 #include <fnmatch.h>
69 #include <paths.h>
70 #include <stddef.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <unistd.h>
75 
76 #if defined(OpenBSD) && OpenBSD >= 201411
77 /* OpenBSD dropped the global setting from sysctl but left the #define
78  * which causes a EPERM error when trying to use it.
79  * I think both the error and keeping the define are wrong, so we #undef it. */
80 #undef IPV6CTL_ACCEPT_RTADV
81 #endif
82 
83 #include "common.h"
84 #include "dhcp.h"
85 #include "if.h"
86 #include "if-options.h"
87 #include "ipv4.h"
88 #include "ipv4ll.h"
89 #include "ipv6.h"
90 #include "ipv6nd.h"
91 #include "logerr.h"
92 #include "route.h"
93 #include "sa.h"
94 
95 #ifndef RT_ROUNDUP
96 #define RT_ROUNDUP(a)							      \
97 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
98 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
99 #endif
100 
101 #ifdef INET6
102 static void ifa_setscope(struct sockaddr_in6 *, unsigned int);
103 static unsigned int ifa_getscope(const struct sockaddr_in6 *);
104 #endif
105 
106 struct priv {
107 	int pf_inet6_fd;
108 };
109 
110 struct rtm
111 {
112 	struct rt_msghdr hdr;
113 	char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
114 };
115 
116 int
117 if_init(__unused struct interface *iface)
118 {
119 	/* BSD promotes secondary address by default */
120 	return 0;
121 }
122 
123 int
124 if_conf(__unused struct interface *iface)
125 {
126 	/* No extra checks needed on BSD */
127 	return 0;
128 }
129 
130 int
131 if_opensockets_os(struct dhcpcd_ctx *ctx)
132 {
133 	struct priv *priv;
134 	int n;
135 #if defined(RO_MSGFILTER) || defined(ROUTE_MSGFILTER)
136 	unsigned char msgfilter[] = {
137 	    RTM_IFINFO,
138 #ifdef RTM_IFANNOUNCE
139 	    RTM_IFANNOUNCE,
140 #endif
141 	    RTM_ADD, RTM_CHANGE, RTM_DELETE,
142 #ifdef RTM_CHGADDR
143 	    RTM_CHGADDR,
144 #endif
145 	    RTM_NEWADDR, RTM_DELADDR
146 	};
147 #ifdef ROUTE_MSGFILTER
148 	unsigned int i, msgfilter_mask;
149 #endif
150 #endif
151 
152 	if ((priv = malloc(sizeof(*priv))) == NULL)
153 		return -1;
154 	ctx->priv = priv;
155 
156 #ifdef INET6
157 	priv->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
158 	/* Don't return an error so we at least work on kernels witout INET6
159 	 * even though we expect INET6 support.
160 	 * We will fail noisily elsewhere anyway. */
161 #else
162 	priv->pf_inet6_fd = -1;
163 #endif
164 
165 #define SOCK_FLAGS	(SOCK_CLOEXEC | SOCK_NONBLOCK)
166 	ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW | SOCK_FLAGS, AF_UNSPEC);
167 #undef SOCK_FLAGS
168 	if (ctx->link_fd == -1)
169 		return -1;
170 
171 	/* Ignore our own route(4) messages.
172 	 * Sadly there is no way of doing this for route(4) messages
173 	 * generated from addresses we add/delete. */
174 	n = 0;
175 	if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_USELOOPBACK,
176 	    &n, sizeof(n)) == -1)
177 		logerr("%s: SO_USELOOPBACK", __func__);
178 
179 #if defined(RO_MSGFILTER)
180 	if (setsockopt(ctx->link_fd, PF_ROUTE, RO_MSGFILTER,
181 	    &msgfilter, sizeof(msgfilter)) == -1)
182 		logerr(__func__);
183 #elif defined(ROUTE_MSGFILTER)
184 	/* Convert the array into a bitmask. */
185 	msgfilter_mask = 0;
186 	for (i = 0; i < __arraycount(msgfilter); i++)
187 		msgfilter_mask |= ROUTE_FILTER(msgfilter[i]);
188 	if (setsockopt(ctx->link_fd, PF_ROUTE, ROUTE_MSGFILTER,
189 	    &msgfilter_mask, sizeof(msgfilter_mask)) == -1)
190 		logerr(__func__);
191 #endif
192 
193 	return 0;
194 }
195 
196 void
197 if_closesockets_os(struct dhcpcd_ctx *ctx)
198 {
199 	struct priv *priv;
200 
201 	priv = (struct priv *)ctx->priv;
202 	if (priv->pf_inet6_fd != -1)
203 		close(priv->pf_inet6_fd);
204 }
205 
206 int
207 if_carrier(struct interface *ifp)
208 {
209 	struct ifmediareq ifmr = { .ifm_status = 0 };
210 
211 	strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
212 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 ||
213 	    !(ifmr.ifm_status & IFM_AVALID))
214 		return LINK_UNKNOWN;
215 
216 	return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
217 }
218 
219 static void
220 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
221 {
222 
223 	memset(sdl, 0, sizeof(*sdl));
224 	sdl->sdl_family = AF_LINK;
225 	sdl->sdl_len = sizeof(*sdl);
226 	sdl->sdl_nlen = sdl->sdl_alen = sdl->sdl_slen = 0;
227 	sdl->sdl_index = (unsigned short)ifp->index;
228 }
229 
230 #if defined(SIOCG80211NWID) || defined(SIOCGETVLAN)
231 static int if_direct_ioctl(int s, const char *ifname,
232     unsigned long cmd, void *data)
233 {
234 
235 	strlcpy(data, ifname, IFNAMSIZ);
236 	return ioctl(s, cmd, data);
237 }
238 
239 static int if_indirect_ioctl(int s, const char *ifname,
240     unsigned long cmd, void *data)
241 {
242 	struct ifreq ifr;
243 
244 	memset(&ifr, 0, sizeof(ifr));
245 	ifr.ifr_data = data;
246 	return if_direct_ioctl(s, ifname, cmd, &ifr);
247 }
248 #endif
249 
250 static int
251 if_getssid1(int s, const char *ifname, void *ssid)
252 {
253 	int retval = -1;
254 #if defined(SIOCG80211NWID)
255 	struct ieee80211_nwid nwid;
256 #elif defined(IEEE80211_IOC_SSID)
257 	struct ieee80211req ireq;
258 	char nwid[IEEE80211_NWID_LEN];
259 #endif
260 
261 #if defined(SIOCG80211NWID) /* NetBSD */
262 	memset(&nwid, 0, sizeof(nwid));
263 	if (if_indirect_ioctl(s, ifname, SIOCG80211NWID, &nwid) == 0) {
264 		if (ssid == NULL)
265 			retval = nwid.i_len;
266 		else if (nwid.i_len > IF_SSIDLEN)
267 			errno = ENOBUFS;
268 		else {
269 			retval = nwid.i_len;
270 			memcpy(ssid, nwid.i_nwid, nwid.i_len);
271 		}
272 	}
273 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
274 	memset(&ireq, 0, sizeof(ireq));
275 	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
276 	ireq.i_type = IEEE80211_IOC_SSID;
277 	ireq.i_val = -1;
278 	memset(nwid, 0, sizeof(nwid));
279 	ireq.i_data = &nwid;
280 	if (ioctl(s, SIOCG80211, &ireq) == 0) {
281 		if (ssid == NULL)
282 			retval = ireq.i_len;
283 		else if (ireq.i_len > IF_SSIDLEN)
284 			errno = ENOBUFS;
285 		else  {
286 			retval = ireq.i_len;
287 			memcpy(ssid, nwid, ireq.i_len);
288 		}
289 	}
290 #else
291 	errno = ENOSYS;
292 #endif
293 
294 	return retval;
295 }
296 
297 int
298 if_getssid(struct interface *ifp)
299 {
300 	int r;
301 
302 	r = if_getssid1(ifp->ctx->pf_inet_fd, ifp->name, ifp->ssid);
303 	if (r != -1)
304 		ifp->ssid_len = (unsigned int)r;
305 	else
306 		ifp->ssid_len = 0;
307 	ifp->ssid[ifp->ssid_len] = '\0';
308 	return r;
309 }
310 
311 /*
312  * FreeBSD allows for Virtual Access Points
313  * We need to check if the interface is a Virtual Interface Master
314  * and if so, don't use it.
315  * This check is made by virtue of being a IEEE80211 device but
316  * returning the SSID gives an error.
317  */
318 int
319 if_vimaster(const struct dhcpcd_ctx *ctx, const char *ifname)
320 {
321 	int r;
322 	struct ifmediareq ifmr;
323 
324 	memset(&ifmr, 0, sizeof(ifmr));
325 	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
326 	r = ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr);
327 	if (r == -1)
328 		return -1;
329 	if (ifmr.ifm_status & IFM_AVALID &&
330 	    IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211)
331 	{
332 		if (if_getssid1(ctx->pf_inet_fd, ifname, NULL) == -1)
333 			return 1;
334 	}
335 	return 0;
336 }
337 
338 unsigned short
339 if_vlanid(const struct interface *ifp)
340 {
341 #ifdef SIOCGETVLAN
342 	struct vlanreq vlr;
343 
344 	memset(&vlr, 0, sizeof(vlr));
345 	if (if_indirect_ioctl(ifp->ctx->pf_inet_fd,
346 	    ifp->name, SIOCGETVLAN, &vlr) != 0)
347 		return 0; /* 0 means no VLANID */
348 	return vlr.vlr_tag;
349 #elif defined(SIOCGVNETID)
350 	struct ifreq ifr;
351 
352 	memset(&ifr, 0, sizeof(ifr));
353 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
354 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGVNETID, &ifr) != 0)
355 		return 0; /* 0 means no VLANID */
356 	return ifr.ifr_vnetid;
357 #else
358 	UNUSED(ifp);
359 	return 0; /* 0 means no VLANID */
360 #endif
361 }
362 
363 static int
364 get_addrs(int type, const void *data, size_t data_len,
365     const struct sockaddr **sa)
366 {
367 	const char *cp, *ep;
368 	int i;
369 
370 	cp = data;
371 	ep = cp + data_len;
372 	for (i = 0; i < RTAX_MAX; i++) {
373 		if (type & (1 << i)) {
374 			if (cp >= ep) {
375 				errno = EINVAL;
376 				return -1;
377 			}
378 			sa[i] = (const struct sockaddr *)cp;
379 			RT_ADVANCE(cp, sa[i]);
380 		} else
381 			sa[i] = NULL;
382 	}
383 
384 	return 0;
385 }
386 
387 static struct interface *
388 if_findsdl(struct dhcpcd_ctx *ctx, const struct sockaddr_dl *sdl)
389 {
390 
391 	if (sdl->sdl_index)
392 		return if_findindex(ctx->ifaces, sdl->sdl_index);
393 
394 	if (sdl->sdl_nlen) {
395 		char ifname[IF_NAMESIZE];
396 
397 		memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
398 		ifname[sdl->sdl_nlen] = '\0';
399 		return if_find(ctx->ifaces, ifname);
400 	}
401 	if (sdl->sdl_alen) {
402 		struct interface *ifp;
403 
404 		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
405 			if (ifp->hwlen == sdl->sdl_alen &&
406 			    memcmp(ifp->hwaddr,
407 			    sdl->sdl_data, sdl->sdl_alen) == 0)
408 				return ifp;
409 		}
410 	}
411 
412 	errno = ENOENT;
413 	return NULL;
414 }
415 
416 static struct interface *
417 if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa)
418 {
419 	if (sa == NULL) {
420 		errno = EINVAL;
421 		return NULL;
422 	}
423 
424 	switch (sa->sa_family) {
425 	case AF_LINK:
426 	{
427 		const struct sockaddr_dl *sdl;
428 
429 		sdl = (const void *)sa;
430 		return if_findsdl(ctx, sdl);
431 	}
432 #ifdef INET
433 	case AF_INET:
434 	{
435 		const struct sockaddr_in *sin;
436 		struct ipv4_addr *ia;
437 
438 		sin = (const void *)sa;
439 		if ((ia = ipv4_findmaskaddr(ctx, &sin->sin_addr)))
440 			return ia->iface;
441 		break;
442 	}
443 #endif
444 #ifdef INET6
445 	case AF_INET6:
446 	{
447 		const struct sockaddr_in6 *sin;
448 		unsigned int scope;
449 		struct ipv6_addr *ia;
450 
451 		sin = (const void *)sa;
452 		scope = ifa_getscope(sin);
453 		if (scope != 0)
454 			return if_findindex(ctx->ifaces, scope);
455 		if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr)))
456 			return ia->iface;
457 		break;
458 	}
459 #endif
460 	default:
461 		errno = EAFNOSUPPORT;
462 		return NULL;
463 	}
464 
465 	errno = ENOENT;
466 	return NULL;
467 }
468 
469 static void
470 if_copysa(struct sockaddr *dst, const struct sockaddr *src)
471 {
472 
473 	assert(dst != NULL);
474 	assert(src != NULL);
475 
476 	memcpy(dst, src, src->sa_len);
477 #if defined(INET6) && defined(__KAME__)
478 	if (dst->sa_family == AF_INET6) {
479 		struct in6_addr *in6;
480 
481 		in6 = &satosin6(dst)->sin6_addr;
482 		if (IN6_IS_ADDR_LINKLOCAL(in6))
483 			in6->s6_addr[2] = in6->s6_addr[3] = '\0';
484 	}
485 #endif
486 }
487 
488 int
489 if_route(unsigned char cmd, const struct rt *rt)
490 {
491 	struct dhcpcd_ctx *ctx;
492 	struct rtm rtmsg;
493 	struct rt_msghdr *rtm = &rtmsg.hdr;
494 	char *bp = rtmsg.buffer;
495 	struct sockaddr_dl sdl;
496 	bool gateway_unspec;
497 
498 	assert(rt != NULL);
499 	ctx = rt->rt_ifp->ctx;
500 
501 #define ADDSA(sa) do {							      \
502 		memcpy(bp, (sa), (sa)->sa_len);				      \
503 		bp += RT_ROUNDUP((sa)->sa_len);				      \
504 	}  while (0 /* CONSTCOND */)
505 
506 	memset(&rtmsg, 0, sizeof(rtmsg));
507 	rtm->rtm_version = RTM_VERSION;
508 	rtm->rtm_type = cmd;
509 #ifdef __OpenBSD__
510 	rtm->rtm_pid = getpid();
511 #endif
512 	rtm->rtm_seq = ++ctx->seq;
513 	rtm->rtm_flags = (int)rt->rt_flags;
514 	rtm->rtm_addrs = RTA_DST;
515 #ifdef RTF_PINNED
516 	if (cmd != RTM_ADD)
517 		rtm->rtm_flags |= RTF_PINNED;
518 #endif
519 
520 	gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
521 
522 	if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
523 		bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
524 
525 		rtm->rtm_flags |= RTF_UP;
526 		rtm->rtm_addrs |= RTA_GATEWAY;
527 		if (!(rtm->rtm_flags & RTF_REJECT) &&
528 		    !sa_is_loopback(&rt->rt_gateway))
529 		{
530 			rtm->rtm_index = (unsigned short)rt->rt_ifp->index;
531 /*
532  * OpenBSD rejects the message for on-link routes.
533  * FreeBSD-12 kernel apparently panics.
534  * I can't replicate the panic, but better safe than sorry!
535  * https://roy.marples.name/archives/dhcpcd-discuss/0002286.html
536  *
537  * Neither OS currently allows IPv6 address sharing anyway, so let's
538  * try to encourage someone to fix that by logging a waring during compile.
539  */
540 #if defined(__FreeBSD__) || defined(__OpenBSD__)
541 #warning OS does not allow IPv6 address sharing
542 			if (!gateway_unspec || rt->rt_dest.sa_family!=AF_INET6)
543 #endif
544 			rtm->rtm_addrs |= RTA_IFP;
545 			if (!sa_is_unspecified(&rt->rt_ifa))
546 				rtm->rtm_addrs |= RTA_IFA;
547 		}
548 		if (netmask_bcast)
549 			rtm->rtm_flags |= RTF_HOST;
550 		/* Network routes are cloning or connected if supported.
551 		 * All other routes are static. */
552 		if (gateway_unspec) {
553 #ifdef RTF_CLONING
554 			rtm->rtm_flags |= RTF_CLONING;
555 #endif
556 #ifdef RTF_CONNECTED
557 			rtm->rtm_flags |= RTF_CONNECTED;
558 #endif
559 #ifdef RTP_CONNECTED
560 			rtm->rtm_priority = RTP_CONNECTED;
561 #endif
562 #ifdef RTF_CLONING
563 			if (netmask_bcast) {
564 				/*
565 				 * We add a cloning network route for a single
566 				 * host. Traffic to the host will generate a
567 				 * cloned route and the hardware address will
568 				 * resolve correctly.
569 				 * It might be more correct to use RTF_HOST
570 				 * instead of RTF_CLONING, and that does work,
571 				 * but some OS generate an arp warning
572 				 * diagnostic which we don't want to do.
573 				 */
574 				rtm->rtm_flags &= ~RTF_HOST;
575 			}
576 #endif
577 		} else
578 			rtm->rtm_flags |= RTF_GATEWAY;
579 
580 		/* Emulate the kernel by marking address generated
581 		 * network routes non-static. */
582 		if (!(rt->rt_dflags & RTDF_IFA_ROUTE))
583 			rtm->rtm_flags |= RTF_STATIC;
584 
585 		if (rt->rt_mtu != 0) {
586 			rtm->rtm_inits |= RTV_MTU;
587 			rtm->rtm_rmx.rmx_mtu = rt->rt_mtu;
588 		}
589 	}
590 
591 	if (!(rtm->rtm_flags & RTF_HOST))
592 		rtm->rtm_addrs |= RTA_NETMASK;
593 
594 	if_linkaddr(&sdl, rt->rt_ifp);
595 
596 	ADDSA(&rt->rt_dest);
597 
598 	if (rtm->rtm_addrs & RTA_GATEWAY) {
599 		if (gateway_unspec)
600 			ADDSA((struct sockaddr *)&sdl);
601 		else {
602 			union sa_ss gateway;
603 
604 			if_copysa(&gateway.sa, &rt->rt_gateway);
605 #ifdef INET6
606 			if (gateway.sa.sa_family == AF_INET6)
607 				ifa_setscope(&gateway.sin6, rt->rt_ifp->index);
608 #endif
609 			ADDSA(&gateway.sa);
610 		}
611 	}
612 
613 	if (rtm->rtm_addrs & RTA_NETMASK)
614 		ADDSA(&rt->rt_netmask);
615 
616 	if (rtm->rtm_addrs & RTA_IFP)
617 		ADDSA((struct sockaddr *)&sdl);
618 
619 	if (rtm->rtm_addrs & RTA_IFA)
620 		ADDSA(&rt->rt_ifa);
621 
622 #undef ADDSA
623 
624 	rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
625 	if (write(ctx->link_fd, rtm, rtm->rtm_msglen) == -1)
626 		return -1;
627 	return 0;
628 }
629 
630 static int
631 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
632 {
633 	const struct sockaddr *rti_info[RTAX_MAX];
634 
635 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) {
636 		errno = EINVAL;
637 		return -1;
638 	}
639 #ifdef RTF_CLONED
640 	if (rtm->rtm_flags & RTF_CLONED) {
641 		errno = ENOTSUP;
642 		return -1;
643 	}
644 #endif
645 #ifdef RTF_LOCAL
646 	if (rtm->rtm_flags & RTF_LOCAL) {
647 		errno = ENOTSUP;
648 		return -1;
649 	}
650 #endif
651 #ifdef RTF_BROADCAST
652 	if (rtm->rtm_flags & RTF_BROADCAST) {
653 		errno = ENOTSUP;
654 		return -1;
655 	}
656 #endif
657 
658 	/* We have already checked that at least one address must be
659 	 * present after the rtm structure. */
660 	/* coverity[ptr_arith] */
661 	if (get_addrs(rtm->rtm_addrs, rtm + 1,
662 		      rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
663 		return -1;
664 	memset(rt, 0, sizeof(*rt));
665 
666 	rt->rt_flags = (unsigned int)rtm->rtm_flags;
667 	if_copysa(&rt->rt_dest, rti_info[RTAX_DST]);
668 	if (rtm->rtm_addrs & RTA_NETMASK) {
669 		if_copysa(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
670 		if (rt->rt_netmask.sa_family == 255) /* Why? */
671 			rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
672 	}
673 	/* dhcpcd likes an unspecified gateway to indicate via the link. */
674 	if (rt->rt_flags & RTF_GATEWAY &&
675 	    rti_info[RTAX_GATEWAY]->sa_family != AF_LINK)
676 		if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
677 	if (rtm->rtm_addrs & RTA_IFA)
678 		if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
679 	rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
680 
681 	if (rtm->rtm_index)
682 		rt->rt_ifp = if_findindex(ctx->ifaces, rtm->rtm_index);
683 	else if (rtm->rtm_addrs & RTA_IFP)
684 		rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_IFP]);
685 	else if (rtm->rtm_addrs & RTA_GATEWAY)
686 		rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_GATEWAY]);
687 	else
688 		rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]);
689 
690 	if (rt->rt_ifp == NULL) {
691 		errno = ESRCH;
692 		return -1;
693 	}
694 	return 0;
695 }
696 
697 int
698 if_initrt(struct dhcpcd_ctx *ctx, int af)
699 {
700 	struct rt_msghdr *rtm;
701 	int mib[6];
702 	size_t needed;
703 	char *buf, *p, *end;
704 	struct rt rt;
705 
706 	rt_headclear(&ctx->kroutes, af);
707 
708 	mib[0] = CTL_NET;
709 	mib[1] = PF_ROUTE;
710 	mib[2] = 0;
711 	mib[3] = af;
712 	mib[4] = NET_RT_DUMP;
713 	mib[5] = 0;
714 
715 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
716 		return -1;
717 	if (needed == 0)
718 		return 0;
719 	if ((buf = malloc(needed)) == NULL)
720 		return -1;
721 	if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) {
722 		free(buf);
723 		return -1;
724 	}
725 
726 	end = buf + needed;
727 	for (p = buf; p < end; p += rtm->rtm_msglen) {
728 		rtm = (void *)p;
729 		if (p + rtm->rtm_msglen >= end) {
730 			errno = EINVAL;
731 			break;
732 		}
733 		if (if_copyrt(ctx, &rt, rtm) == 0) {
734 			rt.rt_dflags |= RTDF_INIT;
735 			rt_recvrt(RTM_ADD, &rt, rtm->rtm_pid);
736 		}
737 	}
738 	free(buf);
739 	return p == end ? 0 : -1;
740 }
741 
742 #ifdef INET
743 int
744 if_address(unsigned char cmd, const struct ipv4_addr *ia)
745 {
746 	int r;
747 	struct in_aliasreq ifra;
748 
749 	memset(&ifra, 0, sizeof(ifra));
750 	strlcpy(ifra.ifra_name, ia->iface->name, sizeof(ifra.ifra_name));
751 
752 #define ADDADDR(var, addr) do {						      \
753 		(var)->sin_family = AF_INET;				      \
754 		(var)->sin_len = sizeof(*(var));			      \
755 		(var)->sin_addr = *(addr);				      \
756 	} while (/*CONSTCOND*/0)
757 	ADDADDR(&ifra.ifra_addr, &ia->addr);
758 	ADDADDR(&ifra.ifra_mask, &ia->mask);
759 	if (cmd == RTM_NEWADDR && ia->brd.s_addr != INADDR_ANY)
760 		ADDADDR(&ifra.ifra_broadaddr, &ia->brd);
761 #undef ADDADDR
762 
763 	r = ioctl(ia->iface->ctx->pf_inet_fd,
764 	    cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
765 	return r;
766 }
767 
768 
769 
770 #if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS))
771 int
772 if_addrflags(const struct interface *ifp, const struct in_addr *addr,
773     __unused const char *alias)
774 {
775 #ifdef SIOCGIFAFLAG_IN
776 	struct ifreq ifr;
777 	struct sockaddr_in *sin;
778 
779 	memset(&ifr, 0, sizeof(ifr));
780 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
781 	sin = (void *)&ifr.ifr_addr;
782 	sin->sin_family = AF_INET;
783 	sin->sin_addr = *addr;
784 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
785 		return -1;
786 	return ifr.ifr_addrflags;
787 #else
788 	UNUSED(ifp);
789 	UNUSED(addr);
790 	return 0;
791 #endif
792 }
793 #endif
794 #endif /* INET */
795 
796 #ifdef INET6
797 static void
798 ifa_setscope(struct sockaddr_in6 *sin, unsigned int ifindex)
799 {
800 
801 #ifdef __KAME__
802 	/* KAME based systems want to store the scope inside the sin6_addr
803 	 * for link local addresses */
804 	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
805 		uint16_t scope = htons((uint16_t)ifindex);
806 		memcpy(&sin->sin6_addr.s6_addr[2], &scope,
807 		    sizeof(scope));
808 	}
809 	sin->sin6_scope_id = 0;
810 #else
811 	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
812 		sin->sin6_scope_id = ifindex;
813 	else
814 		sin->sin6_scope_id = 0;
815 #endif
816 }
817 
818 static unsigned int
819 ifa_getscope(const struct sockaddr_in6 *sin)
820 {
821 #ifdef __KAME__
822 	uint16_t scope;
823 #endif
824 
825 	if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
826 		return 0;
827 #ifdef __KAME__
828 	memcpy(&scope, &sin->sin6_addr.s6_addr[2], sizeof(scope));
829 	return (unsigned int)ntohs(scope);
830 #else
831 	return (unsigned int)sin->sin6_scope_id;
832 #endif
833 }
834 
835 int
836 if_address6(unsigned char cmd, const struct ipv6_addr *ia)
837 {
838 	struct in6_aliasreq ifa;
839 	struct in6_addr mask;
840 	struct priv *priv;
841 
842 	priv = (struct priv *)ia->iface->ctx->priv;
843 
844 	memset(&ifa, 0, sizeof(ifa));
845 	strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name));
846 	/*
847 	 * We should not set IN6_IFF_TENTATIVE as the kernel should be
848 	 * able to work out if it's a new address or not.
849 	 *
850 	 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us.
851 	 * This is probably a safety measure, but still it's not entirely right
852 	 * either.
853 	 */
854 #if 0
855 	if (ia->autoconf)
856 		ifa.ifra_flags |= IN6_IFF_AUTOCONF;
857 #endif
858 #if defined(__FreeBSD__) || defined(__DragonFly__)
859 	if (ia->addr_flags & IN6_IFF_TENTATIVE)
860 		ifa.ifra_flags |= IN6_IFF_TENTATIVE;
861 #endif
862 #ifdef IPV6_MANGETEMPADDR
863 	if (ia->flags & IPV6_AF_TEMPORARY)
864 		ifa.ifra_flags |= IN6_IFF_TEMPORARY;
865 #endif
866 
867 #define ADDADDR(v, addr) {						      \
868 		(v)->sin6_family = AF_INET6;				      \
869 		(v)->sin6_len = sizeof(*v);				      \
870 		(v)->sin6_addr = *(addr);				      \
871 	}
872 
873 	ADDADDR(&ifa.ifra_addr, &ia->addr);
874 	ifa_setscope(&ifa.ifra_addr, ia->iface->index);
875 	ipv6_mask(&mask, ia->prefix_len);
876 	ADDADDR(&ifa.ifra_prefixmask, &mask);
877 
878 #undef ADDADDR
879 
880 	/*
881 	 * Every BSD kernel wants to add the prefix of the address to it's
882 	 * list of RA received prefixes.
883 	 * THIS IS WRONG because there (as the comments in the kernel state)
884 	 * is no API for managing prefix lifetime and the kernel should not
885 	 * pretend it's from a RA either.
886 	 *
887 	 * The issue is that the very first assigned prefix will inherit the
888 	 * lifetime of the address, but any subsequent alteration of the
889 	 * address OR it's lifetime will not affect the prefix lifetime.
890 	 * As such, we cannot stop the prefix from timing out and then
891 	 * constantly removing the prefix route dhcpcd is capable of adding
892 	 * in it's absense.
893 	 *
894 	 * What we can do to mitigate the issue is to add the address with
895 	 * infinite lifetimes, so the prefix route will never time out.
896 	 * Once done, we can then set lifetimes on the address and all is good.
897 	 * The downside of this approach is that we need to manually remove
898 	 * the kernel route because it has no lifetime, but this is OK as
899 	 * dhcpcd will handle this too.
900 	 *
901 	 * This issue is discussed on the NetBSD mailing lists here:
902 	 * http://mail-index.netbsd.org/tech-net/2016/08/05/msg006044.html
903 	 *
904 	 * Fixed in NetBSD-7.99.36
905 	 * NOT fixed in FreeBSD - bug 195197
906 	 * Fixed in OpenBSD-5.9
907 	 */
908 
909 #if !((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003600) || \
910       (defined(__OpenBSD__) && OpenBSD >= 201605))
911 	if (cmd == RTM_NEWADDR && !(ia->flags & IPV6_AF_ADDED)) {
912 		ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
913 		ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
914 		(void)ioctl(priv->pf_inet6_fd, SIOCAIFADDR_IN6, &ifa);
915 	}
916 #endif
917 
918 #if defined(__OpenBSD__) && OpenBSD <= 201705
919 	/* BUT OpenBSD older than 6.2 does not reset the address lifetime
920 	 * for subsequent calls...
921 	 * Luckily dhcpcd will remove the lease when it expires so
922 	 * just set an infinite lifetime, unless a temporary address. */
923 	if (ifa.ifra_flags & IN6_IFF_PRIVACY) {
924 		ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime;
925 		ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
926 	} else {
927 		ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
928 		ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
929 	}
930 #else
931 	ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime;
932 	ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
933 #endif
934 
935 	return ioctl(priv->pf_inet6_fd,
936 	    cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
937 }
938 
939 int
940 if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
941     __unused const char *alias)
942 {
943 	int flags;
944 	struct in6_ifreq ifr6;
945 	struct priv *priv;
946 
947 	memset(&ifr6, 0, sizeof(ifr6));
948 	strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
949 	ifr6.ifr_addr.sin6_family = AF_INET6;
950 	ifr6.ifr_addr.sin6_addr = *addr;
951 	ifa_setscope(&ifr6.ifr_addr, ifp->index);
952 	priv = (struct priv *)ifp->ctx->priv;
953 	if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
954 		flags = ifr6.ifr_ifru.ifru_flags6;
955 	else
956 		flags = -1;
957 	return flags;
958 }
959 
960 int
961 if_getlifetime6(struct ipv6_addr *ia)
962 {
963 	struct in6_ifreq ifr6;
964 	time_t t;
965 	struct in6_addrlifetime *lifetime;
966 	struct priv *priv;
967 
968 	memset(&ifr6, 0, sizeof(ifr6));
969 	strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
970 	ifr6.ifr_addr.sin6_family = AF_INET6;
971 	ifr6.ifr_addr.sin6_addr = ia->addr;
972 	ifa_setscope(&ifr6.ifr_addr, ia->iface->index);
973 	priv = (struct priv *)ia->iface->ctx->priv;
974 	if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1)
975 		return -1;
976 	clock_gettime(CLOCK_MONOTONIC, &ia->created);
977 
978 #if defined(__FreeBSD__) || defined(__DragonFly__)
979 	t = ia->created.tv_sec;
980 #else
981 	t = time(NULL);
982 #endif
983 
984 	lifetime = &ifr6.ifr_ifru.ifru_lifetime;
985 	if (lifetime->ia6t_preferred)
986 		ia->prefix_pltime = (uint32_t)(lifetime->ia6t_preferred -
987 		    MIN(t, lifetime->ia6t_preferred));
988 	else
989 		ia->prefix_pltime = ND6_INFINITE_LIFETIME;
990 	if (lifetime->ia6t_expire) {
991 		ia->prefix_vltime = (uint32_t)(lifetime->ia6t_expire -
992 		    MIN(t, lifetime->ia6t_expire));
993 		/* Calculate the created time */
994 		ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime;
995 	} else
996 		ia->prefix_vltime = ND6_INFINITE_LIFETIME;
997 	return 0;
998 }
999 #endif
1000 
1001 static int
1002 if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan)
1003 {
1004 
1005 	if (ifan->ifan_msglen < sizeof(*ifan)) {
1006 		errno = EINVAL;
1007 		return -1;
1008 	}
1009 
1010 	switch(ifan->ifan_what) {
1011 	case IFAN_ARRIVAL:
1012 		return dhcpcd_handleinterface(ctx, 1, ifan->ifan_name);
1013 	case IFAN_DEPARTURE:
1014 		return dhcpcd_handleinterface(ctx, -1, ifan->ifan_name);
1015 	}
1016 
1017 	return 0;
1018 }
1019 
1020 static int
1021 if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
1022 {
1023 	struct interface *ifp;
1024 	int link_state;
1025 
1026 	if (ifm->ifm_msglen < sizeof(*ifm)) {
1027 		errno = EINVAL;
1028 		return -1;
1029 	}
1030 
1031 	if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
1032 		return 0;
1033 
1034 	switch (ifm->ifm_data.ifi_link_state) {
1035 	case LINK_STATE_UNKNOWN:
1036 		link_state = LINK_UNKNOWN;
1037 		break;
1038 	case LINK_STATE_UP:
1039 		link_state = LINK_UP;
1040 		break;
1041 	default:
1042 		link_state = LINK_DOWN;
1043 		break;
1044 	}
1045 
1046 	dhcpcd_handlecarrier(ctx, link_state,
1047 	    (unsigned int)ifm->ifm_flags, ifp->name);
1048 	return 0;
1049 }
1050 
1051 static int
1052 if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
1053 {
1054 	struct rt rt;
1055 
1056 	if (rtm->rtm_msglen < sizeof(*rtm)) {
1057 		errno = EINVAL;
1058 		return -1;
1059 	}
1060 
1061 	/* Ignore errors. */
1062 	if (rtm->rtm_errno != 0)
1063 		return 0;
1064 
1065 	if (if_copyrt(ctx, &rt, rtm) == -1)
1066 		return -1;
1067 
1068 #ifdef INET6
1069 	/*
1070 	 * BSD announces host routes.
1071 	 * As such, we should be notified of reachability by its
1072 	 * existance with a hardware address.
1073 	 */
1074 	if (rt.rt_dest.sa_family == AF_INET6 && rt.rt_flags & RTF_HOST) {
1075 		struct sockaddr_in6 dest;
1076 		struct sockaddr_dl sdl;
1077 
1078 		memcpy(&dest, &rt.rt_dest, rt.rt_dest.sa_len);
1079 		if (rt.rt_gateway.sa_family == AF_LINK)
1080 			memcpy(&sdl, &rt.rt_gateway, rt.rt_gateway.sa_len);
1081 		else
1082 			sdl.sdl_alen = 0;
1083 		ipv6nd_neighbour(ctx, &dest.sin6_addr,
1084 		    rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
1085 		    IPV6ND_REACHABLE : 0);
1086 	}
1087 #endif
1088 
1089 	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
1090 	return 0;
1091 }
1092 
1093 static int
1094 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
1095 {
1096 	struct interface *ifp;
1097 	const struct sockaddr *rti_info[RTAX_MAX];
1098 	int addrflags;
1099 	pid_t pid;
1100 
1101 	if (ifam->ifam_msglen < sizeof(*ifam)) {
1102 		errno = EINVAL;
1103 		return -1;
1104 	}
1105 	if (~ifam->ifam_addrs & RTA_IFA)
1106 		return 0;
1107 	if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
1108 		return 0;
1109 
1110 	/* We have already checked that at least one address must be
1111 	 * present after the ifam structure. */
1112 	/* coverity[ptr_arith] */
1113 	if (get_addrs(ifam->ifam_addrs, ifam + 1,
1114 		      ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
1115 		return -1;
1116 
1117 #ifdef HAVE_IFAM_PID
1118 	pid = ifam->ifam_pid;
1119 #else
1120 	pid = 0;
1121 #endif
1122 
1123 #ifdef HAVE_IFAM_ADDRFLAGS
1124 	addrflags = ifam->ifam_addrflags;
1125 #endif
1126 	switch (rti_info[RTAX_IFA]->sa_family) {
1127 	case AF_LINK:
1128 	{
1129 		struct sockaddr_dl sdl;
1130 
1131 #ifdef RTM_CHGADDR
1132 		if (ifam->ifam_type != RTM_CHGADDR)
1133 			break;
1134 #else
1135 		if (ifam->ifam_type != RTM_NEWADDR)
1136 			break;
1137 #endif
1138 		memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len);
1139 		dhcpcd_handlehwaddr(ctx, ifp->name, CLLADDR(&sdl),sdl.sdl_alen);
1140 		break;
1141 	}
1142 #ifdef INET
1143 	case AF_INET:
1144 	case 255: /* FIXME: Why 255? */
1145 	{
1146 		const struct sockaddr_in *sin;
1147 		struct in_addr addr, mask, bcast;
1148 
1149 		sin = (const void *)rti_info[RTAX_IFA];
1150 		addr.s_addr = sin != NULL && sin->sin_family == AF_INET ?
1151 		    sin->sin_addr.s_addr : INADDR_ANY;
1152 		sin = (const void *)rti_info[RTAX_NETMASK];
1153 		mask.s_addr = sin != NULL && sin->sin_family == AF_INET ?
1154 		    sin->sin_addr.s_addr : INADDR_ANY;
1155 		sin = (const void *)rti_info[RTAX_BRD];
1156 		bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ?
1157 		    sin->sin_addr.s_addr : INADDR_ANY;
1158 
1159 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000
1160 		/*
1161 		 * NetBSD-7 and older send an invalid broadcast address.
1162 		 * So we need to query the actual address to get
1163 		 * the right one.
1164 		 */
1165 		{
1166 #else
1167 		/*
1168 		 * If the address was deleted, lets check if it's
1169 		 * a late message and it still exists (maybe modified).
1170 		 * If so, ignore it as deleting an address causes
1171 		 * dhcpcd to drop any lease to which it belongs.
1172 		 */
1173 		if (ifam->ifam_type == RTM_DELADDR) {
1174 #endif
1175 #ifdef SIOCGIFALIAS
1176 			struct in_aliasreq ifra;
1177 
1178 			memset(&ifra, 0, sizeof(ifra));
1179 			strlcpy(ifra.ifra_name, ifp->name,
1180 			    sizeof(ifra.ifra_name));
1181 			ifra.ifra_addr.sin_family = AF_INET;
1182 			ifra.ifra_addr.sin_len = sizeof(ifra.ifra_addr);
1183 			ifra.ifra_addr.sin_addr = addr;
1184 			if (ioctl(ctx->pf_inet_fd, SIOCGIFALIAS, &ifra) == -1) {
1185 				if (errno != ENXIO && errno != EADDRNOTAVAIL)
1186 					logerr("%s: SIOCGIFALIAS", __func__);
1187 				if (ifam->ifam_type != RTM_DELADDR)
1188 					break;
1189 			}
1190 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000
1191 			else
1192 				bcast = ifra.ifra_broadaddr.sin_addr;
1193 #endif
1194 #else
1195 #warning No SIOCGIFALIAS support
1196 			/*
1197 			 * No SIOCGIFALIAS? That sucks!
1198 			 * This makes this call very heavy weight, but we
1199 			 * really need to know if the message is late or not.
1200 			 */
1201 			const struct sockaddr *sa;
1202 			struct ifaddrs *ifaddrs = NULL, *ifa;
1203 
1204 			sa = rti_info[RTAX_IFA];
1205 			getifaddrs(&ifaddrs);
1206 			for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
1207 				if (ifa->ifa_addr == NULL)
1208 					continue;
1209 				if (sa_cmp(ifa->ifa_addr, sa) == 0 &&
1210 				    strcmp(ifa->ifa_name, ifp->name) == 0)
1211 					break;
1212 			}
1213 			freeifaddrs(ifaddrs);
1214 			if (ifa != NULL)
1215 				return 0;
1216 #endif
1217 		}
1218 
1219 #ifndef HAVE_IFAM_ADDRFLAGS
1220 		if (ifam->ifam_type == RTM_DELADDR)
1221 			addrflags = 0 ;
1222 		else if ((addrflags = if_addrflags(ifp, &addr, NULL)) == -1) {
1223 			if (errno != EADDRNOTAVAIL)
1224 				logerr("%s: if_addrflags", __func__);
1225 			break;
1226 		}
1227 #endif
1228 
1229 		ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name,
1230 		    &addr, &mask, &bcast, addrflags, pid);
1231 		break;
1232 	}
1233 #endif
1234 #ifdef INET6
1235 	case AF_INET6:
1236 	{
1237 		struct in6_addr addr6, mask6;
1238 		const struct sockaddr_in6 *sin6;
1239 		int flags;
1240 
1241 		sin6 = (const void *)rti_info[RTAX_IFA];
1242 		addr6 = sin6->sin6_addr;
1243 		sin6 = (const void *)rti_info[RTAX_NETMASK];
1244 		mask6 = sin6->sin6_addr;
1245 
1246 		/*
1247 		 * If the address was deleted, lets check if it's
1248 		 * a late message and it still exists (maybe modified).
1249 		 * If so, ignore it as deleting an address causes
1250 		 * dhcpcd to drop any lease to which it belongs.
1251 		 */
1252 		if (ifam->ifam_type == RTM_DELADDR) {
1253 			flags = if_addrflags6(ifp, &addr6, NULL);
1254 			if (flags != -1)
1255 				break;
1256 			addrflags = 0;
1257 		}
1258 #ifndef HAVE_IFAM_ADDRFLAGS
1259 		else if ((addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1) {
1260 			if (errno != EADDRNOTAVAIL)
1261 				logerr("%s: if_addrflags6", __func__);
1262 			break;
1263 		}
1264 #endif
1265 
1266 #ifdef __KAME__
1267 		if (IN6_IS_ADDR_LINKLOCAL(&addr6))
1268 			/* Remove the scope from the address */
1269 			addr6.s6_addr[2] = addr6.s6_addr[3] = '\0';
1270 #endif
1271 
1272 		ipv6_handleifa(ctx, ifam->ifam_type, NULL,
1273 		    ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags, pid);
1274 		break;
1275 	}
1276 #endif
1277 	}
1278 
1279 	return 0;
1280 }
1281 
1282 static int
1283 if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
1284 {
1285 
1286 	if (rtm->rtm_version != RTM_VERSION)
1287 		return 0;
1288 
1289 	switch(rtm->rtm_type) {
1290 #ifdef RTM_IFANNOUNCE
1291 	case RTM_IFANNOUNCE:
1292 		return if_announce(ctx, (const void *)rtm);
1293 #endif
1294 	case RTM_IFINFO:
1295 		return if_ifinfo(ctx, (const void *)rtm);
1296 	case RTM_ADD:		/* FALLTHROUGH */
1297 	case RTM_CHANGE:	/* FALLTHROUGH */
1298 	case RTM_DELETE:
1299 		return if_rtm(ctx, (const void *)rtm);
1300 #ifdef RTM_CHGADDR
1301 	case RTM_CHGADDR:	/* FALLTHROUGH */
1302 #endif
1303 	case RTM_DELADDR:	/* FALLTHROUGH */
1304 	case RTM_NEWADDR:
1305 		return if_ifa(ctx, (const void *)rtm);
1306 #ifdef RTM_DESYNC
1307 	case RTM_DESYNC:
1308 		return dhcpcd_linkoverflow(ctx);
1309 #endif
1310 	}
1311 
1312 	return 0;
1313 }
1314 
1315 int
1316 if_handlelink(struct dhcpcd_ctx *ctx)
1317 {
1318 	struct rtm rtm;
1319 	struct iovec iov = { .iov_base = &rtm, .iov_len = sizeof(rtm) };
1320 	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
1321 	ssize_t len;
1322 
1323 	len = recvmsg(ctx->link_fd, &msg, 0);
1324 	if (len == -1)
1325 		return -1;
1326 	if (len == 0)
1327 		return 0;
1328 	if (len < rtm.hdr.rtm_msglen) {
1329 		errno = EINVAL;
1330 		return -1;
1331 	}
1332 	return if_dispatch(ctx, &rtm.hdr);
1333 }
1334 
1335 #ifndef SYS_NMLN	/* OSX */
1336 #  define SYS_NMLN 256
1337 #endif
1338 #ifndef HW_MACHINE_ARCH
1339 #  ifdef HW_MODEL	/* OpenBSD */
1340 #    define HW_MACHINE_ARCH HW_MODEL
1341 #  endif
1342 #endif
1343 int
1344 if_machinearch(char *str, size_t len)
1345 {
1346 	int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1347 	char march[SYS_NMLN];
1348 	size_t marchlen = sizeof(march);
1349 
1350 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1351 	    march, &marchlen, NULL, 0) != 0)
1352 		return -1;
1353 	return snprintf(str, len, ":%s", march);
1354 }
1355 
1356 #ifdef INET6
1357 #if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \
1358     defined(IPV6CTL_USETEMPADDR) || defined(IPV6CTL_TEMPVLTIME) || \
1359     defined(IPV6CTL_FORWARDING)
1360 #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0)
1361 #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1)
1362 static int
1363 inet6_sysctl(int code, int val, int action)
1364 {
1365 	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
1366 	size_t size;
1367 
1368 	mib[3] = code;
1369 	size = sizeof(val);
1370 	if (action) {
1371 		if (sysctl(mib, sizeof(mib)/sizeof(mib[0]),
1372 		    NULL, 0, &val, size) == -1)
1373 			return -1;
1374 		return 0;
1375 	}
1376 	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1)
1377 		return -1;
1378 	return val;
1379 }
1380 #endif
1381 
1382 #ifdef IPV6_MANAGETEMPADDR
1383 #ifndef IPV6CTL_TEMPVLTIME
1384 #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0)
1385 #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1)
1386 static int
1387 inet6_sysctlbyname(const char *name, int val, int action)
1388 {
1389 	size_t size;
1390 
1391 	size = sizeof(val);
1392 	if (action) {
1393 		if (sysctlbyname(name, NULL, 0, &val, size) == -1)
1394 			return -1;
1395 		return 0;
1396 	}
1397 	if (sysctlbyname(name, &val, &size, NULL, 0) == -1)
1398 		return -1;
1399 	return val;
1400 }
1401 #endif
1402 
1403 int
1404 ip6_use_tempaddr(__unused const char *ifname)
1405 {
1406 	int val;
1407 
1408 #ifdef IPV6CTL_USETEMPADDR
1409 	val = get_inet6_sysctl(IPV6CTL_USETEMPADDR);
1410 #else
1411 	val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr");
1412 #endif
1413 	return val == -1 ? 0 : val;
1414 }
1415 
1416 int
1417 ip6_temp_preferred_lifetime(__unused const char *ifname)
1418 {
1419 	int val;
1420 
1421 #ifdef IPV6CTL_TEMPPLTIME
1422 	val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME);
1423 #else
1424 	val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime");
1425 #endif
1426 	return val < 0 ? TEMP_PREFERRED_LIFETIME : val;
1427 }
1428 
1429 int
1430 ip6_temp_valid_lifetime(__unused const char *ifname)
1431 {
1432 	int val;
1433 
1434 #ifdef IPV6CTL_TEMPVLTIME
1435 	val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME);
1436 #else
1437 	val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime");
1438 #endif
1439 	return val < 0 ? TEMP_VALID_LIFETIME : val;
1440 }
1441 #endif
1442 
1443 int
1444 ip6_forwarding(__unused const char *ifname)
1445 {
1446 	int val;
1447 
1448 #ifdef IPV6CTL_FORWARDING
1449 	val = get_inet6_sysctl(IPV6CTL_FORWARDING);
1450 #else
1451 	val = get_inet6_sysctlbyname("net.inet6.ip6.forwarding");
1452 #endif
1453 	return val < 0 ? 0 : val;
1454 }
1455 
1456 #ifdef SIOCIFAFATTACH
1457 static int
1458 af_attach(int s, const struct interface *ifp, int af)
1459 {
1460 	struct if_afreq ifar;
1461 
1462 	strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name));
1463 	ifar.ifar_af = af;
1464 	return ioctl(s, SIOCIFAFATTACH, (void *)&ifar);
1465 }
1466 #endif
1467 
1468 #ifdef SIOCGIFXFLAGS
1469 static int
1470 set_ifxflags(int s, const struct interface *ifp)
1471 {
1472 	struct ifreq ifr;
1473 	int flags;
1474 
1475 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
1476 	if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1)
1477 		return -1;
1478 	flags = ifr.ifr_flags;
1479 #ifdef IFXF_NOINET6
1480 	flags &= ~IFXF_NOINET6;
1481 #endif
1482 	/*
1483 	 * If not doing autoconf, don't disable the kernel from doing it.
1484 	 * If we need to, we should have another option actively disable it.
1485 	 *
1486 	 * OpenBSD moved from kernel based SLAAC to userland via slaacd(8).
1487 	 * It has a similar featureset to dhcpcd such as stable private
1488 	 * addresses, but lacks the ability to handle DNS inside the RA
1489 	 * which is a serious shortfall in this day and age.
1490 	 * Appease their user base by working alongside slaacd(8) if
1491 	 * dhcpcd is instructed not to do auto configuration of addresses.
1492 	 */
1493 #if defined(ND6_IFF_ACCEPT_RTADV)
1494 #define	BSD_AUTOCONF	DHCPCD_IPV6RS
1495 #else
1496 #define	BSD_AUTOCONF	DHCPCD_IPV6RA_AUTOCONF
1497 #endif
1498 	if (ifp->options->options & BSD_AUTOCONF)
1499 		flags &= ~IFXF_AUTOCONF6;
1500 	if (ifr.ifr_flags == flags)
1501 		return 0;
1502 	ifr.ifr_flags = flags;
1503 	return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr);
1504 }
1505 #endif
1506 
1507 /* OpenBSD removed ND6 flags entirely, so we need to check for their
1508  * existance. */
1509 #if defined(ND6_IFF_AUTO_LINKLOCAL) || \
1510     defined(ND6_IFF_PERFORMNUD) || \
1511     defined(ND6_IFF_ACCEPT_RTADV) || \
1512     defined(ND6_IFF_OVERRIDE_RTADV) || \
1513     defined(ND6_IFF_IFDISABLED)
1514 #define	ND6_NDI_FLAGS
1515 #endif
1516 
1517 void
1518 if_setup_inet6(const struct interface *ifp)
1519 {
1520 	struct priv *priv;
1521 	int s;
1522 #ifdef ND6_NDI_FLAGS
1523 	struct in6_ndireq nd;
1524 	int flags;
1525 #endif
1526 
1527 	priv = (struct priv *)ifp->ctx->priv;
1528 	s = priv->pf_inet6_fd;
1529 
1530 #ifdef ND6_NDI_FLAGS
1531 	memset(&nd, 0, sizeof(nd));
1532 	strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname));
1533 	if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1)
1534 		logerr("%s: SIOCGIFINFO_FLAGS", ifp->name);
1535 	flags = (int)nd.ndi.flags;
1536 #endif
1537 
1538 #ifdef ND6_IFF_AUTO_LINKLOCAL
1539 	/* Unlike the kernel,
1540 	 * dhcpcd make make a stable private address. */
1541 	flags &= ~ND6_IFF_AUTO_LINKLOCAL;
1542 #endif
1543 
1544 #ifdef ND6_IFF_PERFORMNUD
1545 	/* NUD is kind of essential. */
1546 	flags |= ND6_IFF_PERFORMNUD;
1547 #endif
1548 
1549 #ifdef ND6_IFF_IFDISABLED
1550 	/* Ensure the interface is not disabled. */
1551 	flags &= ~ND6_IFF_IFDISABLED;
1552 #endif
1553 
1554 	/*
1555 	 * If not doing autoconf, don't disable the kernel from doing it.
1556 	 * If we need to, we should have another option actively disable it.
1557 	 */
1558 #ifdef ND6_IFF_ACCEPT_RTADV
1559 	if (ifp->options->options & DHCPCD_IPV6RS)
1560 		flags &= ~ND6_IFF_ACCEPT_RTADV;
1561 #ifdef ND6_IFF_OVERRIDE_RTADV
1562 	if (ifp->options->options & DHCPCD_IPV6RS)
1563 		flags |= ND6_IFF_OVERRIDE_RTADV;
1564 #endif
1565 #endif
1566 
1567 #ifdef ND6_NDI_FLAGS
1568 	if (nd.ndi.flags != (uint32_t)flags) {
1569 		nd.ndi.flags = (uint32_t)flags;
1570 		if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1)
1571 			logerr("%s: SIOCSIFINFO_FLAGS", ifp->name);
1572 	}
1573 #endif
1574 
1575 	/* Enabling IPv6 by whatever means must be the
1576 	 * last action undertaken to ensure kernel RS and
1577 	 * LLADDR auto configuration are disabled where applicable. */
1578 #ifdef SIOCIFAFATTACH
1579 	if (af_attach(s, ifp, AF_INET6) == -1)
1580 		logerr("%s: af_attach", ifp->name);
1581 #endif
1582 
1583 #ifdef SIOCGIFXFLAGS
1584 	if (set_ifxflags(s, ifp) == -1)
1585 		logerr("%s: set_ifxflags", ifp->name);
1586 #endif
1587 
1588 #if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)
1589 	/* If we cannot control ra per interface, disable it globally. */
1590 	if (ifp->options->options & DHCPCD_IPV6RS) {
1591 		int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
1592 
1593 		if (ra == -1) {
1594 			if (errno != ENOENT)
1595 				logerr("IPV6CTL_ACCEPT_RTADV");
1596 		else if (ra != 0)
1597 			if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1)
1598 				logerr("IPV6CTL_ACCEPT_RTADV");
1599 		}
1600 	}
1601 #endif
1602 
1603 #if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV)
1604 	/* Flush the kernel knowledge of advertised routers
1605 	 * and prefixes so the kernel does not expire prefixes
1606 	 * and default routes we are trying to own. */
1607 	if (ifp->options->options & DHCPCD_IPV6RS) {
1608 		struct in6_ifreq ifr;
1609 
1610 		memset(&ifr, 0, sizeof(ifr));
1611 		strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
1612 		if (ioctl(s, SIOCSRTRFLUSH_IN6, &ifr) == -1 &&
1613 		    errno != ENOTSUP)
1614 			logwarn("SIOCSRTRFLUSH_IN6");
1615 		if (ioctl(s, SIOCSPFXFLUSH_IN6, &ifr) == -1 &&
1616 		    errno != ENOTSUP)
1617 			logwarn("SIOCSPFXFLUSH_IN6");
1618 	}
1619 #endif
1620 }
1621 #endif
1622