1 /*
2  * dhcpcd - DHCP client daemon
3  * Copyright (c) 2006-2015 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 <arpa/inet.h>
39 #include <net/bpf.h>
40 #include <net/if.h>
41 #include <net/if_dl.h>
42 #ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
43 #  include <net/if_var.h>
44 #endif
45 #include <net/if_media.h>
46 #include <net/route.h>
47 #include <netinet/if_ether.h>
48 #include <netinet/in.h>
49 #include <netinet/in_var.h>
50 #include <netinet6/in6_var.h>
51 #include <netinet6/nd6.h>
52 #ifdef __DragonFly__
53 #  include <netproto/802_11/ieee80211_ioctl.h>
54 #elif __APPLE__
55   /* FIXME: Add apple includes so we can work out SSID */
56 #else
57 #  include <net80211/ieee80211.h>
58 #  include <net80211/ieee80211_ioctl.h>
59 #endif
60 
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <fnmatch.h>
64 #include <paths.h>
65 #include <stddef.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <unistd.h>
70 
71 #if defined(OpenBSD) && OpenBSD >= 201411
72 /* OpenBSD dropped the global setting from sysctl but left the #define
73  * which causes a EPERM error when trying to use it.
74  * I think both the error and keeping the define are wrong, so we #undef it. */
75 #undef IPV6CTL_ACCEPT_RTADV
76 #endif
77 
78 #include "config.h"
79 #include "common.h"
80 #include "dhcp.h"
81 #include "if.h"
82 #include "if-options.h"
83 #include "ipv4.h"
84 #include "ipv6.h"
85 #include "ipv6nd.h"
86 
87 #include "bpf-filter.h"
88 
89 #ifndef RT_ROUNDUP
90 #define RT_ROUNDUP(a)							      \
91 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
92 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
93 #endif
94 
95 #define COPYOUT(sin, sa) do {						      \
96 	if ((sa) && ((sa)->sa_family == AF_INET || (sa)->sa_family == 255))   \
97 		(sin) = ((struct sockaddr_in*)(void *)(sa))->sin_addr;	      \
98 	} while (0)
99 
100 #define COPYOUT6(sin, sa) do {						      \
101 	if ((sa) && ((sa)->sa_family == AF_INET6 || (sa)->sa_family == 255))  \
102 		(sin) = ((struct sockaddr_in6*)(void *)(sa))->sin6_addr;      \
103 	} while (0)
104 
105 #ifndef CLLADDR
106 #  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
107 #endif
108 
109 int
if_init(__unused struct interface * iface)110 if_init(__unused struct interface *iface)
111 {
112 	/* BSD promotes secondary address by default */
113 	return 0;
114 }
115 
116 int
if_conf(__unused struct interface * iface)117 if_conf(__unused struct interface *iface)
118 {
119 	/* No extra checks needed on BSD */
120 	return 0;
121 }
122 
123 int
if_openlinksocket(void)124 if_openlinksocket(void)
125 {
126 
127 #ifdef SOCK_CLOEXEC
128 	return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
129 #else
130 	int s, flags;
131 
132 	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
133 		return -1;
134 	if ((flags = fcntl(s, F_GETFD, 0)) == -1 ||
135 	    fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1)
136 	{
137 		close(s);
138 	        return -1;
139 	}
140 	if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
141 	    fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
142 	{
143 		close(s);
144 	        return -1;
145 	}
146 	return s;
147 #endif
148 }
149 
150 #if defined(INET) || defined(INET6)
151 static void
if_linkaddr(struct sockaddr_dl * sdl,const struct interface * ifp)152 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
153 {
154 
155 	memset(sdl, 0, sizeof(*sdl));
156 	sdl->sdl_family = AF_LINK;
157 	sdl->sdl_len = sizeof(*sdl);
158 	sdl->sdl_nlen = sdl->sdl_alen = sdl->sdl_slen = 0;
159 	sdl->sdl_index = (unsigned short)ifp->index;
160 }
161 #endif
162 
163 static int
if_getssid1(const char * ifname,uint8_t * ssid)164 if_getssid1(const char *ifname, uint8_t *ssid)
165 {
166 	int s, retval = -1;
167 #if defined(SIOCG80211NWID)
168 	struct ifreq ifr;
169 	struct ieee80211_nwid nwid;
170 #elif defined(IEEE80211_IOC_SSID)
171 	struct ieee80211req ireq;
172 	char nwid[IEEE80211_NWID_LEN + 1];
173 #endif
174 
175 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
176 		return -1;
177 
178 #if defined(SIOCG80211NWID) /* NetBSD */
179 	memset(&ifr, 0, sizeof(ifr));
180 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
181 	memset(&nwid, 0, sizeof(nwid));
182 	ifr.ifr_data = (void *)&nwid;
183 	if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
184 		if (ssid == NULL)
185 			retval = nwid.i_len;
186 		else if (nwid.i_len > IF_SSIDSIZE) {
187 			errno = ENOBUFS;
188 			retval = -1;
189 		} else {
190 			retval = nwid.i_len;
191 			memcpy(ssid, nwid.i_nwid, nwid.i_len);
192 			ssid[nwid.i_len] = '\0';
193 		}
194 	}
195 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
196 	memset(&ireq, 0, sizeof(ireq));
197 	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
198 	ireq.i_type = IEEE80211_IOC_SSID;
199 	ireq.i_val = -1;
200 	memset(nwid, 0, sizeof(nwid));
201 	ireq.i_data = &nwid;
202 	if (ioctl(s, SIOCG80211, &ireq) == 0) {
203 		if (ssid == NULL)
204 			retval = ireq.i_len;
205 		else if (ireq.i_len > IF_SSIDSIZE) {
206 			errno = ENOBUFS;
207 			retval = -1;
208 		} else  {
209 			retval = ireq.i_len;
210 			memcpy(ssid, nwid, ireq.i_len);
211 			ssid[ireq.i_len] = '\0';
212 		}
213 	}
214 #endif
215 
216 	close(s);
217 	return retval;
218 }
219 
220 int
if_getssid(struct interface * ifp)221 if_getssid(struct interface *ifp)
222 {
223 	int r;
224 
225 	r = if_getssid1(ifp->name, ifp->ssid);
226 	if (r != -1)
227 		ifp->ssid_len = (unsigned int)r;
228 	return r;
229 }
230 
231 /*
232  * FreeBSD allows for Virtual Access Points
233  * We need to check if the interface is a Virtual Interface Master
234  * and if so, don't use it.
235  * This check is made by virtue of being a IEEE80211 device but
236  * returning the SSID gives an error.
237  */
238 int
if_vimaster(const char * ifname)239 if_vimaster(const char *ifname)
240 {
241 	int s, r;
242 	struct ifmediareq ifmr;
243 
244 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
245 		return -1;
246 	memset(&ifmr, 0, sizeof(ifmr));
247 	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
248 	r = ioctl(s, SIOCGIFMEDIA, &ifmr);
249 	close(s);
250 	if (r == -1)
251 		return -1;
252 	if (ifmr.ifm_status & IFM_AVALID &&
253 	    IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211)
254 	{
255 		if (if_getssid1(ifname, NULL) == -1)
256 			return 1;
257 	}
258 	return 0;
259 }
260 
261 static void
get_addrs(int type,char * cp,struct sockaddr ** sa)262 get_addrs(int type, char *cp, struct sockaddr **sa)
263 {
264 	int i;
265 
266 	for (i = 0; i < RTAX_MAX; i++) {
267 		if (type & (1 << i)) {
268 			sa[i] = (struct sockaddr *)cp;
269 			RT_ADVANCE(cp, sa[i]);
270 		} else
271 			sa[i] = NULL;
272 	}
273 }
274 
275 #if defined(INET) || defined(INET6)
276 static struct interface *
if_findsdl(struct dhcpcd_ctx * ctx,struct sockaddr_dl * sdl)277 if_findsdl(struct dhcpcd_ctx *ctx, struct sockaddr_dl *sdl)
278 {
279 
280 	if (sdl->sdl_nlen) {
281 		char ifname[IF_NAMESIZE];
282 		memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
283 		ifname[sdl->sdl_nlen] = '\0';
284 		return if_find(ctx->ifaces, ifname);
285 	}
286 	return NULL;
287 }
288 #endif
289 
290 #ifdef INET
291 const char *if_pfname = "Berkley Packet Filter";
292 
293 int
if_openrawsocket(struct interface * ifp,uint16_t protocol)294 if_openrawsocket(struct interface *ifp, uint16_t protocol)
295 {
296 	struct dhcp_state *state;
297 	int fd = -1;
298 	struct ifreq ifr;
299 	int ibuf_len = 0;
300 	size_t buf_len;
301 	struct bpf_version pv;
302 	struct bpf_program pf;
303 #ifdef BIOCIMMEDIATE
304 	int flags;
305 #endif
306 #ifdef _PATH_BPF
307 	fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC | O_NONBLOCK);
308 #else
309 	char device[32];
310 	int n = 0;
311 
312 	do {
313 		snprintf(device, sizeof(device), "/dev/bpf%d", n++);
314 		fd = open(device, O_RDWR | O_CLOEXEC | O_NONBLOCK);
315 	} while (fd == -1 && errno == EBUSY);
316 #endif
317 
318 	if (fd == -1)
319 		return -1;
320 
321 	state = D_STATE(ifp);
322 
323 	memset(&pv, 0, sizeof(pv));
324 	if (ioctl(fd, BIOCVERSION, &pv) == -1)
325 		goto eexit;
326 	if (pv.bv_major != BPF_MAJOR_VERSION ||
327 	    pv.bv_minor < BPF_MINOR_VERSION) {
328 		logger(ifp->ctx, LOG_ERR, "BPF version mismatch - recompile");
329 		goto eexit;
330 	}
331 
332 	memset(&ifr, 0, sizeof(ifr));
333 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
334 	if (ioctl(fd, BIOCSETIF, &ifr) == -1)
335 		goto eexit;
336 
337 	/* Get the required BPF buffer length from the kernel. */
338 	if (ioctl(fd, BIOCGBLEN, &ibuf_len) == -1)
339 		goto eexit;
340 	buf_len = (size_t)ibuf_len;
341 	if (state->buffer_size != buf_len) {
342 		free(state->buffer);
343 		state->buffer = malloc(buf_len);
344 		if (state->buffer == NULL)
345 			goto eexit;
346 		state->buffer_size = buf_len;
347 		state->buffer_len = state->buffer_pos = 0;
348 	}
349 
350 #ifdef BIOCIMMEDIATE
351 	flags = 1;
352 	if (ioctl(fd, BIOCIMMEDIATE, &flags) == -1)
353 		goto eexit;
354 #endif
355 
356 	/* Install the DHCP filter */
357 	memset(&pf, 0, sizeof(pf));
358 	if (protocol == ETHERTYPE_ARP) {
359 		pf.bf_insns = UNCONST(arp_bpf_filter);
360 		pf.bf_len = arp_bpf_filter_len;
361 	} else {
362 		pf.bf_insns = UNCONST(dhcp_bpf_filter);
363 		pf.bf_len = dhcp_bpf_filter_len;
364 	}
365 	if (ioctl(fd, BIOCSETF, &pf) == -1)
366 		goto eexit;
367 
368 	return fd;
369 
370 eexit:
371 	free(state->buffer);
372 	state->buffer = NULL;
373 	close(fd);
374 	return -1;
375 }
376 
377 ssize_t
if_sendrawpacket(const struct interface * ifp,uint16_t protocol,const void * data,size_t len,const uint8_t * dest_hw_addr)378 if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
379     const void *data, size_t len, const uint8_t *dest_hw_addr)
380 {
381 	struct iovec iov[2];
382 	struct ether_header hw;
383 	int fd;
384 	const struct dhcp_state *state;
385 
386 	memset(&hw, 0, ETHER_HDR_LEN);
387 	if (dest_hw_addr)
388 		memcpy(&hw.ether_dhost, dest_hw_addr, ETHER_ADDR_LEN);
389 	else
390 		memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
391 	hw.ether_type = htons(protocol);
392 	iov[0].iov_base = &hw;
393 	iov[0].iov_len = ETHER_HDR_LEN;
394 	iov[1].iov_base = UNCONST(data);
395 	iov[1].iov_len = len;
396 	state = D_CSTATE(ifp);
397 	if (protocol == ETHERTYPE_ARP)
398 		fd = state->arp_fd;
399 	else
400 		fd = state->raw_fd;
401 	return writev(fd, iov, 2);
402 }
403 
404 /* BPF requires that we read the entire buffer.
405  * So we pass the buffer in the API so we can loop on >1 packet. */
406 ssize_t
if_readrawpacket(struct interface * ifp,uint16_t protocol,void * data,size_t len,int * flags)407 if_readrawpacket(struct interface *ifp, uint16_t protocol,
408     void *data, size_t len, int *flags)
409 {
410 	int fd;
411 	struct bpf_hdr packet;
412 	ssize_t bytes;
413 	const unsigned char *payload;
414 	struct dhcp_state *state;
415 
416 	state = D_STATE(ifp);
417 	if (protocol == ETHERTYPE_ARP)
418 		fd = state->arp_fd;
419 	else
420 		fd = state->raw_fd;
421 
422 	*flags = 0;
423 	for (;;) {
424 		if (state->buffer_len == 0) {
425 			bytes = read(fd, state->buffer, state->buffer_size);
426 			if (bytes == -1 || bytes == 0)
427 				return bytes;
428 			state->buffer_len = (size_t)bytes;
429 			state->buffer_pos = 0;
430 		}
431 		bytes = -1;
432 		memcpy(&packet, state->buffer + state->buffer_pos,
433 		    sizeof(packet));
434 		if (packet.bh_caplen != packet.bh_datalen)
435 			goto next; /* Incomplete packet, drop. */
436 		if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
437 		    state->buffer_len)
438 			goto next; /* Packet beyond buffer, drop. */
439 		payload = state->buffer + state->buffer_pos +
440 		    packet.bh_hdrlen + ETHER_HDR_LEN;
441 		bytes = (ssize_t)packet.bh_caplen - ETHER_HDR_LEN;
442 		if ((size_t)bytes > len)
443 			bytes = (ssize_t)len;
444 		memcpy(data, payload, (size_t)bytes);
445 next:
446 		state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
447 		    packet.bh_caplen);
448 		if (state->buffer_pos >= state->buffer_len) {
449 			state->buffer_len = state->buffer_pos = 0;
450 			*flags |= RAW_EOF;
451 		}
452 		if (bytes != -1)
453 			return bytes;
454 	}
455 }
456 
457 int
if_address(const struct interface * ifp,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)458 if_address(const struct interface *ifp, const struct in_addr *address,
459     const struct in_addr *netmask, const struct in_addr *broadcast,
460     int action)
461 {
462 	int s, r;
463 	struct in_aliasreq ifra;
464 
465 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
466 		return -1;
467 
468 	memset(&ifra, 0, sizeof(ifra));
469 	strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name));
470 
471 #define ADDADDR(var, addr) do {						      \
472 		(var)->sin_family = AF_INET;				      \
473 		(var)->sin_len = sizeof(*(var));			      \
474 		(var)->sin_addr = *(addr);				      \
475 	} while (/*CONSTCOND*/0)
476 	ADDADDR(&ifra.ifra_addr, address);
477 	ADDADDR(&ifra.ifra_mask, netmask);
478 	if (action >= 0 && broadcast)
479 		ADDADDR(&ifra.ifra_broadaddr, broadcast);
480 #undef ADDADDR
481 
482 	r = ioctl(s,
483 	    action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
484 	close(s);
485 	return r;
486 }
487 
488 static int
if_copyrt(struct dhcpcd_ctx * ctx,struct rt * rt,struct rt_msghdr * rtm)489 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
490 {
491 	char *cp;
492 	struct sockaddr *sa, *rti_info[RTAX_MAX];
493 
494 	cp = (char *)(void *)(rtm + 1);
495 	sa = (struct sockaddr *)(void *)cp;
496 	if (sa->sa_family != AF_INET)
497 		return -1;
498 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
499 		return -1;
500 #ifdef RTF_CLONED
501 	if (rtm->rtm_flags & RTF_CLONED)
502 		return -1;
503 #endif
504 #ifdef RTF_LOCAL
505 	if (rtm->rtm_flags & RTF_LOCAL)
506 		return -1;
507 #endif
508 #ifdef RTF_BROADCAST
509 	if (rtm->rtm_flags & RTF_BROADCAST)
510 		return -1;
511 #endif
512 
513 	get_addrs(rtm->rtm_addrs, cp, rti_info);
514 	memset(rt, 0, sizeof(*rt));
515 	COPYOUT(rt->dest, rti_info[RTAX_DST]);
516 	if (rtm->rtm_addrs & RTA_NETMASK)
517 		COPYOUT(rt->net, rti_info[RTAX_NETMASK]);
518 	else
519 		rt->net.s_addr = INADDR_BROADCAST;
520 	COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
521 
522 	if (rtm->rtm_index)
523 		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
524 	else if (rtm->rtm_addrs & RTA_IFP) {
525 		struct sockaddr_dl *sdl;
526 
527 		sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
528 		rt->iface = if_findsdl(ctx, sdl);
529 	}
530 	/* If we don't have an interface and it's a host route, it maybe
531 	 * to a local ip via the loopback interface. */
532 	if (rt->iface == NULL &&
533 	    !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY)))
534 	{
535 		struct ipv4_addr *ia;
536 
537 		if ((ia = ipv4_findaddr(ctx, &rt->dest)))
538 			rt->iface = ia->iface;
539 	}
540 
541 	return 0;
542 }
543 
544 int
if_route(unsigned char cmd,const struct rt * rt)545 if_route(unsigned char cmd, const struct rt *rt)
546 {
547 	const struct dhcp_state *state;
548 	union sockunion {
549 		struct sockaddr sa;
550 		struct sockaddr_in sin;
551 		struct sockaddr_dl sdl;
552 	} su;
553 	struct rtm
554 	{
555 		struct rt_msghdr hdr;
556 		char buffer[sizeof(su) * RTAX_MAX];
557 	} rtm;
558 	char *bp = rtm.buffer;
559 	size_t l;
560 	int s, retval;
561 
562 	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
563 		return -1;
564 
565 #define ADDSU {								      \
566 		l = RT_ROUNDUP(su.sa.sa_len);				      \
567 		memcpy(bp, &su, l);					      \
568 		bp += l;						      \
569 	}
570 #define ADDADDR(addr) {							      \
571 		memset(&su, 0, sizeof(su));				      \
572 		su.sin.sin_family = AF_INET;				      \
573 		su.sin.sin_len = sizeof(su.sin);			      \
574 		(&su.sin)->sin_addr = *addr;				      \
575 		ADDSU;							      \
576 	}
577 
578 	if (cmd != RTM_DELETE)
579 		state = D_CSTATE(rt->iface);
580 	else	/* appease GCC */
581 		state = NULL;
582 	memset(&rtm, 0, sizeof(rtm));
583 	rtm.hdr.rtm_version = RTM_VERSION;
584 	rtm.hdr.rtm_seq = 1;
585 	rtm.hdr.rtm_type = cmd;
586 	rtm.hdr.rtm_addrs = RTA_DST;
587 	if (cmd == RTM_ADD || cmd == RTM_CHANGE)
588 		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
589 	rtm.hdr.rtm_flags = RTF_UP;
590 #ifdef RTF_PINNED
591 	if (cmd != RTM_ADD)
592 		rtm.hdr.rtm_flags |= RTF_PINNED;
593 #endif
594 
595 	if (cmd != RTM_DELETE) {
596 		rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP;
597 		/* None interface subnet routes are static. */
598 		if (rt->gate.s_addr != INADDR_ANY ||
599 		    rt->net.s_addr != state->net.s_addr ||
600 		    rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
601 			rtm.hdr.rtm_flags |= RTF_STATIC;
602 		else {
603 #ifdef RTF_CLONING
604 			rtm.hdr.rtm_flags |= RTF_CLONING;
605 #endif
606 #ifdef RTP_CONNECTED
607 			rtm.hdr.rtm_priority = RTP_CONNECTED;
608 #endif
609 		}
610 	}
611 	if (rt->net.s_addr == htonl(INADDR_BROADCAST) &&
612 	    rt->gate.s_addr == htonl(INADDR_ANY))
613 	{
614 #ifdef RTF_CLONING
615 		/* We add a cloning network route for a single host.
616 		 * Traffic to the host will generate a cloned route and the
617 		 * hardware address will resolve correctly.
618 		 * It might be more correct to use RTF_HOST instead of
619 		 * RTF_CLONING, and that does work, but some OS generate
620 		 * an arp warning diagnostic which we don't want to do. */
621 		rtm.hdr.rtm_flags |= RTF_CLONING;
622 		rtm.hdr.rtm_addrs |= RTA_NETMASK;
623 #else
624 		rtm.hdr.rtm_flags |= RTF_HOST;
625 #endif
626 	} else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
627 	    rt->net.s_addr == htonl(INADDR_BROADCAST))
628 	{
629 		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
630 		/* Going via lo0 so remove the interface flags */
631 		if (cmd == RTM_ADD)
632 			rtm.hdr.rtm_addrs &= ~(RTA_IFA | RTA_IFP);
633 	} else {
634 		rtm.hdr.rtm_addrs |= RTA_NETMASK;
635 		if (rtm.hdr.rtm_flags & RTF_STATIC)
636 			rtm.hdr.rtm_flags |= RTF_GATEWAY;
637 	}
638 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
639 	    !(rtm.hdr.rtm_flags & RTF_GATEWAY))
640 		rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP;
641 
642 	ADDADDR(&rt->dest);
643 	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
644 #ifdef RTF_CLONING
645 		if ((rtm.hdr.rtm_flags & (RTF_HOST | RTF_CLONING) &&
646 #else
647 		if ((rtm.hdr.rtm_flags & RTF_HOST &&
648 #endif
649 		    rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
650 		    !(rtm.hdr.rtm_flags & RTF_STATIC))
651 		{
652 			if_linkaddr(&su.sdl, rt->iface);
653 			ADDSU;
654 		} else
655 			ADDADDR(&rt->gate);
656 	}
657 
658 	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
659 		ADDADDR(&rt->net);
660 
661 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
662 	    (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)))
663 	{
664 		rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
665 		if (rtm.hdr.rtm_addrs & RTA_IFP) {
666 			if_linkaddr(&su.sdl, rt->iface);
667 			ADDSU;
668 		}
669 
670 		if (rtm.hdr.rtm_addrs & RTA_IFA)
671 			ADDADDR(&state->addr);
672 	}
673 
674 #undef ADDADDR
675 #undef ADDSU
676 
677 	rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
678 	retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
679 	close(s);
680 	return retval;
681 }
682 
683 int
if_initrt(struct interface * ifp)684 if_initrt(struct interface *ifp)
685 {
686 	struct rt_msghdr *rtm;
687 	int mib[6];
688 	size_t needed;
689 	char *buf, *p, *end;
690 	struct rt rt;
691 
692 	ipv4_freerts(ifp->ctx->ipv4_kroutes);
693 
694 	mib[0] = CTL_NET;
695 	mib[1] = PF_ROUTE;
696 	mib[2] = 0;
697 	mib[3] = AF_INET;
698 	mib[4] = NET_RT_DUMP;
699 	mib[5] = 0;
700 
701 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
702 		return -1;
703 	if (needed == 0)
704 		return 0;
705 	if ((buf = malloc(needed)) == NULL)
706 		return -1;
707 	if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
708 		return -1;
709 
710 	end = buf + needed;
711 	for (p = buf; p < end; p += rtm->rtm_msglen) {
712 		rtm = (struct rt_msghdr *)(void *)p;
713 		if (if_copyrt(ifp->ctx, &rt, rtm) == 0)
714 			ipv4_handlert(ifp->ctx, RTM_ADD, &rt);
715 	}
716 	free(buf);
717 	return 0;
718 }
719 
720 #ifdef SIOCGIFAFLAG_IN
721 int
if_addrflags(const struct in_addr * addr,const struct interface * ifp)722 if_addrflags(const struct in_addr *addr, const struct interface *ifp)
723 {
724 	int s, flags;
725 	struct ifreq ifr;
726 	struct sockaddr_in *sin;
727 
728 	s = socket(PF_INET, SOCK_DGRAM, 0);
729 	flags = -1;
730 	if (s != -1) {
731 		memset(&ifr, 0, sizeof(ifr));
732 		strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
733 		sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
734 		sin->sin_family = AF_INET;
735 		sin->sin_addr = *addr;
736 		if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1)
737 			flags = ifr.ifr_addrflags;
738 		close(s);
739 	}
740 	return flags;
741 }
742 #else
743 int
if_addrflags(__unused const struct in_addr * addr,__unused const struct interface * ifp)744 if_addrflags(__unused const struct in_addr *addr,
745     __unused const struct interface *ifp)
746 {
747 
748 	errno = ENOTSUP;
749 	return 0;
750 }
751 #endif
752 #endif /* INET */
753 
754 #ifdef INET6
755 static void
ifa_scope(struct sockaddr_in6 * sin,unsigned int ifindex)756 ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex)
757 {
758 
759 #ifdef __KAME__
760 	/* KAME based systems want to store the scope inside the sin6_addr
761 	 * for link local addreses */
762 	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
763 		uint16_t scope = htons((uint16_t)ifindex);
764 		memcpy(&sin->sin6_addr.s6_addr[2], &scope,
765 		    sizeof(scope));
766 	}
767 	sin->sin6_scope_id = 0;
768 #else
769 	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
770 		sin->sin6_scope_id = ifindex;
771 	else
772 		sin->sin6_scope_id = 0;
773 #endif
774 }
775 
776 #ifdef __KAME__
777 #define DESCOPE(ia6) do {						      \
778 	if (IN6_IS_ADDR_LINKLOCAL((ia6)))				      \
779 		(ia6)->s6_addr[2] = (ia6)->s6_addr[3] = '\0';		      \
780 	} while (/*CONSTCOND */0)
781 #else
782 #define DESCOPE(ia6)
783 #endif
784 
785 int
if_address6(const struct ipv6_addr * a,int action)786 if_address6(const struct ipv6_addr *a, int action)
787 {
788 	int s, r;
789 	struct in6_aliasreq ifa;
790 	struct in6_addr mask;
791 
792 	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
793 		return -1;
794 
795 	memset(&ifa, 0, sizeof(ifa));
796 	strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
797 	/*
798 	 * We should not set IN6_IFF_TENTATIVE as the kernel should be
799 	 * able to work out if it's a new address or not.
800 	 *
801 	 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us.
802 	 * This is probably a safety measure, but still it's not entirely right
803 	 * either.
804 	 */
805 #if 0
806 	if (a->autoconf)
807 		ifa.ifra_flags |= IN6_IFF_AUTOCONF;
808 #endif
809 #ifdef IPV6_MANGETEMPADDR
810 	if (a->flags & IPV6_AF_TEMPORARY)
811 		ifa.ifra_flags |= IN6_IFF_TEMPORARY;
812 #endif
813 
814 #define ADDADDR(v, addr) {						      \
815 		(v)->sin6_family = AF_INET6;				      \
816 		(v)->sin6_len = sizeof(*v);				      \
817 		(v)->sin6_addr = *addr;					      \
818 	}
819 
820 	ADDADDR(&ifa.ifra_addr, &a->addr);
821 	ifa_scope(&ifa.ifra_addr, a->iface->index);
822 	ipv6_mask(&mask, a->prefix_len);
823 	ADDADDR(&ifa.ifra_prefixmask, &mask);
824 	ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
825 	ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
826 #undef ADDADDR
827 
828 	r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
829 	close(s);
830 	return r;
831 }
832 
833 
834 static int
if_copyrt6(struct dhcpcd_ctx * ctx,struct rt6 * rt,struct rt_msghdr * rtm)835 if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
836 {
837 	char *cp;
838 	struct sockaddr *sa, *rti_info[RTAX_MAX];
839 
840 	cp = (char *)(void *)(rtm + 1);
841 	sa = (struct sockaddr *)(void *)cp;
842 	if (sa->sa_family != AF_INET6)
843 		return -1;
844 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
845 		return -1;
846 #ifdef RTF_CLONED
847 	if (rtm->rtm_flags & (RTF_CLONED | RTF_HOST))
848 		return -1;
849 #else
850 	if (rtm->rtm_flags & RTF_HOST)
851 		return -1;
852 #endif
853 #ifdef RTF_LOCAL
854 	if (rtm->rtm_flags & RTF_LOCAL)
855 		return -1;
856 #endif
857 
858 	get_addrs(rtm->rtm_addrs, cp, rti_info);
859 	memset(rt, 0, sizeof(*rt));
860 	rt->flags = (unsigned int)rtm->rtm_flags;
861 	COPYOUT6(rt->dest, rti_info[RTAX_DST]);
862 	if (rtm->rtm_addrs & RTA_NETMASK) {
863 		/*
864 		 * We need to zero out the struct beyond sin6_len and
865 		 * ensure it's valid.
866 		 * I have no idea what the invalid data is for, could be
867 		 * a kernel bug or actually used for something.
868 		 * Either way it needs to be zeroed out.
869 		 */
870 		struct sockaddr_in6 *sin6;
871 		size_t e, i, len = 0, final = 0;
872 
873 		sin6 = (struct sockaddr_in6 *)(void *)rti_info[RTAX_NETMASK];
874 		rt->net = sin6->sin6_addr;
875 		e = sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr);
876 		if (e > sizeof(struct in6_addr))
877 			e = sizeof(struct in6_addr);
878 		for (i = 0; i < e; i++) {
879 			switch (rt->net.s6_addr[i] & 0xff) {
880 			case 0xff:
881 				/* We don't really want the length,
882 				 * just that it's valid */
883 				len++;
884 				break;
885 			case 0xfe:
886 			case 0xfc:
887 			case 0xf8:
888 			case 0xf0:
889 			case 0xe0:
890 			case 0xc0:
891 			case 0x80:
892 				len++;
893 				final = 1;
894 				break;
895 			default:
896 				rt->net.s6_addr[i] = 0x00;
897 				final = 1;
898 				break;
899 			}
900 			if (final)
901 				break;
902 		}
903 		if (len == 0)
904 			i = 0;
905 		while (i < sizeof(rt->net.s6_addr))
906 			rt->net.s6_addr[i++] = 0x00;
907 	} else
908 		ipv6_mask(&rt->net, 128);
909 	COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
910 
911 	if (rtm->rtm_index)
912 		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
913 	else if (rtm->rtm_addrs & RTA_IFP) {
914 		struct sockaddr_dl *sdl;
915 
916 		sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
917 		rt->iface = if_findsdl(ctx, sdl);
918 	}
919 	/* If we don't have an interface and it's a host route, it maybe
920 	 * to a local ip via the loopback interface. */
921 	if (rt->iface == NULL &&
922 	    !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY)))
923 	{
924 		struct ipv6_addr *ia;
925 
926 		if ((ia = ipv6_findaddr(ctx, &rt->dest, 0)))
927 			rt->iface = ia->iface;
928 	}
929 
930 	return 0;
931 }
932 
933 int
if_route6(unsigned char cmd,const struct rt6 * rt)934 if_route6(unsigned char cmd, const struct rt6 *rt)
935 {
936 	union sockunion {
937 		struct sockaddr sa;
938 		struct sockaddr_in6 sin;
939 		struct sockaddr_dl sdl;
940 	} su;
941 	struct rtm
942 	{
943 		struct rt_msghdr hdr;
944 		char buffer[sizeof(su) * RTAX_MAX];
945 	} rtm;
946 	char *bp = rtm.buffer;
947 	size_t l;
948 	int s, retval;
949 
950 	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
951 		return -1;
952 
953 #define ADDSU {								      \
954 		l = RT_ROUNDUP(su.sa.sa_len);				      \
955 		memcpy(bp, &su, l);					      \
956 		bp += l;						      \
957 	}
958 #define ADDADDRS(addr, scope) {						      \
959 		memset(&su, 0, sizeof(su));				      \
960 		su.sin.sin6_family = AF_INET6;				      \
961 		su.sin.sin6_len = sizeof(su.sin);			      \
962 		(&su.sin)->sin6_addr = *addr;				      \
963 		if (scope)						      \
964 			ifa_scope(&su.sin, scope);			      \
965 		ADDSU;							      \
966 	}
967 #define ADDADDR(addr) ADDADDRS(addr, 0)
968 
969 	memset(&rtm, 0, sizeof(rtm));
970 	rtm.hdr.rtm_version = RTM_VERSION;
971 	rtm.hdr.rtm_seq = 1;
972 	rtm.hdr.rtm_type = cmd;
973 	rtm.hdr.rtm_flags = RTF_UP | (int)rt->flags;
974 #ifdef RTF_PINNED
975 	if (rtm.hdr.rtm_type != RTM_ADD)
976 		rtm.hdr.rtm_flags |= RTF_PINNED;
977 #endif
978 	rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
979 	/* None interface subnet routes are static. */
980 	if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
981 #ifdef RTF_CLONING
982 		rtm.hdr.rtm_flags |= RTF_CLONING;
983 #endif
984 #ifdef RTP_CONNECTED
985 		rtm.hdr.rtm_priority = RTP_CONNECTED;
986 #endif
987 	} else
988 		rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
989 
990 	if (cmd == RTM_ADD)
991 		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
992 	if (cmd == RTM_ADD && !(rtm.hdr.rtm_flags & RTF_REJECT))
993 		rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
994 
995 	ADDADDR(&rt->dest);
996 	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
997 		if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
998 			if_linkaddr(&su.sdl, rt->iface);
999 			ADDSU;
1000 		} else {
1001 			ADDADDRS(&rt->gate, rt->iface->index);
1002 		}
1003 	}
1004 
1005 	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
1006 		ADDADDR(&rt->net);
1007 
1008 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
1009 	    (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)))
1010 	{
1011 		rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
1012 		if (rtm.hdr.rtm_addrs & RTA_IFP) {
1013 			if_linkaddr(&su.sdl, rt->iface);
1014 			ADDSU;
1015 		}
1016 
1017 		if (rtm.hdr.rtm_addrs & RTA_IFA) {
1018 			const struct ipv6_addr *lla;
1019 
1020 			lla = ipv6_linklocal(rt->iface);
1021 			if (lla == NULL) /* unlikely */
1022 					return -1;
1023 			ADDADDRS(&lla->addr, rt->iface->index);
1024 		}
1025 
1026 		if (rt->mtu) {
1027 			rtm.hdr.rtm_inits |= RTV_MTU;
1028 			rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
1029 		}
1030 	}
1031 
1032 #undef ADDADDR
1033 #undef ADDSU
1034 
1035 	rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
1036 	retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
1037 	close(s);
1038 	return retval;
1039 }
1040 
1041 int
if_initrt6(struct interface * ifp)1042 if_initrt6(struct interface *ifp)
1043 {
1044 	struct rt_msghdr *rtm;
1045 	int mib[6];
1046 	size_t needed;
1047 	char *buf, *p, *end;
1048 	struct rt6 rt;
1049 
1050 	ipv6_freerts(&ifp->ctx->ipv6->kroutes);
1051 
1052 	mib[0] = CTL_NET;
1053 	mib[1] = PF_ROUTE;
1054 	mib[2] = 0;
1055 	mib[3] = AF_INET6;
1056 	mib[4] = NET_RT_DUMP;
1057 	mib[5] = 0;
1058 
1059 	if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
1060 		return -1;
1061 	if (needed == 0)
1062 		return 0;
1063 	if ((buf = malloc(needed)) == NULL)
1064 		return -1;
1065 	if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
1066 		return -1;
1067 
1068 	end = buf + needed;
1069 	for (p = buf; p < end; p += rtm->rtm_msglen) {
1070 		rtm = (struct rt_msghdr *)(void *)p;
1071 		if (if_copyrt6(ifp->ctx, &rt, rtm) == 0)
1072 			ipv6_handlert(ifp->ctx, RTM_ADD, &rt);
1073 	}
1074 	free(buf);
1075 	return 0;
1076 }
1077 
1078 int
if_addrflags6(const struct in6_addr * addr,const struct interface * ifp)1079 if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
1080 {
1081 	int s, flags;
1082 	struct in6_ifreq ifr6;
1083 
1084 	s = socket(PF_INET6, SOCK_DGRAM, 0);
1085 	flags = -1;
1086 	if (s != -1) {
1087 		memset(&ifr6, 0, sizeof(ifr6));
1088 		strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
1089 		ifr6.ifr_addr.sin6_family = AF_INET6;
1090 		ifr6.ifr_addr.sin6_addr = *addr;
1091 		ifa_scope(&ifr6.ifr_addr, ifp->index);
1092 		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1)
1093 			flags = ifr6.ifr_ifru.ifru_flags6;
1094 		close(s);
1095 	}
1096 	return flags;
1097 }
1098 
1099 int
if_getlifetime6(struct ipv6_addr * ia)1100 if_getlifetime6(struct ipv6_addr *ia)
1101 {
1102 	int s, r;
1103 	struct in6_ifreq ifr6;
1104 
1105 	s = socket(PF_INET6, SOCK_DGRAM, 0);
1106 	r = -1;
1107 	if (s != -1) {
1108 		memset(&ifr6, 0, sizeof(ifr6));
1109 		strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
1110 		ifr6.ifr_addr.sin6_family = AF_INET6;
1111 		ifr6.ifr_addr.sin6_addr = ia->addr;
1112 		ifa_scope(&ifr6.ifr_addr, ia->iface->index);
1113 		if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) != -1) {
1114 			time_t t;
1115 			struct in6_addrlifetime *lifetime;
1116 
1117 			t = time(NULL);
1118 			lifetime = &ifr6.ifr_ifru.ifru_lifetime;
1119 
1120 			if (lifetime->ia6t_preferred)
1121 				ia->prefix_pltime =
1122 				    (uint32_t)(lifetime->ia6t_preferred -
1123 				    MIN(t, lifetime->ia6t_preferred));
1124 			else
1125 				ia->prefix_pltime = ND6_INFINITE_LIFETIME;
1126 			if (lifetime->ia6t_expire) {
1127 				ia->prefix_vltime =
1128 				    (uint32_t)(lifetime->ia6t_expire -
1129 				    MIN(t, lifetime->ia6t_expire));
1130 				/* Calculate the created time */
1131 				get_monotonic(&ia->created);
1132 				ia->created.tv_sec -=
1133 				    lifetime->ia6t_vltime - ia->prefix_vltime;
1134 			} else
1135 				ia->prefix_vltime = ND6_INFINITE_LIFETIME;
1136 
1137 			r = 0;
1138 		}
1139 		close(s);
1140 	}
1141 	return r;
1142 }
1143 #endif
1144 
1145 int
if_managelink(struct dhcpcd_ctx * ctx)1146 if_managelink(struct dhcpcd_ctx *ctx)
1147 {
1148 	/* route and ifwatchd like a msg buf size of 2048 */
1149 	char msg[2048], *p, *e, *cp;
1150 	ssize_t bytes;
1151 	struct rt_msghdr *rtm;
1152 	struct if_announcemsghdr *ifan;
1153 	struct if_msghdr *ifm;
1154 	struct ifa_msghdr *ifam;
1155 	struct sockaddr *sa, *rti_info[RTAX_MAX];
1156 	int len;
1157 	struct sockaddr_dl sdl;
1158 	struct interface *ifp;
1159 #ifdef INET
1160 	struct rt rt;
1161 #endif
1162 #ifdef INET6
1163 	struct rt6 rt6;
1164 	struct in6_addr ia6, net6;
1165 	struct sockaddr_in6 *sin6;
1166 #endif
1167 #if (defined(INET) && defined(IN_IFF_TENTATIVE)) || defined(INET6)
1168 	int ifa_flags;
1169 #endif
1170 
1171 	if ((bytes = read(ctx->link_fd, msg, sizeof(msg))) == -1)
1172 		return -1;
1173 	e = msg + bytes;
1174 	for (p = msg; p < e; p += rtm->rtm_msglen) {
1175 		rtm = (struct rt_msghdr *)(void *)p;
1176 		// Ignore messages generated by us
1177 		if (rtm->rtm_pid == getpid())
1178 			break;
1179 		switch(rtm->rtm_type) {
1180 #ifdef RTM_IFANNOUNCE
1181 		case RTM_IFANNOUNCE:
1182 			ifan = (struct if_announcemsghdr *)(void *)p;
1183 			switch(ifan->ifan_what) {
1184 			case IFAN_ARRIVAL:
1185 				dhcpcd_handleinterface(ctx, 1,
1186 				    ifan->ifan_name);
1187 				break;
1188 			case IFAN_DEPARTURE:
1189 				dhcpcd_handleinterface(ctx, -1,
1190 				    ifan->ifan_name);
1191 				break;
1192 			}
1193 			break;
1194 #endif
1195 		case RTM_IFINFO:
1196 			ifm = (struct if_msghdr *)(void *)p;
1197 			ifp = if_findindex(ctx->ifaces, ifm->ifm_index);
1198 			if (ifp == NULL)
1199 				break;
1200 			switch (ifm->ifm_data.ifi_link_state) {
1201 			case LINK_STATE_DOWN:
1202 				len = LINK_DOWN;
1203 				break;
1204 			case LINK_STATE_UP:
1205 				len = LINK_UP;
1206 				break;
1207 			default:
1208 				/* handle_carrier will re-load
1209 				 * the interface flags and check for
1210 				 * IFF_RUNNING as some drivers that
1211 				 * don't handle link state also don't
1212 				 * set IFF_RUNNING when this routing
1213 				 * message is generated.
1214 				 * As such, it is a race ...*/
1215 				len = LINK_UNKNOWN;
1216 				break;
1217 			}
1218 			dhcpcd_handlecarrier(ctx, len,
1219 			    (unsigned int)ifm->ifm_flags, ifp->name);
1220 			break;
1221 		case RTM_ADD:
1222 		case RTM_CHANGE:
1223 		case RTM_DELETE:
1224 			cp = (char *)(void *)(rtm + 1);
1225 			sa = (struct sockaddr *)(void *)cp;
1226 			switch (sa->sa_family) {
1227 #ifdef INET
1228 			case AF_INET:
1229 				if (if_copyrt(ctx, &rt, rtm) == 0)
1230 					ipv4_handlert(ctx, rtm->rtm_type, &rt);
1231 				break;
1232 #endif
1233 #ifdef INET6
1234 			case AF_INET6:
1235 				if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
1236 					break;
1237 				/*
1238 				 * BSD caches host routes in the
1239 				 * routing table.
1240 				 * As such, we should be notified of
1241 				 * reachability by its existance
1242 				 * with a hardware address
1243 				 */
1244 				if (rtm->rtm_flags & (RTF_HOST)) {
1245 					get_addrs(rtm->rtm_addrs, cp, rti_info);
1246 					COPYOUT6(ia6, rti_info[RTAX_DST]);
1247 					DESCOPE(&ia6);
1248 					if (rti_info[RTAX_GATEWAY]->sa_family
1249 					    == AF_LINK)
1250 						memcpy(&sdl,
1251 						    rti_info[RTAX_GATEWAY],
1252 						    sizeof(sdl));
1253 					else
1254 						sdl.sdl_alen = 0;
1255 					ipv6nd_neighbour(ctx, &ia6,
1256 					    rtm->rtm_type != RTM_DELETE &&
1257 					    sdl.sdl_alen ?
1258 					    IPV6ND_REACHABLE : 0);
1259 					break;
1260 				}
1261 
1262 				if (if_copyrt6(ctx, &rt6, rtm) == 0)
1263 					ipv6_handlert(ctx, rtm->rtm_type, &rt6);
1264 				break;
1265 #endif
1266 			}
1267 			break;
1268 #ifdef RTM_CHGADDR
1269 		case RTM_CHGADDR:	/* FALLTHROUGH */
1270 #endif
1271 		case RTM_DELADDR:	/* FALLTHROUGH */
1272 		case RTM_NEWADDR:
1273 			ifam = (struct ifa_msghdr *)(void *)p;
1274 			ifp = if_findindex(ctx->ifaces, ifam->ifam_index);
1275 			if (ifp == NULL)
1276 				break;
1277 			cp = (char *)(void *)(ifam + 1);
1278 			get_addrs(ifam->ifam_addrs, cp, rti_info);
1279 			if (rti_info[RTAX_IFA] == NULL)
1280 				break;
1281 			switch (rti_info[RTAX_IFA]->sa_family) {
1282 			case AF_LINK:
1283 #ifdef RTM_CHGADDR
1284 				if (rtm->rtm_type != RTM_CHGADDR)
1285 					break;
1286 #else
1287 				if (rtm->rtm_type != RTM_NEWADDR)
1288 					break;
1289 #endif
1290 				memcpy(&sdl, rti_info[RTAX_IFA],
1291 				    rti_info[RTAX_IFA]->sa_len);
1292 				dhcpcd_handlehwaddr(ctx, ifp->name,
1293 				    (const unsigned char*)CLLADDR(&sdl),
1294 				    sdl.sdl_alen);
1295 				break;
1296 #ifdef INET
1297 			case AF_INET:
1298 			case 255: /* FIXME: Why 255? */
1299 				COPYOUT(rt.dest, rti_info[RTAX_IFA]);
1300 				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
1301 				COPYOUT(rt.gate, rti_info[RTAX_BRD]);
1302 				if (rtm->rtm_type == RTM_NEWADDR) {
1303 					ifa_flags = if_addrflags(&rt.dest, ifp);
1304 					if (ifa_flags == -1)
1305 						break;
1306 				} else
1307 					ifa_flags = 0;
1308 				ipv4_handleifa(ctx, rtm->rtm_type,
1309 				    NULL, ifp->name,
1310 				    &rt.dest, &rt.net, &rt.gate, ifa_flags);
1311 				break;
1312 #endif
1313 #ifdef INET6
1314 			case AF_INET6:
1315 				sin6 = (struct sockaddr_in6*)(void *)
1316 				    rti_info[RTAX_IFA];
1317 				ia6 = sin6->sin6_addr;
1318 				DESCOPE(&ia6);
1319 				sin6 = (struct sockaddr_in6*)(void *)
1320 				    rti_info[RTAX_NETMASK];
1321 				net6 = sin6->sin6_addr;
1322 				DESCOPE(&net6);
1323 				if (rtm->rtm_type == RTM_NEWADDR) {
1324 					ifa_flags = if_addrflags6(&ia6, ifp);
1325 					if (ifa_flags == -1)
1326 						break;
1327 				} else
1328 					ifa_flags = 0;
1329 				ipv6_handleifa(ctx, rtm->rtm_type, NULL,
1330 				    ifp->name, &ia6, ipv6_prefixlen(&net6),
1331 				    ifa_flags);
1332 				break;
1333 #endif
1334 			}
1335 			break;
1336 		}
1337 	}
1338 	return 0;
1339 }
1340 
1341 #ifndef SYS_NMLN	/* OSX */
1342 #  define SYS_NMLN 256
1343 #endif
1344 #ifndef HW_MACHINE_ARCH
1345 #  ifdef HW_MODEL	/* OpenBSD */
1346 #    define HW_MACHINE_ARCH HW_MODEL
1347 #  endif
1348 #endif
1349 int
if_machinearch(char * str,size_t len)1350 if_machinearch(char *str, size_t len)
1351 {
1352 	int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1353 	char march[SYS_NMLN];
1354 	size_t marchlen = sizeof(march);
1355 
1356 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1357 	    march, &marchlen, NULL, 0) != 0)
1358 		return -1;
1359 	return snprintf(str, len, ":%s", march);
1360 }
1361 
1362 #ifdef INET6
1363 #ifdef IPV6CTL_ACCEPT_RTADV
1364 #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0)
1365 #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1)
1366 static int
inet6_sysctl(int code,int val,int action)1367 inet6_sysctl(int code, int val, int action)
1368 {
1369 	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
1370 	size_t size;
1371 
1372 	mib[3] = code;
1373 	size = sizeof(val);
1374 	if (action) {
1375 		if (sysctl(mib, sizeof(mib)/sizeof(mib[0]),
1376 		    NULL, 0, &val, size) == -1)
1377 			return -1;
1378 		return 0;
1379 	}
1380 	if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1)
1381 		return -1;
1382 	return val;
1383 }
1384 #endif
1385 
1386 #ifdef IPV6_MANAGETEMPADDR
1387 #ifndef IPV6CTL_TEMPVLTIME
1388 #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0)
1389 #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1)
1390 static int
inet6_sysctlbyname(const char * name,int val,int action)1391 inet6_sysctlbyname(const char *name, int val, int action)
1392 {
1393 	size_t size;
1394 
1395 	size = sizeof(val);
1396 	if (action) {
1397 		if (sysctlbyname(name, NULL, 0, &val, size) == -1)
1398 			return -1;
1399 		return 0;
1400 	}
1401 	if (sysctlbyname(name, &val, &size, NULL, 0) == -1)
1402 		return -1;
1403 	return val;
1404 }
1405 #endif
1406 
1407 int
ip6_use_tempaddr(__unused const char * ifname)1408 ip6_use_tempaddr(__unused const char *ifname)
1409 {
1410 	int val;
1411 
1412 #ifdef IPV6CTL_USETEMPADDR
1413 	val = get_inet6_sysctl(IPV6CTL_USETEMPADDR);
1414 #else
1415 	val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr");
1416 #endif
1417 	return val == -1 ? 0 : val;
1418 }
1419 
1420 int
ip6_temp_preferred_lifetime(__unused const char * ifname)1421 ip6_temp_preferred_lifetime(__unused const char *ifname)
1422 {
1423 	int val;
1424 
1425 #ifdef IPV6CTL_TEMPPLTIME
1426 	val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME);
1427 #else
1428 	val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime");
1429 #endif
1430 	return val < 0 ? TEMP_PREFERRED_LIFETIME : val;
1431 }
1432 
1433 int
ip6_temp_valid_lifetime(__unused const char * ifname)1434 ip6_temp_valid_lifetime(__unused const char *ifname)
1435 {
1436 	int val;
1437 
1438 #ifdef IPV6CTL_TEMPVLTIME
1439 	val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME);
1440 #else
1441 	val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime");
1442 #endif
1443 	return val < 0 ? TEMP_VALID_LIFETIME : val;
1444 }
1445 #endif
1446 
1447 #define del_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), -1)
1448 #define get_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag),  0)
1449 #define set_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag),  1)
1450 static int
if_nd6_flag(int s,const struct interface * ifp,unsigned int flag,int set)1451 if_nd6_flag(int s, const struct interface *ifp, unsigned int flag, int set)
1452 {
1453 	struct in6_ndireq nd;
1454 	unsigned int oflags;
1455 
1456 	memset(&nd, 0, sizeof(nd));
1457 	strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname));
1458 	if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1)
1459 		return -1;
1460 	if (set == 0)
1461 		return nd.ndi.flags & flag ? 1 : 0;
1462 
1463 	oflags = nd.ndi.flags;
1464 	if (set == -1)
1465 		nd.ndi.flags &= ~flag;
1466 	else
1467 		nd.ndi.flags |= flag;
1468 	if (oflags == nd.ndi.flags)
1469 		return 0;
1470 	return ioctl(s, SIOCSIFINFO_FLAGS, &nd);
1471 }
1472 
1473 static int
if_raflush(int s)1474 if_raflush(int s)
1475 {
1476 	char dummy[IFNAMSIZ + 8];
1477 
1478 	strlcpy(dummy, "lo0", sizeof(dummy));
1479 	if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&dummy) == -1 ||
1480 	    ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&dummy) == -1)
1481 		return -1;
1482 	return 0;
1483 }
1484 
1485 #ifdef SIOCIFAFATTACH
1486 static int
af_attach(int s,const struct interface * ifp,int af)1487 af_attach(int s, const struct interface *ifp, int af)
1488 {
1489 	struct if_afreq ifar;
1490 
1491 	strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name));
1492 	ifar.ifar_af = af;
1493 	return ioctl(s, SIOCIFAFATTACH, (void *)&ifar);
1494 }
1495 #endif
1496 
1497 #ifdef SIOCGIFXFLAGS
1498 static int
set_ifxflags(int s,const struct interface * ifp,int own)1499 set_ifxflags(int s, const struct interface *ifp, int own)
1500 {
1501 	struct ifreq ifr;
1502 	int flags;
1503 
1504 #ifndef IFXF_NOINET6
1505 	/* No point in removing the no inet6 flag if it doesn't
1506 	 * exist and we're not owning inet6. */
1507 	if (! own)
1508 		return 0;
1509 #endif
1510 
1511 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
1512 	if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1)
1513 		return -1;
1514 	flags = ifr.ifr_flags;
1515 #ifdef IFXF_NOINET6
1516 	flags &= ~IFXF_NOINET6;
1517 #endif
1518 	if (own)
1519 		flags &= ~IFXF_AUTOCONF6;
1520 	if (ifr.ifr_flags == flags)
1521 		return 0;
1522 	ifr.ifr_flags = flags;
1523 	return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr);
1524 }
1525 #endif
1526 
1527 static int
_if_checkipv6(int s,struct dhcpcd_ctx * ctx,const struct interface * ifp,int own)1528 _if_checkipv6(int s, struct dhcpcd_ctx *ctx,
1529     const struct interface *ifp, int own)
1530 {
1531 	int ra;
1532 
1533 	if (ifp) {
1534 #ifdef ND6_IFF_OVERRIDE_RTADV
1535 		int override;
1536 #endif
1537 
1538 #ifdef ND6_IFF_IFDISABLED
1539 		if (del_if_nd6_flag(s, ifp, ND6_IFF_IFDISABLED) == -1) {
1540 			logger(ifp->ctx, LOG_ERR,
1541 			    "%s: del_if_nd6_flag: ND6_IFF_IFDISABLED: %m",
1542 			    ifp->name);
1543 			return -1;
1544 		}
1545 #endif
1546 
1547 #ifdef ND6_IFF_PERFORMNUD
1548 		if (set_if_nd6_flag(s, ifp, ND6_IFF_PERFORMNUD) == -1) {
1549 			logger(ifp->ctx, LOG_ERR,
1550 			    "%s: set_if_nd6_flag: ND6_IFF_PERFORMNUD: %m",
1551 			    ifp->name);
1552 			return -1;
1553 		}
1554 #endif
1555 
1556 #ifdef ND6_IFF_AUTO_LINKLOCAL
1557 		if (own) {
1558 			int all;
1559 
1560 			all = get_if_nd6_flag(s, ifp, ND6_IFF_AUTO_LINKLOCAL);
1561 			if (all == -1)
1562 				logger(ifp->ctx, LOG_ERR,
1563 				    "%s: get_if_nd6_flag: "
1564 				    "ND6_IFF_AUTO_LINKLOCAL: %m",
1565 				    ifp->name);
1566 			else if (all != 0) {
1567 				logger(ifp->ctx, LOG_DEBUG,
1568 				    "%s: disabling Kernel IPv6 "
1569 				    "auto link-local support",
1570 				    ifp->name);
1571 				if (del_if_nd6_flag(s, ifp,
1572 				    ND6_IFF_AUTO_LINKLOCAL) == -1)
1573 				{
1574 					logger(ifp->ctx, LOG_ERR,
1575 					    "%s: del_if_nd6_flag: "
1576 					    "ND6_IFF_AUTO_LINKLOCAL: %m",
1577 					    ifp->name);
1578 					return -1;
1579 				}
1580 			}
1581 		}
1582 #endif
1583 
1584 #ifdef SIOCIFAFATTACH
1585 		if (af_attach(s, ifp, AF_INET6) == -1) {
1586 			logger(ifp->ctx, LOG_ERR,
1587 			    "%s: af_attach: %m", ifp->name);
1588 			return 1;
1589 		}
1590 #endif
1591 
1592 #ifdef SIOCGIFXFLAGS
1593 		if (set_ifxflags(s, ifp, own) == -1) {
1594 			logger(ifp->ctx, LOG_ERR,
1595 			    "%s: set_ifxflags: %m", ifp->name);
1596 			return -1;
1597 		}
1598 #endif
1599 
1600 #ifdef ND6_IFF_OVERRIDE_RTADV
1601 		override = get_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV);
1602 		if (override == -1)
1603 			logger(ifp->ctx, LOG_ERR,
1604 			    "%s: get_if_nd6_flag: ND6_IFF_OVERRIDE_RTADV: %m",
1605 			    ifp->name);
1606 		else if (override == 0 && own) {
1607 			if (set_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV)
1608 			    == -1)
1609 				logger(ifp->ctx, LOG_ERR,
1610 				    "%s: set_if_nd6_flag: "
1611 				    "ND6_IFF_OVERRIDE_RTADV: %m",
1612 				    ifp->name);
1613 			else
1614 				override = 1;
1615 		}
1616 #endif
1617 
1618 #ifdef ND6_IFF_ACCEPT_RTADV
1619 		ra = get_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV);
1620 		if (ra == -1)
1621 			logger(ifp->ctx, LOG_ERR,
1622 			    "%s: get_if_nd6_flag: ND6_IFF_ACCEPT_RTADV: %m",
1623 			    ifp->name);
1624 		else if (ra != 0 && own) {
1625 			logger(ifp->ctx, LOG_DEBUG,
1626 			    "%s: disabling Kernel IPv6 RA support",
1627 			    ifp->name);
1628 			if (del_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV)
1629 			    == -1)
1630 				logger(ifp->ctx, LOG_ERR,
1631 				    "%s: del_if_nd6_flag: "
1632 				    "ND6_IFF_ACCEPT_RTADV: %m",
1633 				    ifp->name);
1634 			else
1635 				ra = 0;
1636 		} else if (ra == 0 && !own)
1637 			logger(ifp->ctx, LOG_WARNING,
1638 			    "%s: IPv6 kernel autoconf disabled", ifp->name);
1639 #ifdef ND6_IFF_OVERRIDE_RTADV
1640 		if (override == 0 && ra)
1641 			return ctx->ra_global;
1642 #endif
1643 		return ra;
1644 #else
1645 		return ctx->ra_global;
1646 #endif
1647 	}
1648 
1649 #ifdef IPV6CTL_ACCEPT_RTADV
1650 	ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
1651 	if (ra == -1)
1652 		/* The sysctl probably doesn't exist, but this isn't an
1653 		 * error as such so just log it and continue */
1654 		logger(ifp->ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
1655 		    "IPV6CTL_ACCEPT_RTADV: %m");
1656 	else if (ra != 0 && own) {
1657 		logger(ifp->ctx, LOG_DEBUG, "disabling Kernel IPv6 RA support");
1658 		if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) {
1659 			logger(ifp->ctx, LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
1660 			return ra;
1661 		}
1662 		ra = 0;
1663 #else
1664 	ra = 0;
1665 	if (own) {
1666 #endif
1667 		/* Flush the kernel knowledge of advertised routers
1668 		 * and prefixes so the kernel does not expire prefixes
1669 		 * and default routes we are trying to own. */
1670 		if (if_raflush(s) == -1)
1671 			logger(ctx, LOG_WARNING, "if_raflush: %m");
1672 	}
1673 
1674 	ctx->ra_global = ra;
1675 	return ra;
1676 }
1677 
1678 int
1679 if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
1680 {
1681 	int s, r;
1682 
1683 	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
1684 		return -1;
1685 	r = _if_checkipv6(s, ctx, ifp, own);
1686 	close(s);
1687 	return r;
1688 }
1689 #endif
1690