• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <asm/types.h> /* Needed for 2.4 kernels */
29 
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <sys/param.h>
34 
35 #include <linux/if_addr.h>
36 #include <linux/if_link.h>
37 #include <linux/if_packet.h>
38 #include <linux/filter.h>
39 #include <linux/netlink.h>
40 #include <linux/rtnetlink.h>
41 
42 #include <arpa/inet.h>
43 #include <net/if.h>
44 #include <netinet/if_ether.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/in.h>
47 #include <net/route.h>
48 
49 /* Support older kernels */
50 #ifndef IFLA_WIRELESS
51 # define IFLA_WIRELESS (IFLA_MASTER + 1)
52 #endif
53 
54 /* Linux has these in an enum and there is just no way to work
55  * out of they exist at compile time. Silly silly silly. */
56 #define IFLA_AF_SPEC			26
57 #define IFLA_INET6_ADDR_GEN_MODE	8
58 #define IN6_ADDR_GEN_MODE_NONE		1
59 
60 /* For some reason, glibc doesn't include newer flags from linux/if.h
61  * However, we cannot include linux/if.h directly as it conflicts
62  * with the glibc version. D'oh! */
63 #ifndef IFF_LOWER_UP
64 #define IFF_LOWER_UP	0x10000		/* driver signals L1 up		*/
65 #endif
66 
67 #include <errno.h>
68 #include <fcntl.h>
69 #include <ctype.h>
70 #include <stddef.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <time.h>
75 #include <unistd.h>
76 
77 #include "config.h"
78 #include "common.h"
79 #include "dev.h"
80 #include "dhcp.h"
81 #include "if.h"
82 #include "ipv4.h"
83 #include "ipv6.h"
84 #include "ipv6nd.h"
85 
86 #ifdef HAVE_NL80211_H
87 #include <linux/genetlink.h>
88 #include <linux/nl80211.h>
89 #endif
90 int if_getssid_wext(const char *ifname, uint8_t *ssid);
91 
92 #define bpf_insn		sock_filter
93 #define BPF_SKIPTYPE
94 #define BPF_ETHCOOK		-ETH_HLEN
95 #define BPF_WHOLEPACKET	0x0fffffff /* work around buggy LPF filters */
96 
97 #include "bpf-filter.h"
98 
99 /* Broadcast address for IPoIB */
100 static const uint8_t ipv4_bcast_addr[] = {
101 	0x00, 0xff, 0xff, 0xff,
102 	0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
103 	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
104 };
105 
106 #define PROC_INET6	"/proc/net/if_inet6"
107 #define PROC_PROMOTE	"/proc/sys/net/ipv4/conf/%s/promote_secondaries"
108 #define SYS_LAYER2	"/sys/class/net/%s/device/layer2"
109 
110 static const char *mproc =
111 #if defined(__alpha__)
112 	"system type"
113 #elif defined(__arm__)
114 	"Hardware"
115 #elif defined(__avr32__)
116 	"cpu family"
117 #elif defined(__bfin__)
118 	"BOARD Name"
119 #elif defined(__cris__)
120 	"cpu model"
121 #elif defined(__frv__)
122 	"System"
123 #elif defined(__i386__) || defined(__x86_64__)
124 	"vendor_id"
125 #elif defined(__ia64__)
126 	"vendor"
127 #elif defined(__hppa__)
128 	"model"
129 #elif defined(__m68k__)
130 	"MMU"
131 #elif defined(__mips__)
132 	"system type"
133 #elif defined(__powerpc__) || defined(__powerpc64__)
134 	"machine"
135 #elif defined(__s390__) || defined(__s390x__)
136 	"Manufacturer"
137 #elif defined(__sh__)
138 	"machine"
139 #elif defined(sparc) || defined(__sparc__)
140 	"cpu"
141 #elif defined(__vax__)
142 	"cpu"
143 #else
144 	NULL
145 #endif
146 	;
147 
148 int
if_machinearch(char * str,size_t len)149 if_machinearch(char *str, size_t len)
150 {
151 	FILE *fp;
152 	char buf[256];
153 
154 	if (mproc == NULL) {
155 		errno = EINVAL;
156 		return -1;
157 	}
158 
159 	fp = fopen("/proc/cpuinfo", "r");
160 	if (fp == NULL)
161 		return -1;
162 
163 	while (fscanf(fp, "%255s : ", buf) != EOF) {
164 		if (strncmp(buf, mproc, strlen(mproc)) == 0 &&
165 		    fscanf(fp, "%255s", buf) == 1)
166 		{
167 		        fclose(fp);
168 			return snprintf(str, len, ":%s", buf);
169 		}
170 	}
171 	fclose(fp);
172 	errno = ESRCH;
173 	return -1;
174 }
175 
176 static int
check_proc_int(const char * path)177 check_proc_int(const char *path)
178 {
179 	FILE *fp;
180 	int i;
181 
182 	fp = fopen(path, "r");
183 	if (fp == NULL)
184 		return -1;
185 	if (fscanf(fp, "%d", &i) != 1)
186 		i = -1;
187 	fclose(fp);
188 	return i;
189 }
190 
191 static ssize_t
write_path(const char * path,const char * val)192 write_path(const char *path, const char *val)
193 {
194 	FILE *fp;
195 	ssize_t r;
196 
197 	fp = fopen(path, "w");
198 	if (fp == NULL)
199 		return -1;
200 	r = fprintf(fp, "%s\n", val);
201 	fclose(fp);
202 	return r;
203 }
204 
205 int
if_init(struct interface * ifp)206 if_init(struct interface *ifp)
207 {
208 	char path[sizeof(PROC_PROMOTE) + IF_NAMESIZE];
209 	int n;
210 
211 	/* We enable promote_secondaries so that we can do this
212 	 * add 192.168.1.2/24
213 	 * add 192.168.1.3/24
214 	 * del 192.168.1.2/24
215 	 * and the subnet mask moves onto 192.168.1.3/24
216 	 * This matches the behaviour of BSD which makes coding dhcpcd
217 	 * a little easier as there's just one behaviour. */
218 	snprintf(path, sizeof(path), PROC_PROMOTE, ifp->name);
219 	n = check_proc_int(path);
220 	if (n == -1)
221 		return errno == ENOENT ? 0 : -1;
222 	if (n == 1)
223 		return 0;
224 	return write_path(path, "1") == -1 ? -1 : 0;
225 }
226 
227 int
if_conf(struct interface * ifp)228 if_conf(struct interface *ifp)
229 {
230 	char path[sizeof(SYS_LAYER2) + IF_NAMESIZE];
231 	int n;
232 
233 	/* Some qeth setups require the use of the broadcast flag. */
234 	snprintf(path, sizeof(path), SYS_LAYER2, ifp->name);
235 	n = check_proc_int(path);
236 	if (n == -1)
237 		return errno == ENOENT ? 0 : -1;
238 	if (n == 0)
239 		ifp->options->options |= DHCPCD_BROADCAST;
240 	return 0;
241 }
242 
243 /* XXX work out Virtal Interface Masters */
244 int
if_vimaster(__unused const char * ifname)245 if_vimaster(__unused const char *ifname)
246 {
247 
248 	return 0;
249 }
250 
251 static int
_open_link_socket(struct sockaddr_nl * nl,int flags,int protocol)252 _open_link_socket(struct sockaddr_nl *nl, int flags, int protocol)
253 {
254 	int fd;
255 
256 #ifdef SOCK_CLOEXEC
257 	if (flags)
258 		flags = SOCK_CLOEXEC;
259 	fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
260 	if (fd == -1)
261 		return -1;
262 #else
263 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
264 	if (fd == -1)
265 		return -1;
266 	if (flags &&
267 	    (flags = fcntl(fd, F_GETFD, 0)) == -1 ||
268 	    fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
269 	{
270 		close(fd);
271 	        return -1;
272 	}
273 #endif
274 	nl->nl_family = AF_NETLINK;
275 	if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) {
276 		close(fd);
277 		return -1;
278 	}
279 	return fd;
280 }
281 
282 int
if_openlinksocket(void)283 if_openlinksocket(void)
284 {
285 	struct sockaddr_nl snl;
286 
287 	memset(&snl, 0, sizeof(snl));
288 	snl.nl_groups = RTMGRP_LINK;
289 
290 #ifdef INET
291 	snl.nl_groups |= RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
292 #endif
293 #ifdef INET6
294 	snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH;
295 #endif
296 
297 	return _open_link_socket(&snl, 1, NETLINK_ROUTE);
298 }
299 
300 static int
err_netlink(struct nlmsghdr * nlm)301 err_netlink(struct nlmsghdr *nlm)
302 {
303 	struct nlmsgerr *err;
304 	size_t len;
305 
306 	if (nlm->nlmsg_type != NLMSG_ERROR)
307 		return 0;
308 	len = nlm->nlmsg_len - sizeof(*nlm);
309 	if (len < sizeof(*err)) {
310 		errno = EBADMSG;
311 		return -1;
312 	}
313 	err = (struct nlmsgerr *)NLMSG_DATA(nlm);
314 	if (err->error == 0)
315 		return (int)len;
316 	errno = -err->error;
317 	return -1;
318 }
319 
320 static int
get_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,int fd,int flags,int (* callback)(struct dhcpcd_ctx *,struct interface *,struct nlmsghdr *))321 get_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int fd, int flags,
322     int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
323 {
324 	char *buf = NULL, *nbuf;
325 	ssize_t bytes;
326 	size_t buflen;
327 	struct nlmsghdr *nlm;
328 	struct sockaddr_nl nladdr;
329 	socklen_t nladdr_len;
330 	int r;
331 
332 	buflen = 0;
333 	r = -1;
334 	for (;;) {
335 		bytes = recv(fd, NULL, 0,
336 		    flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC);
337 		if (bytes == -1)
338 			goto eexit;
339 		if ((size_t)bytes == buflen) {
340 			/* Support kernels older than 2.6.22 */
341 			if (bytes == 0)
342 				bytes = 512;
343 			else
344 				bytes *= 2;
345 		}
346 		if (buflen < (size_t)bytes) {
347 			/* Alloc 1 more so we work with older kernels */
348 			buflen = (size_t)bytes + 1;
349 			nbuf = realloc(buf, buflen);
350 			if (nbuf == NULL)
351 				goto eexit;
352 			buf = nbuf;
353 		}
354 		nladdr_len = sizeof(nladdr);
355 		bytes = recvfrom(fd, buf, buflen, flags,
356 		    (struct sockaddr *)&nladdr, &nladdr_len);
357 		if (bytes == -1 || bytes == 0)
358 			goto eexit;
359 
360 		/* Check sender */
361 		if (nladdr_len != sizeof(nladdr)) {
362 			errno = EINVAL;
363 			goto eexit;
364 		}
365 		/* Ignore message if it is not from kernel */
366 		if (nladdr.nl_pid != 0) {
367 			r = 0;
368 			continue;
369 		}
370 
371 		for (nlm = (struct nlmsghdr *)(void *)buf;
372 		     nlm && NLMSG_OK(nlm, (size_t)bytes);
373 		     nlm = NLMSG_NEXT(nlm, bytes))
374 		{
375 			r = err_netlink(nlm);
376 			if (r == -1)
377 				goto eexit;
378 			if (r)
379 				continue;
380 			if (callback) {
381 				r = callback(ctx, ifp, nlm);
382 				if (r != 0)
383 					goto eexit;
384 			}
385 		}
386 	}
387 
388 eexit:
389 	free(buf);
390 	return r;
391 }
392 
393 #ifdef INET
394 static int
if_copyrt(struct dhcpcd_ctx * ctx,struct rt * rt,struct nlmsghdr * nlm)395 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
396 {
397 	size_t len;
398 	struct rtmsg *rtm;
399 	struct rtattr *rta;
400 	struct in_addr prefsrc;
401 
402 	len = nlm->nlmsg_len - sizeof(*nlm);
403 	if (len < sizeof(*rtm)) {
404 		errno = EBADMSG;
405 		return -1;
406 	}
407 	rtm = (struct rtmsg *)NLMSG_DATA(nlm);
408 	if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET)
409 		return -1;
410 
411 	memset(rt, 0, sizeof(*rt));
412 	if (rtm->rtm_type == RTN_UNREACHABLE)
413 		rt->flags = RTF_REJECT;
414 	if (rtm->rtm_scope == RT_SCOPE_HOST)
415 		rt->flags |= RTF_HOST;
416 
417 	prefsrc.s_addr = INADDR_ANY;
418 	rta = (struct rtattr *)RTM_RTA(rtm);
419 	len = RTM_PAYLOAD(nlm);
420 	while (RTA_OK(rta, len)) {
421 		switch (rta->rta_type) {
422 		case RTA_DST:
423 			memcpy(&rt->dest.s_addr, RTA_DATA(rta),
424 			    sizeof(rt->dest.s_addr));
425 			break;
426 		case RTA_GATEWAY:
427 			memcpy(&rt->gate.s_addr, RTA_DATA(rta),
428 			    sizeof(rt->gate.s_addr));
429 			break;
430 		case RTA_PREFSRC:
431 			memcpy(&prefsrc.s_addr, RTA_DATA(rta),
432 			    sizeof(prefsrc.s_addr));
433 			break;
434 		case RTA_OIF:
435 			rt->iface = if_findindex(ctx->ifaces,
436 			    *(unsigned int *)RTA_DATA(rta));
437 			break;
438 		case RTA_PRIORITY:
439 			rt->metric = *(unsigned int *)RTA_DATA(rta);
440 			break;
441 		}
442 		rta = RTA_NEXT(rta, len);
443 	}
444 
445 	inet_cidrtoaddr(rtm->rtm_dst_len, &rt->net);
446 	if (rt->iface == NULL && prefsrc.s_addr != INADDR_ANY) {
447 		struct ipv4_addr *ap;
448 
449 		/* For some reason the default route comes back with the
450 		 * loopback interface in RTA_OIF? Lets find it by
451 		 * preferred source address */
452 		if ((ap = ipv4_findaddr(ctx, &prefsrc)))
453 			rt->iface = ap->iface;
454 	}
455 	return 0;
456 }
457 #endif
458 
459 #ifdef INET6
460 static int
if_copyrt6(struct dhcpcd_ctx * ctx,struct rt6 * rt,struct nlmsghdr * nlm)461 if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct nlmsghdr *nlm)
462 {
463 	size_t len;
464 	struct rtmsg *rtm;
465 	struct rtattr *rta;
466 
467 	len = nlm->nlmsg_len - sizeof(*nlm);
468 	if (len < sizeof(*rtm)) {
469 		errno = EBADMSG;
470 		return -1;
471 	}
472 	rtm = (struct rtmsg *)NLMSG_DATA(nlm);
473 	if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET6)
474 		return -1;
475 
476 	memset(rt, 0, sizeof(*rt));
477 	if (rtm->rtm_type == RTN_UNREACHABLE)
478 		rt->flags = RTF_REJECT;
479 	if (rtm->rtm_scope == RT_SCOPE_HOST)
480 		rt->flags |= RTF_HOST;
481 	ipv6_mask(&rt->net, rtm->rtm_dst_len);
482 
483 	rta = (struct rtattr *)RTM_RTA(rtm);
484 	len = RTM_PAYLOAD(nlm);
485 	while (RTA_OK(rta, len)) {
486 		switch (rta->rta_type) {
487 		case RTA_DST:
488 			memcpy(&rt->dest.s6_addr, RTA_DATA(rta),
489 			    sizeof(rt->dest.s6_addr));
490 			break;
491 		case RTA_GATEWAY:
492 			memcpy(&rt->gate.s6_addr, RTA_DATA(rta),
493 			    sizeof(rt->gate.s6_addr));
494 			break;
495 		case RTA_OIF:
496 			rt->iface = if_findindex(ctx->ifaces,
497 			    *(unsigned int *)RTA_DATA(rta));
498 			break;
499 		case RTA_PRIORITY:
500 			rt->metric = *(unsigned int *)RTA_DATA(rta);
501 			break;
502 		}
503 		rta = RTA_NEXT(rta, len);
504 	}
505 
506 	return 0;
507 }
508 #endif
509 
510 /* Work out the maximum pid size */
511 static inline long long
get_max_pid_t()512 get_max_pid_t()
513 {
514 
515 	if (sizeof(pid_t) == sizeof(short))		return SHRT_MAX;
516 	if (sizeof(pid_t) == sizeof(int))		return INT_MAX;
517 	if (sizeof(pid_t) == sizeof(long))		return LONG_MAX;
518 	if (sizeof(pid_t) == sizeof(long long))		return LLONG_MAX;
519 	abort();
520 }
521 
522 static int
link_route(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)523 link_route(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
524     struct nlmsghdr *nlm)
525 {
526 	size_t len;
527 	struct rtmsg *rtm;
528 	int cmd;
529 #ifdef INET
530 	struct rt rt;
531 #endif
532 #ifdef INET6
533 	struct rt6 rt6;
534 #endif
535 	switch (nlm->nlmsg_type) {
536 	case RTM_NEWROUTE:
537 		cmd = RTM_ADD;
538 		break;
539 	case RTM_DELROUTE:
540 		cmd = RTM_DELETE;
541 		break;
542 	default:
543 		return 0;
544 	}
545 
546 	len = nlm->nlmsg_len - sizeof(*nlm);
547 	if (len < sizeof(*rtm)) {
548 		errno = EBADMSG;
549 		return -1;
550 	}
551 
552 	/* Ignore messages generated by us.
553 	 * For some reason we get messages generated by us
554 	 * with a very large value in nlmsg_pid that seems to be
555 	 * sequentially changing. Is there a better test for this? */
556 	if (nlm->nlmsg_pid > get_max_pid_t())
557 		return 1;
558 
559 	rtm = NLMSG_DATA(nlm);
560 	switch (rtm->rtm_family) {
561 #ifdef INET
562 	case AF_INET:
563 		if (if_copyrt(ctx, &rt, nlm) == 0)
564 			ipv4_handlert(ctx, cmd, &rt);
565 		break;
566 #endif
567 #ifdef INET6
568 	case AF_INET6:
569 		if (if_copyrt6(ctx, &rt6, nlm) == 0)
570 			ipv6_handlert(ctx, cmd, &rt6);
571 		break;
572 #endif
573 	}
574 
575 	return 0;
576 }
577 
578 static int
link_addr(struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)579 link_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm)
580 {
581 	size_t len;
582 	struct rtattr *rta;
583 	struct ifaddrmsg *ifa;
584 #ifdef INET
585 	struct in_addr addr, net, dest;
586 #endif
587 #ifdef INET6
588 	struct in6_addr addr6;
589 #endif
590 
591 	if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR)
592 		return 0;
593 
594 	len = nlm->nlmsg_len - sizeof(*nlm);
595 	if (len < sizeof(*ifa)) {
596 		errno = EBADMSG;
597 		return -1;
598 	}
599 	ifa = NLMSG_DATA(nlm);
600 	if ((ifp = if_findindex(ctx->ifaces, ifa->ifa_index)) == NULL) {
601 		/* We don't know about the interface the address is for
602 		 * so it's not really an error */
603 		return 1;
604 	}
605 	rta = (struct rtattr *)IFA_RTA(ifa);
606 	len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
607 	switch (ifa->ifa_family) {
608 #ifdef INET
609 	case AF_INET:
610 		addr.s_addr = dest.s_addr = INADDR_ANY;
611 		dest.s_addr = INADDR_ANY;
612 		inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
613 		while (RTA_OK(rta, len)) {
614 			switch (rta->rta_type) {
615 			case IFA_ADDRESS:
616 				if (ifp->flags & IFF_POINTOPOINT) {
617 					memcpy(&dest.s_addr, RTA_DATA(rta),
618 					       sizeof(addr.s_addr));
619 				}
620 				break;
621 			case IFA_LOCAL:
622 				memcpy(&addr.s_addr, RTA_DATA(rta),
623 				       sizeof(addr.s_addr));
624 				break;
625 			}
626 			rta = RTA_NEXT(rta, len);
627 		}
628 		ipv4_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
629 		    &addr, &net, &dest, ifa->ifa_flags);
630 		break;
631 #endif
632 #ifdef INET6
633 	case AF_INET6:
634 		memset(&addr6, 0, sizeof(addr6));
635 		while (RTA_OK(rta, len)) {
636 			switch (rta->rta_type) {
637 			case IFA_ADDRESS:
638 				memcpy(&addr6.s6_addr, RTA_DATA(rta),
639 				       sizeof(addr6.s6_addr));
640 				break;
641 			}
642 			rta = RTA_NEXT(rta, len);
643 		}
644 		ipv6_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
645 		    &addr6, ifa->ifa_prefixlen, ifa->ifa_flags);
646 		break;
647 #endif
648 	}
649 	return 0;
650 }
651 
652 static uint8_t
l2addr_len(unsigned short if_type)653 l2addr_len(unsigned short if_type)
654 {
655 
656 	switch (if_type) {
657 	case ARPHRD_ETHER: /* FALLTHROUGH */
658 	case ARPHRD_IEEE802: /*FALLTHROUGH */
659 	case ARPHRD_IEEE80211:
660 		return 6;
661 	case ARPHRD_IEEE1394:
662 		return 8;
663 	case ARPHRD_INFINIBAND:
664 		return 20;
665 	}
666 
667 	/* Impossible */
668 	return 0;
669 }
670 
671 static int
handle_rename(struct dhcpcd_ctx * ctx,unsigned int ifindex,const char * ifname)672 handle_rename(struct dhcpcd_ctx *ctx, unsigned int ifindex, const char *ifname)
673 {
674 	struct interface *ifp;
675 
676 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
677 		if (ifp->index == ifindex && strcmp(ifp->name, ifname)) {
678 			dhcpcd_handleinterface(ctx, -1, ifp->name);
679 			/* Let dev announce the interface for renaming */
680 			if (!dev_listening(ctx))
681 				dhcpcd_handleinterface(ctx, 1, ifname);
682 			return 1;
683 		}
684 	}
685 	return 0;
686 }
687 
688 #ifdef INET6
689 static int
link_neigh(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)690 link_neigh(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
691     struct nlmsghdr *nlm)
692 {
693 	struct ndmsg *r;
694 	struct rtattr *rta;
695 	size_t len;
696 	struct in6_addr addr6;
697 	int flags;
698 
699 	if (nlm->nlmsg_type != RTM_NEWNEIGH && nlm->nlmsg_type != RTM_DELNEIGH)
700 		return 0;
701 	if (nlm->nlmsg_len < sizeof(*r))
702 		return -1;
703 
704 	r = NLMSG_DATA(nlm);
705 	rta = (struct rtattr *)RTM_RTA(r);
706 	len = RTM_PAYLOAD(nlm);
707         if (r->ndm_family == AF_INET6) {
708 		flags = 0;
709 		if (r->ndm_flags & NTF_ROUTER)
710 			flags |= IPV6ND_ROUTER;
711 		if (nlm->nlmsg_type == RTM_NEWNEIGH &&
712 		    r->ndm_state &
713 		    (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE |
714 		     NUD_PERMANENT))
715 		        flags |= IPV6ND_REACHABLE;
716 		memset(&addr6, 0, sizeof(addr6));
717 		while (RTA_OK(rta, len)) {
718 			switch (rta->rta_type) {
719 			case NDA_DST:
720 				memcpy(&addr6.s6_addr, RTA_DATA(rta),
721 				       sizeof(addr6.s6_addr));
722 				break;
723 			}
724 			rta = RTA_NEXT(rta, len);
725 		}
726 		ipv6nd_neighbour(ctx, &addr6, flags);
727 	}
728 
729 	return 0;
730 }
731 #endif
732 
733 static int
link_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)734 link_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
735     struct nlmsghdr *nlm)
736 {
737 	int r;
738 	size_t len;
739 	struct rtattr *rta, *hwaddr;
740 	struct ifinfomsg *ifi;
741 	char ifn[IF_NAMESIZE + 1];
742 
743 	r = link_route(ctx, ifp, nlm);
744 	if (r != 0)
745 		return r;
746 	r = link_addr(ctx, ifp, nlm);
747 	if (r != 0)
748 		return r;
749 #ifdef INET6
750 	r = link_neigh(ctx, ifp, nlm);
751 	if (r != 0)
752 		return r;
753 #endif
754 
755 	if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
756 		return 0;
757 	len = nlm->nlmsg_len - sizeof(*nlm);
758 	if ((size_t)len < sizeof(*ifi)) {
759 		errno = EBADMSG;
760 		return -1;
761 	}
762 	ifi = NLMSG_DATA(nlm);
763 	if (ifi->ifi_flags & IFF_LOOPBACK)
764 		return 0;
765 	rta = (struct rtattr *)(void *)((char *)ifi +NLMSG_ALIGN(sizeof(*ifi)));
766 	len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
767 	*ifn = '\0';
768 	hwaddr = NULL;
769 
770 	while (RTA_OK(rta, len)) {
771 		switch (rta->rta_type) {
772 		case IFLA_WIRELESS:
773 			/* Ignore wireless messages */
774 			if (nlm->nlmsg_type == RTM_NEWLINK &&
775 			    ifi->ifi_change == 0)
776 				return 0;
777 			break;
778 		case IFLA_IFNAME:
779 			strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
780 			break;
781 		case IFLA_ADDRESS:
782 			hwaddr = rta;
783 			break;
784 		}
785 		rta = RTA_NEXT(rta, len);
786 	}
787 
788 	if (nlm->nlmsg_type == RTM_DELLINK) {
789 		dhcpcd_handleinterface(ctx, -1, ifn);
790 		return 0;
791 	}
792 
793 	/* Virtual interfaces may not get a valid hardware address
794 	 * at this point.
795 	 * To trigger a valid hardware address pickup we need to pretend
796 	 * that that don't exist until they have one. */
797 	if (ifi->ifi_flags & IFF_MASTER && !hwaddr) {
798 		dhcpcd_handleinterface(ctx, -1, ifn);
799 		return 0;
800 	}
801 
802 	/* Check for interface name change */
803 	if (handle_rename(ctx, (unsigned int)ifi->ifi_index, ifn))
804 		return 0;
805 
806 	/* Check for a new interface */
807 	if ((ifp = if_find(ctx->ifaces, ifn)) == NULL) {
808 		/* If are listening to a dev manager, let that announce
809 		 * the interface rather than the kernel. */
810 		if (dev_listening(ctx) < 1)
811 			dhcpcd_handleinterface(ctx, 1, ifn);
812 		return 0;
813 	}
814 
815 	/* Re-read hardware address and friends */
816 	if (!(ifi->ifi_flags & IFF_UP) && hwaddr) {
817 		uint8_t l;
818 
819 		l = l2addr_len(ifi->ifi_type);
820 		if (hwaddr->rta_len == RTA_LENGTH(l))
821 			dhcpcd_handlehwaddr(ctx, ifn, RTA_DATA(hwaddr), l);
822 	}
823 
824 	dhcpcd_handlecarrier(ctx,
825 	    ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN,
826 	    ifi->ifi_flags, ifn);
827 	return 0;
828 }
829 
830 int
if_managelink(struct dhcpcd_ctx * ctx)831 if_managelink(struct dhcpcd_ctx *ctx)
832 {
833 
834 	return get_netlink(ctx, NULL,
835 	    ctx->link_fd, MSG_DONTWAIT, &link_netlink);
836 }
837 
838 static int
send_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,int protocol,struct nlmsghdr * hdr,int (* callback)(struct dhcpcd_ctx *,struct interface *,struct nlmsghdr *))839 send_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
840     int protocol, struct nlmsghdr *hdr,
841     int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
842 {
843 	int s, r;
844 	struct sockaddr_nl snl;
845 	struct iovec iov;
846 	struct msghdr msg;
847 	static unsigned int seq;
848 
849 	memset(&snl, 0, sizeof(snl));
850 	if ((s = _open_link_socket(&snl, 0, protocol)) == -1)
851 		return -1;
852 	memset(&iov, 0, sizeof(iov));
853 	iov.iov_base = hdr;
854 	iov.iov_len = hdr->nlmsg_len;
855 	memset(&msg, 0, sizeof(msg));
856 	msg.msg_name = &snl;
857 	msg.msg_namelen = sizeof(snl);
858 	msg.msg_iov = &iov;
859 	msg.msg_iovlen = 1;
860 	/* Request a reply */
861 	hdr->nlmsg_flags |= NLM_F_ACK;
862 	hdr->nlmsg_seq = ++seq;
863 
864 	if (sendmsg(s, &msg, 0) != -1)
865 		r = get_netlink(ctx, ifp, s, 0, callback);
866 	else
867 		r = -1;
868 	close(s);
869 	return r;
870 }
871 
872 #define NLMSG_TAIL(nmsg)						\
873 	((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len)))
874 
875 static int
add_attr_l(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,const void * data,unsigned short alen)876 add_attr_l(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
877     const void *data, unsigned short alen)
878 {
879 	unsigned short len = (unsigned short)RTA_LENGTH(alen);
880 	struct rtattr *rta;
881 
882 	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
883 		errno = ENOBUFS;
884 		return -1;
885 	}
886 
887 	rta = NLMSG_TAIL(n);
888 	rta->rta_type = type;
889 	rta->rta_len = len;
890 	if (alen)
891 		memcpy(RTA_DATA(rta), data, alen);
892 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
893 
894 	return 0;
895 }
896 
897 static int
add_attr_32(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint32_t data)898 add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
899     uint32_t data)
900 {
901 	unsigned short len = RTA_LENGTH(sizeof(data));
902 	struct rtattr *rta;
903 
904 	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
905 		errno = ENOBUFS;
906 		return -1;
907 	}
908 
909 	rta = NLMSG_TAIL(n);
910 	rta->rta_type = type;
911 	rta->rta_len = len;
912 	memcpy(RTA_DATA(rta), &data, sizeof(data));
913 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
914 
915 	return 0;
916 }
917 
918 #ifdef HAVE_NL80211_H
919 static struct nlattr *
nla_next(struct nlattr * nla,size_t * rem)920 nla_next(struct nlattr *nla, size_t *rem)
921 {
922 
923 	*rem -= NLA_ALIGN(nla->nla_len);
924 	return (struct nlattr *)(void *)((char *)nla + NLA_ALIGN(nla->nla_len));
925 }
926 
927 #define NLA_TYPE(nla) ((nla)->nla_type & NLA_TYPE_MASK)
928 #define NLA_LEN(nla) (unsigned int)((nla)->nla_len - NLA_HDRLEN)
929 #define NLA_OK(nla, rem) \
930 	((rem) >= sizeof(struct nlattr) && \
931 	(nla)->nla_len >= sizeof(struct nlattr) && \
932 	(nla)->nla_len <= rem)
933 #define NLA_DATA(nla) ((char *)(nla) + NLA_HDRLEN)
934 #define NLA_FOR_EACH_ATTR(pos, head, len, rem) \
935 	for (pos = head, rem = len; NLA_OK(pos, rem); pos = nla_next(pos, &(rem)))
936 
937 struct nlmg
938 {
939 	struct nlmsghdr hdr;
940 	struct genlmsghdr ghdr;
941 	char buffer[64];
942 };
943 
944 static int
nla_put_32(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint32_t data)945 nla_put_32(struct nlmsghdr *n, unsigned short maxlen,
946     unsigned short type, uint32_t data)
947 {
948 	unsigned short len;
949 	struct nlattr *nla;
950 
951 	len = NLA_ALIGN(NLA_HDRLEN + sizeof(data));
952 	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
953 		errno = ENOBUFS;
954 		return -1;
955 	}
956 
957 	nla = (struct nlattr *)NLMSG_TAIL(n);
958 	nla->nla_type = type;
959 	nla->nla_len = len;
960 	memcpy(NLA_DATA(nla), &data, sizeof(data));
961 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
962 
963 	return 0;
964 }
965 
966 static int
nla_put_string(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,const char * data)967 nla_put_string(struct nlmsghdr *n, unsigned short maxlen,
968     unsigned short type, const char *data)
969 {
970 	struct nlattr *nla;
971 	size_t len, sl;
972 
973 	sl = strlen(data) + 1;
974 	len = NLA_ALIGN(NLA_HDRLEN + sl);
975 	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
976 		errno = ENOBUFS;
977 		return -1;
978 	}
979 
980 	nla = (struct nlattr *)NLMSG_TAIL(n);
981 	nla->nla_type = type;
982 	nla->nla_len = (unsigned short)len;
983 	memcpy(NLA_DATA(nla), data, sl);
984 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + (unsigned short)len;
985 	return 0;
986 }
987 
988 static int
gnl_parse(struct nlmsghdr * nlm,struct nlattr * tb[],int maxtype)989 gnl_parse(struct nlmsghdr *nlm, struct nlattr *tb[], int maxtype)
990 {
991 	struct genlmsghdr *ghdr;
992 	struct nlattr *head, *nla;
993 	size_t len, rem;
994 	int type;
995 
996 	memset(tb, 0, sizeof(*tb) * ((unsigned int)maxtype + 1));
997 	ghdr = NLMSG_DATA(nlm);
998 	head = (struct nlattr *)(void *)((char *) ghdr + GENL_HDRLEN);
999 	len = nlm->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN;
1000 	NLA_FOR_EACH_ATTR(nla, head, len, rem) {
1001 		type = NLA_TYPE(nla);
1002 		if (type > maxtype)
1003 			continue;
1004 		tb[type] = nla;
1005 	}
1006 	return 0;
1007 }
1008 
1009 static int
_gnl_getfamily(__unused struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1010 _gnl_getfamily(__unused struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1011     struct nlmsghdr *nlm)
1012 {
1013 	struct nlattr *tb[CTRL_ATTR_FAMILY_ID + 1];
1014 	uint16_t family;
1015 
1016 	if (gnl_parse(nlm, tb, CTRL_ATTR_FAMILY_ID) == -1)
1017 		return -1;
1018 	if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
1019 		errno = ENOENT;
1020 		return -1;
1021 	}
1022 	family = *(uint16_t *)(void *)NLA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
1023 	return (int)family;
1024 }
1025 
1026 static int
gnl_getfamily(struct dhcpcd_ctx * ctx,const char * name)1027 gnl_getfamily(struct dhcpcd_ctx *ctx, const char *name)
1028 {
1029 	struct nlmg nlm;
1030 
1031 	memset(&nlm, 0, sizeof(nlm));
1032 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr));
1033 	nlm.hdr.nlmsg_type = GENL_ID_CTRL;
1034 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1035 	nlm.ghdr.cmd = CTRL_CMD_GETFAMILY;
1036 	nlm.ghdr.version = 1;
1037 	if (nla_put_string(&nlm.hdr, sizeof(nlm),
1038 	    CTRL_ATTR_FAMILY_NAME, name) == -1)
1039 		return -1;
1040 	return send_netlink(ctx, NULL, NETLINK_GENERIC, &nlm.hdr,
1041 	    &_gnl_getfamily);
1042 }
1043 
1044 static int
_if_getssid(__unused struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)1045 _if_getssid(__unused struct dhcpcd_ctx *ctx, struct interface *ifp,
1046     struct nlmsghdr *nlm)
1047 {
1048 	struct nlattr *tb[NL80211_ATTR_SSID + 1];
1049 
1050 	if (gnl_parse(nlm, tb, NL80211_ATTR_SSID) == -1)
1051 		return -1;
1052 
1053 	if (tb[NL80211_ATTR_SSID] == NULL) {
1054 		/* If the SSID is not found then it means that
1055 		 * we're not associated to an AP. */
1056 		ifp->ssid_len = 0;
1057 		goto out;
1058 	}
1059 
1060 	ifp->ssid_len = NLA_LEN(tb[NL80211_ATTR_SSID]);
1061 	if (ifp->ssid_len > sizeof(ifp->ssid)) {
1062 		errno = ENOBUFS;
1063 		ifp->ssid_len = 0;
1064 		return -1;
1065 	}
1066 	memcpy(ifp->ssid, NLA_DATA(tb[NL80211_ATTR_SSID]), ifp->ssid_len);
1067 
1068 out:
1069 	ifp->ssid[ifp->ssid_len] = '\0';
1070 	return (int)ifp->ssid_len;
1071 }
1072 
1073 static int
if_getssid_nl80211(struct interface * ifp)1074 if_getssid_nl80211(struct interface *ifp)
1075 {
1076 	int family;
1077 	struct nlmg nlm;
1078 
1079 	errno = 0;
1080 	family = gnl_getfamily(ifp->ctx, "nl80211");
1081 	if (family == -1)
1082 		return -1;
1083 	memset(&nlm, 0, sizeof(nlm));
1084 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr));
1085 	nlm.hdr.nlmsg_type = (unsigned short)family;
1086 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1087 	nlm.ghdr.cmd = NL80211_CMD_GET_INTERFACE;
1088 	nla_put_32(&nlm.hdr, sizeof(nlm), NL80211_ATTR_IFINDEX, ifp->index);
1089 
1090 	return send_netlink(ifp->ctx, ifp,
1091 	    NETLINK_GENERIC, &nlm.hdr, &_if_getssid);
1092 }
1093 #endif
1094 
1095 int
if_getssid(struct interface * ifp)1096 if_getssid(struct interface *ifp)
1097 {
1098 	int r;
1099 
1100 	r = if_getssid_wext(ifp->name, ifp->ssid);
1101 	if (r != -1)
1102 		ifp->ssid_len = (unsigned int)r;
1103 #ifdef HAVE_NL80211_H
1104 	else if (r == -1)
1105 		r = if_getssid_nl80211(ifp);
1106 #endif
1107 	return r;
1108 }
1109 
1110 struct nlma
1111 {
1112 	struct nlmsghdr hdr;
1113 	struct ifaddrmsg ifa;
1114 	char buffer[64];
1115 };
1116 
1117 struct nlmr
1118 {
1119 	struct nlmsghdr hdr;
1120 	struct rtmsg rt;
1121 	char buffer[256];
1122 };
1123 
1124 #ifdef INET
1125 const char *if_pfname = "Packet Socket";
1126 
1127 int
if_openrawsocket(struct interface * ifp,uint16_t protocol)1128 if_openrawsocket(struct interface *ifp, uint16_t protocol)
1129 {
1130 	int s;
1131 	union sockunion {
1132 		struct sockaddr sa;
1133 		struct sockaddr_ll sll;
1134 		struct sockaddr_storage ss;
1135 	} su;
1136 	struct sock_fprog pf;
1137 #ifdef PACKET_AUXDATA
1138 	int n;
1139 #endif
1140 
1141 #ifdef SOCK_CLOEXEC
1142 	if ((s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1143 	    htons(protocol))) == -1)
1144 		return -1;
1145 #else
1146 	int flags;
1147 
1148 	if ((s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1)
1149 		return -1;
1150 	if ((flags = fcntl(s, F_GETFD, 0)) == -1 ||
1151 	    fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1)
1152 	{
1153 		close(s);
1154 	        return -1;
1155 	}
1156 	if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
1157 	    fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
1158 	{
1159 		close(s);
1160 	        return -1;
1161 	}
1162 #endif
1163 	/* Install the DHCP filter */
1164 	memset(&pf, 0, sizeof(pf));
1165 	if (protocol == ETHERTYPE_ARP) {
1166 		pf.filter = UNCONST(arp_bpf_filter);
1167 		pf.len = arp_bpf_filter_len;
1168 	} else {
1169 		pf.filter = UNCONST(dhcp_bpf_filter);
1170 		pf.len = dhcp_bpf_filter_len;
1171 	}
1172 	if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0)
1173 		goto eexit;
1174 #ifdef PACKET_AUXDATA
1175 	n = 1;
1176 	if (setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &n, sizeof(n)) != 0) {
1177 		if (errno != ENOPROTOOPT)
1178 			goto eexit;
1179 	}
1180 #endif
1181 
1182 	memset(&su, 0, sizeof(su));
1183 	su.sll.sll_family = PF_PACKET;
1184 	su.sll.sll_protocol = htons(protocol);
1185 	su.sll.sll_ifindex = (int)ifp->index;
1186 	if (bind(s, &su.sa, sizeof(su.sll)) == -1)
1187 		goto eexit;
1188 	return s;
1189 
1190 eexit:
1191 	close(s);
1192 	return -1;
1193 }
1194 
1195 ssize_t
if_sendrawpacket(const struct interface * ifp,uint16_t protocol,const void * data,size_t len,const uint8_t * dest_hw_addr)1196 if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
1197     const void *data, size_t len, const uint8_t *dest_hw_addr)
1198 {
1199 	const struct dhcp_state *state;
1200 	union sockunion {
1201 		struct sockaddr sa;
1202 		struct sockaddr_ll sll;
1203 		struct sockaddr_storage ss;
1204 	} su;
1205 	int fd;
1206 
1207 	memset(&su, 0, sizeof(su));
1208 	su.sll.sll_family = AF_PACKET;
1209 	su.sll.sll_protocol = htons(protocol);
1210 	su.sll.sll_ifindex = (int)ifp->index;
1211 	su.sll.sll_hatype = htons(ifp->family);
1212 	su.sll.sll_halen = (unsigned char)ifp->hwlen;
1213 	if (ifp->family == ARPHRD_INFINIBAND)
1214 		memcpy(&su.sll.sll_addr,
1215 		    &ipv4_bcast_addr, sizeof(ipv4_bcast_addr));
1216 	else {
1217 		if (dest_hw_addr)
1218 			memcpy(&su.sll.sll_addr, dest_hw_addr, ifp->hwlen);
1219 		else
1220 			memset(&su.sll.sll_addr, 0xff, ifp->hwlen);
1221 	}
1222 	state = D_CSTATE(ifp);
1223 	if (protocol == ETHERTYPE_ARP)
1224 		fd = state->arp_fd;
1225 	else
1226 		fd = state->raw_fd;
1227 
1228 	return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll));
1229 }
1230 
1231 ssize_t
if_readrawpacket(struct interface * ifp,uint16_t protocol,void * data,size_t len,int * flags)1232 if_readrawpacket(struct interface *ifp, uint16_t protocol,
1233     void *data, size_t len, int *flags)
1234 {
1235 	struct iovec iov = {
1236 		.iov_base = data,
1237 		.iov_len = len,
1238 	};
1239 	struct msghdr msg = {
1240 		.msg_iov = &iov,
1241 		.msg_iovlen = 1,
1242 	};
1243 	struct dhcp_state *state;
1244 #ifdef PACKET_AUXDATA
1245 	unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1246 	struct cmsghdr *cmsg;
1247 	struct tpacket_auxdata *aux;
1248 #endif
1249 
1250 	ssize_t bytes;
1251 	int fd = -1;
1252 
1253 #ifdef PACKET_AUXDATA
1254 	msg.msg_control = cmsgbuf;
1255 	msg.msg_controllen = sizeof(cmsgbuf);
1256 #endif
1257 
1258 	state = D_STATE(ifp);
1259 	if (protocol == ETHERTYPE_ARP)
1260 		fd = state->arp_fd;
1261 	else
1262 		fd = state->raw_fd;
1263 	bytes = recvmsg(fd, &msg, 0);
1264 	if (bytes == -1)
1265 		return -1;
1266 	*flags = RAW_EOF; /* We only ever read one packet */
1267 	if (bytes) {
1268 #ifdef PACKET_AUXDATA
1269 		for (cmsg = CMSG_FIRSTHDR(&msg);
1270 		     cmsg;
1271 		     cmsg = CMSG_NXTHDR(&msg, cmsg))
1272 		{
1273 			if (cmsg->cmsg_level == SOL_PACKET &&
1274 			    cmsg->cmsg_type == PACKET_AUXDATA) {
1275 				aux = (void *)CMSG_DATA(cmsg);
1276 				if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
1277 					*flags |= RAW_PARTIALCSUM;
1278 			}
1279 		}
1280 #endif
1281 	}
1282 	return bytes;
1283 }
1284 
1285 int
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)1286 if_address(const struct interface *iface,
1287     const struct in_addr *address, const struct in_addr *netmask,
1288     const struct in_addr *broadcast, int action)
1289 {
1290 	struct nlma nlm;
1291 	int retval = 0;
1292 
1293 	memset(&nlm, 0, sizeof(nlm));
1294 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1295 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1296 	if (action >= 0) {
1297 		nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
1298 		nlm.hdr.nlmsg_type = RTM_NEWADDR;
1299 	} else
1300 		nlm.hdr.nlmsg_type = RTM_DELADDR;
1301 	nlm.ifa.ifa_index = iface->index;
1302 	nlm.ifa.ifa_family = AF_INET;
1303 	nlm.ifa.ifa_prefixlen = inet_ntocidr(*netmask);
1304 	/* This creates the aliased interface */
1305 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
1306 	    iface->alias, (unsigned short)(strlen(iface->alias) + 1));
1307 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
1308 	    &address->s_addr, sizeof(address->s_addr));
1309 	if (action >= 0 && broadcast)
1310 		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
1311 		    &broadcast->s_addr, sizeof(broadcast->s_addr));
1312 
1313 	if (send_netlink(iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1314 		retval = -1;
1315 	return retval;
1316 }
1317 
1318 int
if_route(unsigned char cmd,const struct rt * rt)1319 if_route(unsigned char cmd, const struct rt *rt)
1320 {
1321 	struct nlmr nlm;
1322 	int retval = 0;
1323 	struct dhcp_state *state;
1324 
1325 	memset(&nlm, 0, sizeof(nlm));
1326 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1327 	switch (cmd) {
1328 	case RTM_CHANGE:
1329 		nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1330 		nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE;
1331 		break;
1332 	case RTM_ADD:
1333 		nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1334 		nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
1335 		break;
1336 	case RTM_DELETE:
1337 		nlm.hdr.nlmsg_type = RTM_DELROUTE;
1338 		break;
1339 	}
1340 	nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1341 	nlm.rt.rtm_family = AF_INET;
1342 	nlm.rt.rtm_table = RT_TABLE_MAIN;
1343 
1344 	state = D_STATE(rt->iface);
1345 	if (cmd == RTM_DELETE)
1346 		nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
1347 	else {
1348 		/* We only change route metrics for kernel routes */
1349 		if (rt->dest.s_addr ==
1350 		    (state->addr.s_addr & state->net.s_addr) &&
1351 		    rt->net.s_addr == state->net.s_addr)
1352 			nlm.rt.rtm_protocol = RTPROT_KERNEL;
1353 		else
1354 			nlm.rt.rtm_protocol = RTPROT_BOOT;
1355 		if (rt->iface->flags & IFF_LOOPBACK)
1356 			nlm.rt.rtm_scope = RT_SCOPE_HOST;
1357 		else if (rt->gate.s_addr == INADDR_ANY ||
1358 		    (rt->gate.s_addr == rt->dest.s_addr &&
1359 			rt->net.s_addr == INADDR_BROADCAST))
1360 			nlm.rt.rtm_scope = RT_SCOPE_LINK;
1361 		else
1362 			nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
1363 		nlm.rt.rtm_type = RTN_UNICAST;
1364 	}
1365 
1366 	nlm.rt.rtm_dst_len = inet_ntocidr(rt->net);
1367 	add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST,
1368 	    &rt->dest.s_addr, sizeof(rt->dest.s_addr));
1369 	if (nlm.rt.rtm_protocol == RTPROT_KERNEL) {
1370 		add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC,
1371 		    &state->addr.s_addr, sizeof(state->addr.s_addr));
1372 	}
1373 	/* If a host route then don't add the gateway */
1374 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
1375 	    rt->net.s_addr != INADDR_BROADCAST)
1376 		add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
1377 		    &rt->gate.s_addr, sizeof(rt->gate.s_addr));
1378 
1379 	if (rt->gate.s_addr != htonl(INADDR_LOOPBACK))
1380 		add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
1381 	if (rt->metric)
1382 		add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
1383 
1384 	if (send_netlink(rt->iface->ctx, NULL,
1385 	    NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1386 		retval = -1;
1387 	return retval;
1388 }
1389 
1390 static int
_if_initrt(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1391 _if_initrt(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1392     struct nlmsghdr *nlm)
1393 {
1394 	struct rt rt;
1395 
1396 	if (if_copyrt(ctx, &rt, nlm) == 0)
1397 		ipv4_handlert(ctx, RTM_ADD, &rt);
1398 	return 0;
1399 }
1400 
1401 int
if_initrt(struct interface * ifp)1402 if_initrt(struct interface *ifp)
1403 {
1404 	struct nlmr nlm;
1405 
1406 	ipv4_freerts(ifp->ctx->ipv4_kroutes);
1407 
1408 	memset(&nlm, 0, sizeof(nlm));
1409 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1410 	nlm.hdr.nlmsg_type = RTM_GETROUTE;
1411 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
1412 	nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1413 	nlm.rt.rtm_family = AF_INET;
1414 	nlm.rt.rtm_table = RT_TABLE_MAIN;
1415 	add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index);
1416 
1417 	return send_netlink(ifp->ctx, ifp,
1418 	    NETLINK_ROUTE, &nlm.hdr, &_if_initrt);
1419 }
1420 
1421 int
if_addrflags(__unused const struct in_addr * addr,__unused const struct interface * ifp)1422 if_addrflags(__unused const struct in_addr *addr,
1423     __unused const struct interface *ifp)
1424 {
1425 
1426 	/* Linux has no support for IPv4 address flags */
1427 	return 0;
1428 }
1429 #endif
1430 
1431 #ifdef INET6
1432 int
if_address6(const struct ipv6_addr * ap,int action)1433 if_address6(const struct ipv6_addr *ap, int action)
1434 {
1435 	struct nlma nlm;
1436 	struct ifa_cacheinfo cinfo;
1437 	int retval = 0;
1438 /* IFA_FLAGS is not a define, but is was added at the same time
1439  * IFA_F_NOPREFIXROUTE was do use that. */
1440 #if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
1441 	uint32_t flags = 0;
1442 #endif
1443 
1444 	memset(&nlm, 0, sizeof(nlm));
1445 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1446 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1447 	if (action >= 0) {
1448 		nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
1449 		nlm.hdr.nlmsg_type = RTM_NEWADDR;
1450 	} else
1451 		nlm.hdr.nlmsg_type = RTM_DELADDR;
1452 	nlm.ifa.ifa_index = ap->iface->index;
1453 	nlm.ifa.ifa_family = AF_INET6;
1454 	if (ap->addr_flags & IFA_F_TEMPORARY) {
1455 #ifdef IFA_F_NOPREFIXROUTE
1456 		flags |= IFA_F_TEMPORARY;
1457 #else
1458 		nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
1459 #endif
1460 	}
1461 #ifdef IFA_F_MANAGETEMPADDR
1462 	else if (ap->flags & IPV6_AF_AUTOCONF &&
1463 	    ip6_use_tempaddr(ap->iface->name))
1464 		flags |= IFA_F_MANAGETEMPADDR;
1465 #endif
1466 
1467 	/* Add as /128 if no IFA_F_NOPREFIXROUTE ? */
1468 	nlm.ifa.ifa_prefixlen = ap->prefix_len;
1469 	/* This creates the aliased interface */
1470 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
1471 	    ap->iface->alias, (unsigned short)(strlen(ap->iface->alias) + 1));
1472 	add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
1473 	    &ap->addr.s6_addr, sizeof(ap->addr.s6_addr));
1474 
1475 	if (action >= 0) {
1476 		memset(&cinfo, 0, sizeof(cinfo));
1477 		cinfo.ifa_prefered = ap->prefix_pltime;
1478 		cinfo.ifa_valid = ap->prefix_vltime;
1479 		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_CACHEINFO,
1480 		    &cinfo, sizeof(cinfo));
1481 	}
1482 
1483 #ifdef IFA_F_NOPREFIXROUTE
1484 	if (!IN6_IS_ADDR_LINKLOCAL(&ap->addr))
1485 		flags |= IFA_F_NOPREFIXROUTE;
1486 #endif
1487 #if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
1488 	if (flags)
1489 		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
1490 #endif
1491 
1492 	if (send_netlink(ap->iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr,
1493 	    NULL) == -1)
1494 		retval = -1;
1495 	return retval;
1496 }
1497 
1498 static int
rta_add_attr_32(struct rtattr * rta,unsigned short maxlen,unsigned short type,uint32_t data)1499 rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
1500     unsigned short type, uint32_t data)
1501 {
1502 	unsigned short len = RTA_LENGTH(sizeof(data));
1503 	struct rtattr *subrta;
1504 
1505 	if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
1506 		errno = ENOBUFS;
1507 		return -1;
1508 	}
1509 
1510 	subrta = (struct rtattr*)(void *)
1511 	    (((char*)rta) + RTA_ALIGN(rta->rta_len));
1512 	subrta->rta_type = type;
1513 	subrta->rta_len = len;
1514 	memcpy(RTA_DATA(subrta), &data, sizeof(data));
1515 	rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
1516 	return 0;
1517 }
1518 
1519 int
if_route6(unsigned char cmd,const struct rt6 * rt)1520 if_route6(unsigned char cmd, const struct rt6 *rt)
1521 {
1522 	struct nlmr nlm;
1523 	int retval = 0;
1524 
1525 	memset(&nlm, 0, sizeof(nlm));
1526 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1527 	switch (cmd) {
1528 	case RTM_CHANGE:
1529 		nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1530 		nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE;
1531 		break;
1532 	case RTM_ADD:
1533 		nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1534 		nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
1535 		break;
1536 	case RTM_DELETE:
1537 		nlm.hdr.nlmsg_type = RTM_DELROUTE;
1538 		break;
1539 	}
1540 	nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1541 	nlm.rt.rtm_family = AF_INET6;
1542 	nlm.rt.rtm_table = RT_TABLE_MAIN;
1543 
1544 	if (cmd == RTM_DELETE)
1545 		nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
1546 	else {
1547 		/* None interface subnet routes are static. */
1548 		if (rt->iface->flags & IFF_LOOPBACK)
1549 			nlm.rt.rtm_scope = RT_SCOPE_HOST;
1550 		else if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
1551 			nlm.rt.rtm_protocol = RTPROT_KERNEL;
1552 			nlm.rt.rtm_scope = RT_SCOPE_LINK;
1553 		} else
1554 			nlm.rt.rtm_protocol = RTPROT_BOOT;
1555 		if (rt->flags & RTF_REJECT)
1556 			nlm.rt.rtm_type = RTN_UNREACHABLE;
1557 		else
1558 			nlm.rt.rtm_type = RTN_UNICAST;
1559 	}
1560 
1561 	nlm.rt.rtm_dst_len = ipv6_prefixlen(&rt->net);
1562 	add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST,
1563 	    &rt->dest.s6_addr, sizeof(rt->dest.s6_addr));
1564 
1565 	if (cmd == RTM_ADD && !IN6_IS_ADDR_UNSPECIFIED(&rt->gate))
1566 		add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
1567 		    &rt->gate.s6_addr, sizeof(rt->gate.s6_addr));
1568 
1569 	if (!(rt->flags & RTF_REJECT)) {
1570 		add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
1571 		if (rt->metric)
1572 			add_attr_32(&nlm.hdr, sizeof(nlm),
1573 			    RTA_PRIORITY, rt->metric);
1574 	}
1575 	if (cmd == RTM_ADD && rt->mtu) {
1576 		char metricsbuf[32];
1577 		struct rtattr *metrics = (void *)metricsbuf;
1578 
1579 		metrics->rta_type = RTA_METRICS;
1580 		metrics->rta_len = RTA_LENGTH(0);
1581 		rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
1582 		add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
1583 		    RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics));
1584 	}
1585 
1586 	if (send_netlink(rt->iface->ctx, NULL,
1587 	    NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1588 		retval = -1;
1589 	return retval;
1590 }
1591 
1592 static int
_if_initrt6(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1593 _if_initrt6(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1594     struct nlmsghdr *nlm)
1595 {
1596 	struct rt6 rt;
1597 
1598 	if (if_copyrt6(ctx, &rt, nlm) == 0)
1599 		ipv6_handlert(ctx, RTM_ADD, &rt);
1600 	return 0;
1601 }
1602 
1603 int
if_initrt6(struct interface * ifp)1604 if_initrt6(struct interface *ifp)
1605 {
1606 	struct nlmr nlm;
1607 
1608 	ipv6_freerts(&ifp->ctx->ipv6->kroutes);
1609 
1610 	memset(&nlm, 0, sizeof(nlm));
1611 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1612 	nlm.hdr.nlmsg_type = RTM_GETROUTE;
1613 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
1614 	nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1615 	nlm.rt.rtm_family = AF_INET6;
1616 	nlm.rt.rtm_table = RT_TABLE_MAIN;
1617 	add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index);
1618 
1619 	return send_netlink(ifp->ctx, ifp,
1620 	    NETLINK_ROUTE, &nlm.hdr, &_if_initrt6);
1621 }
1622 
1623 int
if_addrflags6(const struct in6_addr * addr,const struct interface * ifp)1624 if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
1625 {
1626 	FILE *fp;
1627 	char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1];
1628 	unsigned int ifindex;
1629 	int prefix, scope, flags, i;
1630 
1631 	fp = fopen(PROC_INET6, "r");
1632 	if (fp == NULL)
1633 		return -1;
1634 
1635 	p = ifaddress;
1636 	for (i = 0; i < (int)sizeof(addr->s6_addr); i++) {
1637 		p += snprintf(p, 3, "%.2x", addr->s6_addr[i]);
1638 	}
1639 	*p = '\0';
1640 
1641 	while (fscanf(fp, "%32[a-f0-9] %x %x %x %x %"TOSTRING(IF_NAMESIZE)"s\n",
1642 	    address, &ifindex, &prefix, &scope, &flags, name) == 6)
1643 	{
1644 		if (strlen(address) != 32) {
1645 			fclose(fp);
1646 			errno = ENOTSUP;
1647 			return -1;
1648 		}
1649 		if (strcmp(name, ifp->name) == 0 &&
1650 		    strcmp(ifaddress, address) == 0)
1651 		{
1652 			fclose(fp);
1653 			return flags;
1654 		}
1655 	}
1656 
1657 	fclose(fp);
1658 	errno = ESRCH;
1659 	return -1;
1660 }
1661 
1662 int
if_getlifetime6(__unused struct ipv6_addr * ia)1663 if_getlifetime6(__unused struct ipv6_addr *ia)
1664 {
1665 
1666 	/* God knows how to work out address lifetimes on Linux */
1667 	errno = ENOTSUP;
1668 	return -1;
1669 }
1670 
1671 struct nlml
1672 {
1673 	struct nlmsghdr hdr;
1674 	struct ifinfomsg i;
1675 	char buffer[32];
1676 };
1677 
1678 static int
add_attr_8(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint8_t data)1679 add_attr_8(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
1680     uint8_t data)
1681 {
1682 
1683 	return add_attr_l(n, maxlen, type, &data, sizeof(data));
1684 }
1685 
1686 static struct rtattr *
add_attr_nest(struct nlmsghdr * n,unsigned short maxlen,unsigned short type)1687 add_attr_nest(struct nlmsghdr *n, unsigned short maxlen, unsigned short type)
1688 {
1689 	struct rtattr *nest;
1690 
1691 	nest = NLMSG_TAIL(n);
1692 	add_attr_l(n, maxlen, type, NULL, 0);
1693 	return nest;
1694 }
1695 
1696 static void
add_attr_nest_end(struct nlmsghdr * n,struct rtattr * nest)1697 add_attr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
1698 {
1699 
1700 	nest->rta_len = (unsigned short)((char *)NLMSG_TAIL(n) - (char *)nest);
1701 }
1702 
1703 static int
if_disable_autolinklocal(struct dhcpcd_ctx * ctx,int ifindex)1704 if_disable_autolinklocal(struct dhcpcd_ctx *ctx, int ifindex)
1705 {
1706 	struct nlml nlm;
1707 	struct rtattr *afs, *afs6;
1708 
1709 	memset(&nlm, 0, sizeof(nlm));
1710 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1711 	nlm.hdr.nlmsg_type = RTM_NEWLINK;
1712 	nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1713 	nlm.i.ifi_family = AF_INET6;
1714 	nlm.i.ifi_index = ifindex;
1715 	afs = add_attr_nest(&nlm.hdr, sizeof(nlm), IFLA_AF_SPEC);
1716 	afs6 = add_attr_nest(&nlm.hdr, sizeof(nlm), AF_INET6);
1717 	add_attr_8(&nlm.hdr, sizeof(nlm), IFLA_INET6_ADDR_GEN_MODE,
1718 	    IN6_ADDR_GEN_MODE_NONE);
1719 	add_attr_nest_end(&nlm.hdr, afs6);
1720 	add_attr_nest_end(&nlm.hdr, afs);
1721 
1722 	return send_netlink(ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL);
1723 }
1724 
1725 static const char *prefix = "/proc/sys/net/ipv6/conf";
1726 
1727 int
if_checkipv6(struct dhcpcd_ctx * ctx,const struct interface * ifp,int own)1728 if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
1729 {
1730 	const char *ifname;
1731 	int ra;
1732 	char path[256];
1733 
1734 	if (ifp == NULL)
1735 		ifname = "all";
1736 	else if (own) {
1737 		if (if_disable_autolinklocal(ctx, (int)ifp->index) == -1)
1738 			logger(ctx, LOG_DEBUG,
1739 			    "%s: if_disable_autolinklocal: %m", ifp->name);
1740 	}
1741 	if (ifp)
1742 		ifname = ifp->name;
1743 
1744 	snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifname);
1745 	ra = check_proc_int(path);
1746 	if (ra != 1) {
1747 		if (!own)
1748 			logger(ctx, LOG_WARNING,
1749 			    "%s: IPv6 kernel autoconf disabled", ifname);
1750 	} else if (ra != -1 && own) {
1751 		if (write_path(path, "0") == -1) {
1752 			logger(ctx, LOG_ERR, "write_path: %s: %m", path);
1753 			return -1;
1754 		}
1755 	}
1756 
1757 	snprintf(path, sizeof(path), "%s/%s/accept_ra", prefix, ifname);
1758 	ra = check_proc_int(path);
1759 	if (ra == -1)
1760 		/* The sysctl probably doesn't exist, but this isn't an
1761 		 * error as such so just log it and continue */
1762 		logger(ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
1763 		    "%s: %m", path);
1764 	else if (ra != 0 && own) {
1765 		logger(ctx, LOG_DEBUG, "%s: disabling kernel IPv6 RA support",
1766 		    ifname);
1767 		if (write_path(path, "0") == -1) {
1768 			logger(ctx, LOG_ERR, "write_path: %s: %m", path);
1769 			return ra;
1770 		}
1771 		return 0;
1772 	}
1773 
1774 	return ra;
1775 }
1776 
1777 #ifdef IPV6_MANAGETEMPADDR
1778 int
ip6_use_tempaddr(const char * ifname)1779 ip6_use_tempaddr(const char *ifname)
1780 {
1781 	char path[256];
1782 	int val;
1783 
1784 	if (ifname == NULL)
1785 		ifname = "all";
1786 	snprintf(path, sizeof(path), "%s/%s/use_tempaddr", prefix, ifname);
1787 	val = check_proc_int(path);
1788 	return val == -1 ? 0 : val;
1789 }
1790 
1791 int
ip6_temp_preferred_lifetime(const char * ifname)1792 ip6_temp_preferred_lifetime(const char *ifname)
1793 {
1794 	char path[256];
1795 	int val;
1796 
1797 	if (ifname == NULL)
1798 		ifname = "all";
1799 	snprintf(path, sizeof(path), "%s/%s/temp_prefered_lft", prefix,
1800 	    ifname);
1801 	val = check_proc_int(path);
1802 	return val < 0 ? TEMP_PREFERRED_LIFETIME : val;
1803 }
1804 
1805 int
ip6_temp_valid_lifetime(const char * ifname)1806 ip6_temp_valid_lifetime(const char *ifname)
1807 {
1808 	char path[256];
1809 	int val;
1810 
1811 	if (ifname == NULL)
1812 		ifname = "all";
1813 	snprintf(path, sizeof(path), "%s/%s/temp_valid_lft", prefix, ifname);
1814 	val = check_proc_int(path);
1815 	return val < 0 ? TEMP_VALID_LIFETIME : val;
1816 }
1817 #endif /* IPV6_MANAGETEMPADDR */
1818 #endif /* INET6 */
1819