1/*	$KAME: rtsol.c,v 1.27 2003/10/05 00:09:36 itojun Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Copyright (C) 2011 Hiroki Sato
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the project nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
36#include <sys/capsicum.h>
37#include <sys/queue.h>
38#include <sys/socket.h>
39#include <sys/stat.h>
40#include <sys/uio.h>
41#include <sys/wait.h>
42
43#include <net/if.h>
44#include <net/route.h>
45#include <net/if_dl.h>
46
47#define	__BSD_VISIBLE	1	/* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */
48#include <netinet/in.h>
49#undef 	__BSD_VISIBLE
50#include <netinet/ip6.h>
51#include <netinet6/ip6_var.h>
52#include <netinet/icmp6.h>
53
54#include <arpa/inet.h>
55
56#include <capsicum_helpers.h>
57#include <netdb.h>
58#include <time.h>
59#include <fcntl.h>
60#include <unistd.h>
61#include <stdio.h>
62#include <time.h>
63#include <err.h>
64#include <errno.h>
65#include <string.h>
66#include <stdlib.h>
67#include <syslog.h>
68#include "rtsold.h"
69
70static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST];
71struct ifinfo_head_t ifinfo_head = TAILQ_HEAD_INITIALIZER(ifinfo_head);
72
73static void call_script(const char *const *, struct script_msg_head_t *);
74static size_t dname_labeldec(char *, size_t, const char *);
75static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
76static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *,
77    struct script_msg_head_t *, struct script_msg_head_t *);
78static char *make_rsid(const char *, const char *, struct rainfo *);
79
80#define	_ARGS_MANAGED	managedconf_script, ifi->ifname, rasender
81#define	_ARGS_OTHER	otherconf_script, ifi->ifname, rasender
82#define	_ARGS_ALWAYS	alwaysconf_script, ifi->ifname, rasender
83#define	_ARGS_RESADD	resolvconf_script, "-a", rsid
84#define	_ARGS_RESDEL	resolvconf_script, "-d", rsid
85
86#define	CALL_SCRIPT(name, sm_head) do {				\
87	const char *const sarg[] = { _ARGS_##name, NULL };	\
88	call_script(sarg, sm_head);				\
89} while (0)
90
91#define	ELM_MALLOC(p, error_action) do {			\
92	p = malloc(sizeof(*p));					\
93	if (p == NULL) {					\
94		warnmsg(LOG_ERR, __func__, "malloc failed: %s", \
95		    strerror(errno));				\
96		error_action;					\
97	}							\
98	memset(p, 0, sizeof(*p));				\
99} while (0)
100
101int
102recvsockopen(void)
103{
104	struct icmp6_filter filt;
105	cap_rights_t rights;
106	int on, sock;
107
108	if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
109		warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
110		goto fail;
111	}
112
113	/* Provide info about the receiving interface. */
114	on = 1;
115	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
116	    sizeof(on)) < 0) {
117		warnmsg(LOG_ERR, __func__, "setsockopt(IPV6_RECVPKTINFO): %s",
118		    strerror(errno));
119		goto fail;
120	}
121
122	/* Include the hop limit from the received header. */
123	on = 1;
124	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
125	    sizeof(on)) < 0) {
126		warnmsg(LOG_ERR, __func__, "setsockopt(IPV6_RECVHOPLIMIT): %s",
127		    strerror(errno));
128		goto fail;
129	}
130
131	/* Filter out everything except for Router Advertisements. */
132	ICMP6_FILTER_SETBLOCKALL(&filt);
133	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
134	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
135	    sizeof(filt)) == -1) {
136		warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s",
137		    strerror(errno));
138		goto fail;
139	}
140
141	cap_rights_init(&rights, CAP_EVENT, CAP_RECV);
142	if (caph_rights_limit(sock, &rights) < 0) {
143		warnmsg(LOG_ERR, __func__, "caph_rights_limit(): %s",
144		    strerror(errno));
145		goto fail;
146	}
147
148	return (sock);
149
150fail:
151	if (sock >= 0)
152		(void)close(sock);
153	return (-1);
154}
155
156void
157rtsol_input(int sock)
158{
159	uint8_t cmsg[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
160	    CMSG_SPACE(sizeof(int))];
161	struct iovec iov;
162	struct msghdr hdr;
163	struct sockaddr_in6 from;
164	char answer[1500], ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
165	int l, ifindex = 0, *hlimp = NULL;
166	ssize_t msglen;
167	struct in6_pktinfo *pi = NULL;
168	struct ifinfo *ifi = NULL;
169	struct ra_opt *rao = NULL;
170	struct icmp6_hdr *icp;
171	struct nd_router_advert *nd_ra;
172	struct cmsghdr *cm;
173	struct rainfo *rai;
174	char *p, *raoptp;
175	struct in6_addr *addr;
176	struct nd_opt_hdr *ndo;
177	struct nd_opt_rdnss *rdnss;
178	struct nd_opt_dnssl *dnssl;
179	size_t len;
180	char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1];
181	char dname[NI_MAXHOST];
182	struct timespec lifetime, now;
183	int newent_rai, newent_rao;
184
185	memset(&hdr, 0, sizeof(hdr));
186	hdr.msg_iov = &iov;
187	hdr.msg_iovlen = 1;
188	hdr.msg_name = &from;
189	hdr.msg_namelen = sizeof(from);
190	hdr.msg_control = cmsg;
191	hdr.msg_controllen = sizeof(cmsg);
192
193	iov.iov_base = (caddr_t)answer;
194	iov.iov_len = sizeof(answer);
195
196	if ((msglen = recvmsg(sock, &hdr, 0)) < 0) {
197		warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
198		return;
199	}
200
201	/* Extract control message info. */
202	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&hdr); cm != NULL;
203	    cm = (struct cmsghdr *)CMSG_NXTHDR(&hdr, cm)) {
204		if (cm->cmsg_level == IPPROTO_IPV6 &&
205		    cm->cmsg_type == IPV6_PKTINFO &&
206		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
207			pi = (struct in6_pktinfo *)(void *)(CMSG_DATA(cm));
208			ifindex = pi->ipi6_ifindex;
209		}
210		if (cm->cmsg_level == IPPROTO_IPV6 &&
211		    cm->cmsg_type == IPV6_HOPLIMIT &&
212		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
213			hlimp = (int *)(void *)CMSG_DATA(cm);
214	}
215
216	if (ifindex == 0) {
217		warnmsg(LOG_ERR, __func__,
218		    "failed to get receiving interface");
219		return;
220	}
221	if (hlimp == NULL) {
222		warnmsg(LOG_ERR, __func__,
223		    "failed to get receiving hop limit");
224		return;
225	}
226
227	if ((size_t)msglen < sizeof(struct nd_router_advert)) {
228		warnmsg(LOG_INFO, __func__,
229		    "packet size(%zd) is too short", msglen);
230		return;
231	}
232
233	icp = (struct icmp6_hdr *)iov.iov_base;
234	if (icp->icmp6_type != ND_ROUTER_ADVERT) {
235		/*
236		 * this should not happen because we configured a filter
237		 * that only passes RAs on the receiving socket.
238		 */
239		warnmsg(LOG_ERR, __func__,
240		    "invalid icmp type(%d) from %s on %s", icp->icmp6_type,
241		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
242			sizeof(ntopbuf)),
243		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
244		return;
245	}
246
247	if (icp->icmp6_code != 0) {
248		warnmsg(LOG_INFO, __func__,
249		    "invalid icmp code(%d) from %s on %s", icp->icmp6_code,
250		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
251			sizeof(ntopbuf)),
252		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
253		return;
254	}
255
256	if (*hlimp != 255) {
257		warnmsg(LOG_INFO, __func__,
258		    "invalid RA with hop limit(%d) from %s on %s",
259		    *hlimp,
260		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
261			sizeof(ntopbuf)),
262		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
263		return;
264	}
265
266	if (pi && !IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) {
267		warnmsg(LOG_INFO, __func__,
268		    "invalid RA with non link-local source from %s on %s",
269		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
270			sizeof(ntopbuf)),
271		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
272		return;
273	}
274
275	/* xxx: more validation? */
276
277	if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) {
278		warnmsg(LOG_DEBUG, __func__,
279		    "received RA from %s on an unexpected IF(%s)",
280		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
281			sizeof(ntopbuf)),
282		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
283		return;
284	}
285
286	warnmsg(LOG_DEBUG, __func__,
287	    "received RA from %s on %s, state is %d",
288	    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, sizeof(ntopbuf)),
289	    ifi->ifname, ifi->state);
290
291	nd_ra = (struct nd_router_advert *)icp;
292
293	/*
294	 * Process the "M bit."
295	 * If the value of ManagedConfigFlag changes from FALSE to TRUE, the
296	 * host should invoke the stateful autoconfiguration protocol,
297	 * requesting information.
298	 * [RFC 4861 Section 4.2]
299	 * XXX ??? [draft-ietf-v6ops-dhcpv6-slaac-problem-07]
300	 */
301	if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_MANAGED) &&
302	    !ifi->managedconfig) {
303		const char *rasender = inet_ntop(AF_INET6, &from.sin6_addr,
304		    ntopbuf, sizeof(ntopbuf));
305		warnmsg(LOG_DEBUG, __func__,
306		    "ManagedConfigFlag on %s is turned on", ifi->ifname);
307		ifi->managedconfig = 1;
308		CALL_SCRIPT(MANAGED, NULL);
309	}
310
311	/*
312	 * Process the "O bit."
313	 * If the value of OtherConfigFlag changes from FALSE to TRUE, the
314	 * host should invoke the stateful autoconfiguration protocol,
315	 * requesting information unless the "M bit" was set as well in
316	 * which case the "O bit" is redundant.
317	 * [RFC 4861 Section 4.2]
318	 */
319	if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) &&
320	    !ifi->otherconfig) {
321		const char *rasender = inet_ntop(AF_INET6, &from.sin6_addr,
322		    ntopbuf, sizeof(ntopbuf));
323		warnmsg(LOG_DEBUG, __func__,
324		    "OtherConfigFlag on %s is turned on", ifi->ifname);
325		ifi->otherconfig = 1;
326		if (!ifi->managedconfig)
327			CALL_SCRIPT(OTHER, NULL);
328	}
329
330	/*
331	 * "Always" script.
332	 */
333	if (!ifi->alwaysconfig) {
334		const char *rasender = inet_ntop(AF_INET6, &from.sin6_addr,
335		    ntopbuf, sizeof(ntopbuf));
336		ifi->alwaysconfig = 1;
337		CALL_SCRIPT(ALWAYS, NULL);
338	}
339
340	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
341	newent_rai = 0;
342	rai = find_rainfo(ifi, &from);
343	if (rai == NULL) {
344		ELM_MALLOC(rai, exit(1));
345		rai->rai_ifinfo = ifi;
346		TAILQ_INIT(&rai->rai_ra_opt);
347		rai->rai_saddr.sin6_family = AF_INET6;
348		rai->rai_saddr.sin6_len = sizeof(rai->rai_saddr);
349		memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
350		    sizeof(rai->rai_saddr.sin6_addr));
351		newent_rai = 1;
352	}
353
354#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)(x) + \
355				(((struct nd_opt_hdr *)(x))->nd_opt_len * 8))
356	/* Process RA options. */
357	warnmsg(LOG_DEBUG, __func__, "Processing RA");
358	raoptp = (char *)icp + sizeof(struct nd_router_advert);
359	while (raoptp < (char *)icp + msglen) {
360		ndo = (struct nd_opt_hdr *)raoptp;
361		warnmsg(LOG_DEBUG, __func__, "ndo = %p", raoptp);
362		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_type = %d",
363		    ndo->nd_opt_type);
364		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
365		    ndo->nd_opt_len);
366
367		if (ndo->nd_opt_len == 0) {
368			warnmsg(LOG_INFO, __func__, "invalid option length 0.");
369			break;
370		}
371		if ((char *)RA_OPT_NEXT_HDR(raoptp) > (char *)icp + msglen) {
372			warnmsg(LOG_INFO, __func__, "option length overflow.");
373			break;
374		}
375
376		switch (ndo->nd_opt_type) {
377		case ND_OPT_RDNSS:
378			rdnss = (struct nd_opt_rdnss *)raoptp;
379
380			/*
381			 * The option header is 8 bytes long and each address
382			 * occupies 16 bytes, so the option length must be
383			 * greater than or equal to 24 bytes and an odd multiple
384			 * of 8 bytes.  See section 5.1 in RFC 6106.
385			 */
386			if (rdnss->nd_opt_rdnss_len < 3 ||
387			    rdnss->nd_opt_rdnss_len % 2 == 0) {
388				warnmsg(LOG_INFO, __func__,
389				    "too short RDNSS option in RA from %s "
390				    "was ignored.",
391				inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
392				    sizeof(ntopbuf)));
393				break;
394			}
395
396			addr = (struct in6_addr *)(void *)(raoptp + sizeof(*rdnss));
397			while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
398				if (inet_ntop(AF_INET6, addr, ntopbuf,
399					sizeof(ntopbuf)) == NULL) {
400					warnmsg(LOG_INFO, __func__,
401		    			    "an invalid address in RDNSS option"
402					    " in RA from %s was ignored.",
403					    inet_ntop(AF_INET6, &from.sin6_addr,
404						ntopbuf, sizeof(ntopbuf)));
405					addr++;
406					continue;
407				}
408				if (IN6_IS_ADDR_LINKLOCAL(addr))
409					/* XXX: % has to be escaped here */
410					l = snprintf(nsbuf, sizeof(nsbuf),
411					    "%s%c%s", ntopbuf,
412					    SCOPE_DELIMITER,
413					    ifi->ifname);
414				else
415					l = snprintf(nsbuf, sizeof(nsbuf),
416					    "%s", ntopbuf);
417				if (l < 0 || (size_t)l >= sizeof(nsbuf)) {
418					warnmsg(LOG_ERR, __func__,
419					    "address copying error in "
420					    "RDNSS option: %d.", l);
421					addr++;
422					continue;
423				}
424				warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
425				    nsbuf);
426
427				newent_rao = 0;
428				rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
429				    strlen(nsbuf));
430				if (rao == NULL) {
431					ELM_MALLOC(rao, break);
432					rao->rao_type = ndo->nd_opt_type;
433					rao->rao_len = strlen(nsbuf);
434					rao->rao_msg = strdup(nsbuf);
435					if (rao->rao_msg == NULL) {
436						warnmsg(LOG_ERR, __func__,
437						    "strdup failed: %s",
438						    strerror(errno));
439						free(rao);
440						addr++;
441						continue;
442					}
443					newent_rao = 1;
444				}
445				/* Set expiration timer */
446				memset(&rao->rao_expire, 0,
447				    sizeof(rao->rao_expire));
448				memset(&lifetime, 0, sizeof(lifetime));
449				lifetime.tv_sec =
450				    ntohl(rdnss->nd_opt_rdnss_lifetime);
451				TS_ADD(&now, &lifetime, &rao->rao_expire);
452
453				if (newent_rao)
454					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
455					    rao, rao_next);
456				addr++;
457			}
458			break;
459		case ND_OPT_DNSSL:
460			dnssl = (struct nd_opt_dnssl *)raoptp;
461
462			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
463			if (dnssl->nd_opt_dnssl_len < 2) {
464				warnmsg(LOG_INFO, __func__,
465		    			"too short DNSSL option"
466					"in RA from %s was ignored.",
467					inet_ntop(AF_INET6, &from.sin6_addr,
468					    ntopbuf, sizeof(ntopbuf)));
469				break;
470			}
471
472			/*
473			 * Ensure NUL-termination in DNSSL in case of
474			 * malformed field.
475			 */
476			p = (char *)RA_OPT_NEXT_HDR(raoptp);
477			*(p - 1) = '\0';
478
479			p = raoptp + sizeof(*dnssl);
480			while (1 < (len = dname_labeldec(dname, sizeof(dname),
481			    p))) {
482				/* length == 1 means empty string */
483				warnmsg(LOG_DEBUG, __func__, "dname = %s",
484				    dname);
485
486				newent_rao = 0;
487				rao = find_raopt(rai, ndo->nd_opt_type, dname,
488				    strlen(dname));
489				if (rao == NULL) {
490					ELM_MALLOC(rao, break);
491					rao->rao_type = ndo->nd_opt_type;
492					rao->rao_len = strlen(dname);
493					rao->rao_msg = strdup(dname);
494					if (rao->rao_msg == NULL) {
495						warnmsg(LOG_ERR, __func__,
496						    "strdup failed: %s",
497						    strerror(errno));
498						free(rao);
499						addr++;
500						continue;
501					}
502					newent_rao = 1;
503				}
504				/* Set expiration timer */
505				memset(&rao->rao_expire, 0,
506				    sizeof(rao->rao_expire));
507				memset(&lifetime, 0, sizeof(lifetime));
508				lifetime.tv_sec =
509				    ntohl(dnssl->nd_opt_dnssl_lifetime);
510				TS_ADD(&now, &lifetime, &rao->rao_expire);
511
512				if (newent_rao)
513					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
514					    rao, rao_next);
515				p += len;
516			}
517			break;
518		default:
519			/* nothing to do for other options */
520			break;
521		}
522		raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
523	}
524	if (newent_rai)
525		TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next);
526
527	ra_opt_handler(ifi);
528	ifi->racnt++;
529
530	switch (ifi->state) {
531	case IFS_IDLE:		/* should be ignored */
532	case IFS_DELAY:		/* right? */
533		break;
534	case IFS_PROBE:
535		ifi->state = IFS_IDLE;
536		ifi->probes = 0;
537		rtsol_timer_update(ifi);
538		break;
539	}
540}
541
542static char resstr_ns_prefix[] = "nameserver ";
543static char resstr_sh_prefix[] = "search ";
544static char resstr_nl[] = "\n";
545static char resstr_sp[] = " ";
546
547int
548ra_opt_handler(struct ifinfo *ifi)
549{
550	struct ra_opt *rao;
551	struct rainfo *rai;
552	struct script_msg *smp1, *smp2, *smp3;
553	struct timespec now;
554	struct script_msg_head_t sm_rdnss_head =
555	    TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
556	struct script_msg_head_t sm_dnssl_head =
557	    TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
558
559	int dcount, dlen;
560
561	dcount = 0;
562	dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
563	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
564
565	/*
566	 * All options from multiple RAs with the same or different
567	 * source addresses on a single interface will be gathered and
568	 * handled, not overridden.  [RFC 4861 6.3.4]
569	 */
570	TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
571		TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
572			switch (rao->rao_type) {
573			case ND_OPT_RDNSS:
574				if (TS_CMP(&now, &rao->rao_expire, >)) {
575					warnmsg(LOG_INFO, __func__,
576					    "expired rdnss entry: %s",
577					    (char *)rao->rao_msg);
578					break;
579				}
580				ELM_MALLOC(smp1, continue);
581				ELM_MALLOC(smp2, goto free1);
582				ELM_MALLOC(smp3, goto free2);
583				smp1->sm_msg = resstr_ns_prefix;
584				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1,
585				    sm_next);
586				smp2->sm_msg = rao->rao_msg;
587				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2,
588				    sm_next);
589				smp3->sm_msg = resstr_nl;
590				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3,
591				    sm_next);
592				ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED;
593				break;
594			case ND_OPT_DNSSL:
595				if (TS_CMP(&now, &rao->rao_expire, >)) {
596					warnmsg(LOG_INFO, __func__,
597					    "expired dnssl entry: %s",
598					    (char *)rao->rao_msg);
599					break;
600				}
601				dcount++;
602				/* Check resolv.conf(5) restrictions. */
603				if (dcount > 6) {
604					warnmsg(LOG_INFO, __func__,
605					    "dnssl entry exceeding maximum count (%d>6)"
606					    ": %s", dcount, (char *)rao->rao_msg);
607					break;
608				}
609				if (256 < dlen + strlen(rao->rao_msg) +
610				    strlen(resstr_sp)) {
611					warnmsg(LOG_INFO, __func__,
612					    "dnssl entry exceeding maximum length "
613					    "(>256): %s", (char *)rao->rao_msg);
614					break;
615				}
616				ELM_MALLOC(smp1, continue);
617				ELM_MALLOC(smp2, goto free1);
618				if (TAILQ_EMPTY(&sm_dnssl_head)) {
619					ELM_MALLOC(smp3, goto free2);
620					smp3->sm_msg = resstr_sh_prefix;
621					TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
622					    sm_next);
623				}
624				smp1->sm_msg = rao->rao_msg;
625				TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
626				    sm_next);
627				smp2->sm_msg = resstr_sp;
628				TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
629				    sm_next);
630				dlen += strlen(rao->rao_msg) +
631				    strlen(resstr_sp);
632				ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
633				break;
634			}
635			continue;
636free2:
637			free(smp2);
638free1:
639			free(smp1);
640		}
641		/* Call the script for each information source. */
642		if (uflag)
643			ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head,
644			    &sm_dnssl_head);
645	}
646	/* Call the script for each interface. */
647	if (!uflag)
648		ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head,
649		    &sm_dnssl_head);
650	return (0);
651}
652
653char *
654make_rsid(const char *ifname, const char *origin, struct rainfo *rai)
655{
656	char hbuf[NI_MAXHOST];
657
658	if (rai == NULL)
659		sprintf(rsid, "%s:%s", ifname, origin);
660	else {
661		if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr))
662			return (NULL);
663		if (getnameinfo((struct sockaddr *)&rai->rai_saddr,
664			rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0,
665			NI_NUMERICHOST) != 0)
666			return (NULL);
667		sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf);
668	}
669	warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid);
670	return (rsid);
671}
672
673int
674ra_opt_rdnss_dispatch(struct ifinfo *ifi, struct rainfo *rai,
675    struct script_msg_head_t *sm_rdnss_head,
676    struct script_msg_head_t *sm_dnssl_head)
677{
678	struct script_msg *smp1;
679	const char *r;
680	int error;
681
682	error = 0;
683	/* Add \n for DNSSL list. */
684	if (!TAILQ_EMPTY(sm_dnssl_head)) {
685		ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit);
686		smp1->sm_msg = resstr_nl;
687		TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next);
688	}
689	TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next);
690
691	r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, uflag ? rai : NULL);
692	if (r == NULL) {
693		warnmsg(LOG_ERR, __func__, "make_rsid() failed.  "
694		    "Script was not invoked.");
695		error = 1;
696		goto ra_opt_rdnss_freeit;
697	}
698	if (!TAILQ_EMPTY(sm_rdnss_head))
699		CALL_SCRIPT(RESADD, sm_rdnss_head);
700	else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
701	    ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
702		CALL_SCRIPT(RESDEL, NULL);
703		ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
704		ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
705	}
706
707ra_opt_rdnss_freeit:
708	/* Clear script message queue. */
709	if (!TAILQ_EMPTY(sm_rdnss_head)) {
710		while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) {
711			TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next);
712			free(smp1);
713		}
714	}
715	if (!TAILQ_EMPTY(sm_dnssl_head)) {
716		while ((smp1 = TAILQ_FIRST(sm_dnssl_head)) != NULL) {
717			TAILQ_REMOVE(sm_dnssl_head, smp1, sm_next);
718			free(smp1);
719		}
720	}
721	return (error);
722}
723
724static struct ra_opt *
725find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
726{
727	struct ra_opt *rao;
728
729	TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
730		if (rao->rao_type == type &&
731		    rao->rao_len == strlen(msg) &&
732		    memcmp(rao->rao_msg, msg, len) == 0)
733			break;
734	}
735
736	return (rao);
737}
738
739static void
740call_script(const char *const argv[], struct script_msg_head_t *sm_head)
741{
742	struct script_msg *smp;
743	ssize_t len;
744	int status, wfd;
745
746	if (argv[0] == NULL)
747		return;
748
749	wfd = cap_script_run(capscript, argv);
750	if (wfd == -1) {
751		warnmsg(LOG_ERR, __func__,
752		    "failed to run %s: %s", argv[0], strerror(errno));
753		return;
754	}
755
756	if (sm_head != NULL) {
757		TAILQ_FOREACH(smp, sm_head, sm_next) {
758			len = strlen(smp->sm_msg);
759			warnmsg(LOG_DEBUG, __func__, "write to child = %s(%zd)",
760			    smp->sm_msg, len);
761			if (write(wfd, smp->sm_msg, len) != len) {
762				warnmsg(LOG_ERR, __func__,
763				    "write to child failed: %s",
764				    strerror(errno));
765				break;
766			}
767		}
768	}
769
770	(void)close(wfd);
771
772	if (cap_script_wait(capscript, &status) != 0)
773		warnmsg(LOG_ERR, __func__, "wait(): %s", strerror(errno));
774	else
775		warnmsg(LOG_DEBUG, __func__, "script \"%s\" status %d",
776		    argv[0], status);
777}
778
779/* Decode domain name label encoding in RFC 1035 Section 3.1 */
780static size_t
781dname_labeldec(char *dst, size_t dlen, const char *src)
782{
783	size_t len;
784	const char *src_origin;
785	const char *src_last;
786	const char *dst_origin;
787
788	src_origin = src;
789	src_last = strchr(src, '\0');
790	dst_origin = dst;
791	memset(dst, '\0', dlen);
792	while ((len = (*src++) & 0x3f) &&
793	    src + len <= src_last &&
794	    len + (dst == dst_origin ? 0 : 1) < dlen) {
795		if (dst != dst_origin) {
796			*dst++ = '.';
797			dlen--;
798		}
799		warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
800		memcpy(dst, src, len);
801		src += len;
802		dst += len;
803		dlen -= len;
804	}
805	*dst = '\0';
806
807	/*
808	 * XXX validate that domain name only contains valid characters
809	 * for two reasons: 1) correctness, 2) we do not want to pass
810	 * possible malicious, unescaped characters like `` to a script
811	 * or program that could be exploited that way.
812	 */
813
814	return (src - src_origin);
815}
816