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