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 * $FreeBSD$
35 */
36
37#include <sys/param.h>
38#include <sys/capsicum.h>
39#include <sys/queue.h>
40#include <sys/socket.h>
41#include <sys/stat.h>
42#include <sys/uio.h>
43#include <sys/wait.h>
44
45#include <net/if.h>
46#include <net/route.h>
47#include <net/if_dl.h>
48
49#define	__BSD_VISIBLE	1	/* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */
50#include <netinet/in.h>
51#undef 	__BSD_VISIBLE
52#include <netinet/ip6.h>
53#include <netinet6/ip6_var.h>
54#include <netinet/icmp6.h>
55
56#include <arpa/inet.h>
57
58#include <capsicum_helpers.h>
59#include <netdb.h>
60#include <time.h>
61#include <fcntl.h>
62#include <unistd.h>
63#include <stdio.h>
64#include <time.h>
65#include <err.h>
66#include <errno.h>
67#include <string.h>
68#include <stdlib.h>
69#include <syslog.h>
70#include "rtsold.h"
71
72static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST];
73struct ifinfo_head_t ifinfo_head = TAILQ_HEAD_INITIALIZER(ifinfo_head);
74
75static void call_script(const char *const *, struct script_msg_head_t *);
76static size_t dname_labeldec(char *, size_t, const char *);
77static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
78static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *,
79    struct script_msg_head_t *, struct script_msg_head_t *);
80static char *make_rsid(const char *, const char *, struct rainfo *);
81
82#define	_ARGS_OTHER	otherconf_script, ifi->ifname
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 "O bit."
295	 * If the value of OtherConfigFlag changes from FALSE to TRUE, the
296	 * host should invoke the stateful autoconfiguration protocol,
297	 * requesting information.
298	 * [RFC 2462 Section 5.5.3]
299	 */
300	if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) &&
301	    !ifi->otherconfig) {
302		warnmsg(LOG_DEBUG, __func__,
303		    "OtherConfigFlag on %s is turned on", ifi->ifname);
304		ifi->otherconfig = 1;
305		CALL_SCRIPT(OTHER, NULL);
306	}
307	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
308	newent_rai = 0;
309	rai = find_rainfo(ifi, &from);
310	if (rai == NULL) {
311		ELM_MALLOC(rai, exit(1));
312		rai->rai_ifinfo = ifi;
313		TAILQ_INIT(&rai->rai_ra_opt);
314		rai->rai_saddr.sin6_family = AF_INET6;
315		rai->rai_saddr.sin6_len = sizeof(rai->rai_saddr);
316		memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
317		    sizeof(rai->rai_saddr.sin6_addr));
318		newent_rai = 1;
319	}
320
321#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)x + \
322				(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
323	/* Process RA options. */
324	warnmsg(LOG_DEBUG, __func__, "Processing RA");
325	raoptp = (char *)icp + sizeof(struct nd_router_advert);
326	while (raoptp < (char *)icp + msglen) {
327		ndo = (struct nd_opt_hdr *)raoptp;
328		warnmsg(LOG_DEBUG, __func__, "ndo = %p", raoptp);
329		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_type = %d",
330		    ndo->nd_opt_type);
331		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
332		    ndo->nd_opt_len);
333
334		switch (ndo->nd_opt_type) {
335		case ND_OPT_RDNSS:
336			rdnss = (struct nd_opt_rdnss *)raoptp;
337
338			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
339			if (rdnss->nd_opt_rdnss_len < 3) {
340				warnmsg(LOG_INFO, __func__,
341		    			"too short RDNSS option"
342					"in RA from %s was ignored.",
343					inet_ntop(AF_INET6, &from.sin6_addr,
344					    ntopbuf, sizeof(ntopbuf)));
345				break;
346			}
347
348			addr = (struct in6_addr *)(void *)(raoptp + sizeof(*rdnss));
349			while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
350				if (inet_ntop(AF_INET6, addr, ntopbuf,
351					sizeof(ntopbuf)) == NULL) {
352					warnmsg(LOG_INFO, __func__,
353		    			    "an invalid address in RDNSS option"
354					    " in RA from %s was ignored.",
355					    inet_ntop(AF_INET6, &from.sin6_addr,
356						ntopbuf, sizeof(ntopbuf)));
357					addr++;
358					continue;
359				}
360				if (IN6_IS_ADDR_LINKLOCAL(addr))
361					/* XXX: % has to be escaped here */
362					l = snprintf(nsbuf, sizeof(nsbuf),
363					    "%s%c%s", ntopbuf,
364					    SCOPE_DELIMITER,
365					    ifi->ifname);
366				else
367					l = snprintf(nsbuf, sizeof(nsbuf),
368					    "%s", ntopbuf);
369				if (l < 0 || (size_t)l >= sizeof(nsbuf)) {
370					warnmsg(LOG_ERR, __func__,
371					    "address copying error in "
372					    "RDNSS option: %d.", l);
373					addr++;
374					continue;
375				}
376				warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
377				    nsbuf);
378
379				newent_rao = 0;
380				rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
381				    strlen(nsbuf));
382				if (rao == NULL) {
383					ELM_MALLOC(rao, break);
384					rao->rao_type = ndo->nd_opt_type;
385					rao->rao_len = strlen(nsbuf);
386					rao->rao_msg = strdup(nsbuf);
387					if (rao->rao_msg == NULL) {
388						warnmsg(LOG_ERR, __func__,
389						    "strdup failed: %s",
390						    strerror(errno));
391						free(rao);
392						addr++;
393						continue;
394					}
395					newent_rao = 1;
396				}
397				/* Set expiration timer */
398				memset(&rao->rao_expire, 0,
399				    sizeof(rao->rao_expire));
400				memset(&lifetime, 0, sizeof(lifetime));
401				lifetime.tv_sec =
402				    ntohl(rdnss->nd_opt_rdnss_lifetime);
403				TS_ADD(&now, &lifetime, &rao->rao_expire);
404
405				if (newent_rao)
406					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
407					    rao, rao_next);
408				addr++;
409			}
410			break;
411		case ND_OPT_DNSSL:
412			dnssl = (struct nd_opt_dnssl *)raoptp;
413
414			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
415			if (dnssl->nd_opt_dnssl_len < 2) {
416				warnmsg(LOG_INFO, __func__,
417		    			"too short DNSSL option"
418					"in RA from %s was ignored.",
419					inet_ntop(AF_INET6, &from.sin6_addr,
420					    ntopbuf, sizeof(ntopbuf)));
421				break;
422			}
423
424			/*
425			 * Ensure NUL-termination in DNSSL in case of
426			 * malformed field.
427			 */
428			p = (char *)RA_OPT_NEXT_HDR(raoptp);
429			*(p - 1) = '\0';
430
431			p = raoptp + sizeof(*dnssl);
432			while (1 < (len = dname_labeldec(dname, sizeof(dname),
433			    p))) {
434				/* length == 1 means empty string */
435				warnmsg(LOG_DEBUG, __func__, "dname = %s",
436				    dname);
437
438				newent_rao = 0;
439				rao = find_raopt(rai, ndo->nd_opt_type, dname,
440				    strlen(dname));
441				if (rao == NULL) {
442					ELM_MALLOC(rao, break);
443					rao->rao_type = ndo->nd_opt_type;
444					rao->rao_len = strlen(dname);
445					rao->rao_msg = strdup(dname);
446					if (rao->rao_msg == NULL) {
447						warnmsg(LOG_ERR, __func__,
448						    "strdup failed: %s",
449						    strerror(errno));
450						free(rao);
451						addr++;
452						continue;
453					}
454					newent_rao = 1;
455				}
456				/* Set expiration timer */
457				memset(&rao->rao_expire, 0,
458				    sizeof(rao->rao_expire));
459				memset(&lifetime, 0, sizeof(lifetime));
460				lifetime.tv_sec =
461				    ntohl(dnssl->nd_opt_dnssl_lifetime);
462				TS_ADD(&now, &lifetime, &rao->rao_expire);
463
464				if (newent_rao)
465					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
466					    rao, rao_next);
467				p += len;
468			}
469			break;
470		default:
471			/* nothing to do for other options */
472			break;
473		}
474		raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
475	}
476	if (newent_rai)
477		TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next);
478
479	ra_opt_handler(ifi);
480	ifi->racnt++;
481
482	switch (ifi->state) {
483	case IFS_IDLE:		/* should be ignored */
484	case IFS_DELAY:		/* right? */
485		break;
486	case IFS_PROBE:
487		ifi->state = IFS_IDLE;
488		ifi->probes = 0;
489		rtsol_timer_update(ifi);
490		break;
491	}
492}
493
494static char resstr_ns_prefix[] = "nameserver ";
495static char resstr_sh_prefix[] = "search ";
496static char resstr_nl[] = "\n";
497static char resstr_sp[] = " ";
498
499int
500ra_opt_handler(struct ifinfo *ifi)
501{
502	struct ra_opt *rao;
503	struct rainfo *rai;
504	struct script_msg *smp1, *smp2, *smp3;
505	struct timespec now;
506	struct script_msg_head_t sm_rdnss_head =
507	    TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
508	struct script_msg_head_t sm_dnssl_head =
509	    TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
510
511	int dcount, dlen;
512
513	dcount = 0;
514	dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
515	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
516
517	/*
518	 * All options from multiple RAs with the same or different
519	 * source addresses on a single interface will be gathered and
520	 * handled, not overridden.  [RFC 4861 6.3.4]
521	 */
522	TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
523		TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
524			switch (rao->rao_type) {
525			case ND_OPT_RDNSS:
526				if (TS_CMP(&now, &rao->rao_expire, >)) {
527					warnmsg(LOG_INFO, __func__,
528					    "expired rdnss entry: %s",
529					    (char *)rao->rao_msg);
530					break;
531				}
532				ELM_MALLOC(smp1, continue);
533				ELM_MALLOC(smp2, goto free1);
534				ELM_MALLOC(smp3, goto free2);
535				smp1->sm_msg = resstr_ns_prefix;
536				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1,
537				    sm_next);
538				smp2->sm_msg = rao->rao_msg;
539				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2,
540				    sm_next);
541				smp3->sm_msg = resstr_nl;
542				TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3,
543				    sm_next);
544				ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED;
545				break;
546			case ND_OPT_DNSSL:
547				if (TS_CMP(&now, &rao->rao_expire, >)) {
548					warnmsg(LOG_INFO, __func__,
549					    "expired dnssl entry: %s",
550					    (char *)rao->rao_msg);
551					break;
552				}
553				dcount++;
554				/* Check resolv.conf(5) restrictions. */
555				if (dcount > 6) {
556					warnmsg(LOG_INFO, __func__,
557					    "dnssl entry exceeding maximum count (%d>6)"
558					    ": %s", dcount, (char *)rao->rao_msg);
559					break;
560				}
561				if (256 < dlen + strlen(rao->rao_msg) +
562				    strlen(resstr_sp)) {
563					warnmsg(LOG_INFO, __func__,
564					    "dnssl entry exceeding maximum length "
565					    "(>256): %s", (char *)rao->rao_msg);
566					break;
567				}
568				ELM_MALLOC(smp1, continue);
569				ELM_MALLOC(smp2, goto free1);
570				if (TAILQ_EMPTY(&sm_dnssl_head)) {
571					ELM_MALLOC(smp3, goto free2);
572					smp3->sm_msg = resstr_sh_prefix;
573					TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
574					    sm_next);
575				}
576				smp1->sm_msg = rao->rao_msg;
577				TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
578				    sm_next);
579				smp2->sm_msg = resstr_sp;
580				TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
581				    sm_next);
582				dlen += strlen(rao->rao_msg) +
583				    strlen(resstr_sp);
584				ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
585				break;
586			}
587			continue;
588free2:
589			free(smp2);
590free1:
591			free(smp1);
592		}
593		/* Call the script for each information source. */
594		if (uflag)
595			ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head,
596			    &sm_dnssl_head);
597	}
598	/* Call the script for each interface. */
599	if (!uflag)
600		ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head,
601		    &sm_dnssl_head);
602	return (0);
603}
604
605char *
606make_rsid(const char *ifname, const char *origin, struct rainfo *rai)
607{
608	char hbuf[NI_MAXHOST];
609
610	if (rai == NULL)
611		sprintf(rsid, "%s:%s", ifname, origin);
612	else {
613		if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr))
614			return (NULL);
615		if (getnameinfo((struct sockaddr *)&rai->rai_saddr,
616			rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0,
617			NI_NUMERICHOST) != 0)
618			return (NULL);
619		sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf);
620	}
621	warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid);
622	return (rsid);
623}
624
625int
626ra_opt_rdnss_dispatch(struct ifinfo *ifi, struct rainfo *rai,
627    struct script_msg_head_t *sm_rdnss_head,
628    struct script_msg_head_t *sm_dnssl_head)
629{
630	struct script_msg *smp1;
631	const char *r;
632	int error;
633
634	error = 0;
635	/* Add \n for DNSSL list. */
636	if (!TAILQ_EMPTY(sm_dnssl_head)) {
637		ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit);
638		smp1->sm_msg = resstr_nl;
639		TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next);
640	}
641	TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next);
642
643	r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, uflag ? rai : NULL);
644	if (r == NULL) {
645		warnmsg(LOG_ERR, __func__, "make_rsid() failed.  "
646		    "Script was not invoked.");
647		error = 1;
648		goto ra_opt_rdnss_freeit;
649	}
650	if (!TAILQ_EMPTY(sm_rdnss_head))
651		CALL_SCRIPT(RESADD, sm_rdnss_head);
652	else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
653	    ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
654		CALL_SCRIPT(RESDEL, NULL);
655		ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
656		ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
657	}
658
659ra_opt_rdnss_freeit:
660	/* Clear script message queue. */
661	if (!TAILQ_EMPTY(sm_rdnss_head)) {
662		while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) {
663			TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next);
664			free(smp1);
665		}
666	}
667	if (!TAILQ_EMPTY(sm_dnssl_head)) {
668		while ((smp1 = TAILQ_FIRST(sm_dnssl_head)) != NULL) {
669			TAILQ_REMOVE(sm_dnssl_head, smp1, sm_next);
670			free(smp1);
671		}
672	}
673	return (error);
674}
675
676static struct ra_opt *
677find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
678{
679	struct ra_opt *rao;
680
681	TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
682		if (rao->rao_type == type &&
683		    rao->rao_len == strlen(msg) &&
684		    memcmp(rao->rao_msg, msg, len) == 0)
685			break;
686	}
687
688	return (rao);
689}
690
691static void
692call_script(const char *const argv[], struct script_msg_head_t *sm_head)
693{
694	struct script_msg *smp;
695	ssize_t len;
696	int status, wfd;
697
698	if (argv[0] == NULL)
699		return;
700
701	wfd = cap_script_run(capscript, argv);
702	if (wfd == -1) {
703		warnmsg(LOG_ERR, __func__,
704		    "failed to run %s: %s", argv[0], strerror(errno));
705		return;
706	}
707
708	if (sm_head != NULL) {
709		TAILQ_FOREACH(smp, sm_head, sm_next) {
710			len = strlen(smp->sm_msg);
711			warnmsg(LOG_DEBUG, __func__, "write to child = %s(%zd)",
712			    smp->sm_msg, len);
713			if (write(wfd, smp->sm_msg, len) != len) {
714				warnmsg(LOG_ERR, __func__,
715				    "write to child failed: %s",
716				    strerror(errno));
717				break;
718			}
719		}
720	}
721
722	(void)close(wfd);
723
724	if (cap_script_wait(capscript, &status) != 0)
725		warnmsg(LOG_ERR, __func__, "wait(): %s", strerror(errno));
726	else
727		warnmsg(LOG_DEBUG, __func__, "script \"%s\" status %d",
728		    argv[0], status);
729}
730
731/* Decode domain name label encoding in RFC 1035 Section 3.1 */
732static size_t
733dname_labeldec(char *dst, size_t dlen, const char *src)
734{
735	size_t len;
736	const char *src_origin;
737	const char *src_last;
738	const char *dst_origin;
739
740	src_origin = src;
741	src_last = strchr(src, '\0');
742	dst_origin = dst;
743	memset(dst, '\0', dlen);
744	while (src && (len = (uint8_t)(*src++) & 0x3f) &&
745	    (src + len) <= src_last &&
746	    (dst - dst_origin < (ssize_t)dlen)) {
747		if (dst != dst_origin)
748			*dst++ = '.';
749		warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
750		memcpy(dst, src, len);
751		src += len;
752		dst += len;
753	}
754	*dst = '\0';
755
756	/*
757	 * XXX validate that domain name only contains valid characters
758	 * for two reasons: 1) correctness, 2) we do not want to pass
759	 * possible malicious, unescaped characters like `` to a script
760	 * or program that could be exploited that way.
761	 */
762
763	return (src - src_origin);
764}
765