]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rtsold/rtsol.c
Update to Zstandard 1.3.8
[FreeBSD/FreeBSD.git] / usr.sbin / rtsold / rtsol.c
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/socket.h>
39 #include <sys/uio.h>
40 #include <sys/queue.h>
41 #include <sys/wait.h>
42 #include <sys/stat.h>
43
44 #include <net/if.h>
45 #include <net/route.h>
46 #include <net/if_dl.h>
47
48 #define __BSD_VISIBLE   1       /* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */
49 #include <netinet/in.h>
50 #undef  __BSD_VISIBLE
51 #include <netinet/ip6.h>
52 #include <netinet6/ip6_var.h>
53 #include <netinet/icmp6.h>
54
55 #include <arpa/inet.h>
56
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
70 static struct msghdr rcvmhdr;
71 static struct msghdr sndmhdr;
72 static struct iovec rcviov[2];
73 static struct iovec sndiov[2];
74 static struct sockaddr_in6 from;
75 static int rcvcmsglen;
76
77 int rssock;
78 static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST];
79 struct ifinfo_head_t ifinfo_head =
80         TAILQ_HEAD_INITIALIZER(ifinfo_head);
81
82 static const struct sockaddr_in6 sin6_allrouters = {
83         .sin6_len =     sizeof(sin6_allrouters),
84         .sin6_family =  AF_INET6,
85         .sin6_addr =    IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
86 };
87
88 static void call_script(const int, const char *const *,
89     struct script_msg_head_t *);
90 static size_t dname_labeldec(char *, size_t, const char *);
91 static int safefile(const char *);
92 static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
93 static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *,
94     struct script_msg_head_t *, struct script_msg_head_t *);
95 static char *make_rsid(const char *, const char *, struct rainfo *);
96
97 #define _ARGS_OTHER     otherconf_script, ifi->ifname
98 #define _ARGS_RESADD    resolvconf_script, "-a", rsid
99 #define _ARGS_RESDEL    resolvconf_script, "-d", rsid
100
101 #define CALL_SCRIPT(name, sm_head) do {                         \
102         const char *const sarg[] = { _ARGS_##name, NULL };      \
103         call_script(sizeof(sarg), sarg, sm_head);               \
104 } while (0)
105
106 #define ELM_MALLOC(p, error_action) 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_DEBUG, __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                                 break;
618                         case ND_OPT_DNSSL:
619                                 if (TS_CMP(&now, &rao->rao_expire, >)) {
620                                         warnmsg(LOG_INFO, __func__,
621                                             "expired dnssl entry: %s",
622                                             (char *)rao->rao_msg);
623                                         break;
624                                 }
625                                 dcount++;
626                                 /* Check resolv.conf(5) restrictions. */
627                                 if (dcount > 6) {
628                                         warnmsg(LOG_INFO, __func__,
629                                             "dnssl entry exceeding maximum count (%d>6)"
630                                             ": %s", dcount, (char *)rao->rao_msg);
631                                         break;
632                                 }
633                                 if (256 < dlen + strlen(rao->rao_msg) +
634                                     strlen(resstr_sp)) {
635                                         warnmsg(LOG_INFO, __func__,
636                                             "dnssl entry exceeding maximum length "
637                                             "(>256): %s", (char *)rao->rao_msg);
638                                         break;
639                                 }
640                                 ELM_MALLOC(smp1, continue);
641                                 ELM_MALLOC(smp2, goto free1);
642                                 if (TAILQ_EMPTY(&sm_dnssl_head)) {
643                                         ELM_MALLOC(smp3, goto free2);
644                                         smp3->sm_msg = resstr_sh_prefix;
645                                         TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
646                                             sm_next);
647                                 }
648                                 smp1->sm_msg = rao->rao_msg;
649                                 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
650                                     sm_next);
651                                 smp2->sm_msg = resstr_sp;
652                                 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
653                                     sm_next);
654                                 dlen += strlen(rao->rao_msg) +
655                                     strlen(resstr_sp);
656                                 ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
657                                 break;
658                         }
659                         continue;
660 free2:
661                         free(smp2);
662 free1:
663                         free(smp1);
664                 }
665                 /* Call the script for each information source. */
666                 if (uflag)
667                         ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head,
668                             &sm_dnssl_head);
669         }
670         /* Call the script for each interface. */
671         if (!uflag)
672                 ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head,
673                     &sm_dnssl_head);
674         return (0);
675 }
676
677 char *
678 make_rsid(const char *ifname, const char *origin, struct rainfo *rai)
679 {
680         char hbuf[NI_MAXHOST];
681         
682         if (rai == NULL)
683                 sprintf(rsid, "%s:%s", ifname, origin);
684         else {
685                 if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr))
686                         return (NULL);
687                 if (getnameinfo((struct sockaddr *)&rai->rai_saddr,
688                         rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0,
689                         NI_NUMERICHOST) != 0)
690                         return (NULL);
691                 sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf);
692         }
693         warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid);
694         return (rsid);
695 }
696
697 int
698 ra_opt_rdnss_dispatch(struct ifinfo *ifi, struct rainfo *rai,
699     struct script_msg_head_t *sm_rdnss_head,
700     struct script_msg_head_t *sm_dnssl_head)
701 {
702         struct script_msg *smp1;
703         const char *r;
704         int error;
705
706         error = 0;
707         /* Add \n for DNSSL list. */
708         if (!TAILQ_EMPTY(sm_dnssl_head)) {
709                 ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit);
710                 smp1->sm_msg = resstr_nl;
711                 TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next);
712         }
713         TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next);
714
715         r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, uflag ? rai : NULL);
716         if (r == NULL) {
717                 warnmsg(LOG_ERR, __func__, "make_rsid() failed.  "
718                     "Script was not invoked.");
719                 error = 1;
720                 goto ra_opt_rdnss_freeit;
721         }
722         if (!TAILQ_EMPTY(sm_rdnss_head))
723                 CALL_SCRIPT(RESADD, sm_rdnss_head);
724         else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
725             ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
726                 CALL_SCRIPT(RESDEL, NULL);
727                 ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
728                 ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
729         }
730
731 ra_opt_rdnss_freeit:
732         /* Clear script message queue. */
733         if (!TAILQ_EMPTY(sm_rdnss_head)) {
734                 while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) {
735                         TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next);
736                         free(smp1);
737                 }
738         }
739         if (!TAILQ_EMPTY(sm_dnssl_head)) {
740                 while ((smp1 = TAILQ_FIRST(sm_dnssl_head)) != NULL) {
741                         TAILQ_REMOVE(sm_dnssl_head, smp1, sm_next);
742                         free(smp1);
743                 }
744         }
745         return (error);
746 }
747
748 static struct ra_opt *
749 find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
750 {
751         struct ra_opt *rao;
752
753         TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
754                 if (rao->rao_type == type &&
755                     rao->rao_len == strlen(msg) &&
756                     memcmp(rao->rao_msg, msg, len) == 0)
757                         break;
758         }
759
760         return (rao);
761 }
762
763 static void
764 call_script(const int argc, const char *const argv[],
765     struct script_msg_head_t *sm_head)
766 {
767         const char *scriptpath;
768         int fd[2];
769         int error;
770         pid_t pid, wpid;
771
772         if ((scriptpath = argv[0]) == NULL)
773                 return;
774
775         fd[0] = fd[1] = -1;
776         if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) {
777                 error = pipe(fd);
778                 if (error) {
779                         warnmsg(LOG_ERR, __func__,
780                             "failed to create a pipe: %s", strerror(errno));
781                         return;
782                 }
783         }
784
785         /* launch the script */
786         pid = fork();
787         if (pid < 0) {
788                 warnmsg(LOG_ERR, __func__,
789                     "failed to fork: %s", strerror(errno));
790                 return;
791         } else if (pid) {       /* parent */
792                 int wstatus;
793
794                 if (fd[0] != -1) {      /* Send message to the child if any. */
795                         ssize_t len;
796                         struct script_msg *smp;
797
798                         close(fd[0]);
799                         TAILQ_FOREACH(smp, sm_head, sm_next) {
800                                 len = strlen(smp->sm_msg);
801                                 warnmsg(LOG_DEBUG, __func__,
802                                     "write to child = %s(%zd)",
803                                     smp->sm_msg, len);
804                                 if (write(fd[1], smp->sm_msg, len) != len) {
805                                         warnmsg(LOG_ERR, __func__,
806                                             "write to child failed: %s",
807                                             strerror(errno));
808                                         break;
809                                 }
810                         }
811                         close(fd[1]);
812                 }
813                 do {
814                         wpid = wait(&wstatus);
815                 } while (wpid != pid && wpid > 0);
816
817                 if (wpid < 0)
818                         warnmsg(LOG_ERR, __func__,
819                             "wait: %s", strerror(errno));
820                 else
821                         warnmsg(LOG_DEBUG, __func__,
822                             "script \"%s\" terminated", scriptpath);
823         } else {                /* child */
824                 int nullfd;
825                 char **_argv;
826
827                 if (safefile(scriptpath)) {
828                         warnmsg(LOG_ERR, __func__,
829                             "script \"%s\" cannot be executed safely",
830                             scriptpath);
831                         exit(1);
832                 }
833                 nullfd = open("/dev/null", O_RDWR);
834                 if (nullfd < 0) {
835                         warnmsg(LOG_ERR, __func__,
836                             "open /dev/null: %s", strerror(errno));
837                         exit(1);
838                 }
839                 if (fd[0] != -1) {      /* Receive message from STDIN if any. */
840                         close(fd[1]);
841                         if (fd[0] != STDIN_FILENO) {
842                                 /* Connect a pipe read-end to child's STDIN. */
843                                 if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
844                                         warnmsg(LOG_ERR, __func__,
845                                             "dup2 STDIN: %s", strerror(errno));
846                                         exit(1);
847                                 }
848                                 close(fd[0]);
849                         }
850                 } else
851                         dup2(nullfd, STDIN_FILENO);
852         
853                 dup2(nullfd, STDOUT_FILENO);
854                 dup2(nullfd, STDERR_FILENO);
855                 if (nullfd > STDERR_FILENO)
856                         close(nullfd);
857
858                 _argv = malloc(sizeof(*_argv) * argc);
859                 if (_argv == NULL) {
860                         warnmsg(LOG_ERR, __func__,
861                                 "malloc: %s", strerror(errno));
862                         exit(1);
863                 }
864                 memcpy(_argv, argv, (size_t)argc);
865                 execv(scriptpath, (char *const *)_argv);
866                 warnmsg(LOG_ERR, __func__, "child: exec failed: %s",
867                     strerror(errno));
868                 exit(1);
869         }
870
871         return;
872 }
873
874 static int
875 safefile(const char *path)
876 {
877         struct stat s;
878         uid_t myuid;
879
880         /* no setuid */
881         if (getuid() != geteuid()) {
882                 warnmsg(LOG_NOTICE, __func__,
883                     "setuid'ed execution not allowed\n");
884                 return (-1);
885         }
886
887         if (lstat(path, &s) != 0) {
888                 warnmsg(LOG_NOTICE, __func__, "lstat failed: %s",
889                     strerror(errno));
890                 return (-1);
891         }
892
893         /* the file must be owned by the running uid */
894         myuid = getuid();
895         if (s.st_uid != myuid) {
896                 warnmsg(LOG_NOTICE, __func__,
897                     "%s has invalid owner uid\n", path);
898                 return (-1);
899         }
900
901         switch (s.st_mode & S_IFMT) {
902         case S_IFREG:
903                 break;
904         default:
905                 warnmsg(LOG_NOTICE, __func__,
906                     "%s is an invalid file type 0x%o\n",
907                     path, (s.st_mode & S_IFMT));
908                 return (-1);
909         }
910
911         return (0);
912 }
913
914 /* Decode domain name label encoding in RFC 1035 Section 3.1 */
915 static size_t
916 dname_labeldec(char *dst, size_t dlen, const char *src)
917 {
918         size_t len;
919         const char *src_origin;
920         const char *src_last;
921         const char *dst_origin;
922
923         src_origin = src;
924         src_last = strchr(src, '\0');
925         dst_origin = dst;
926         memset(dst, '\0', dlen);
927         while (src && (len = (uint8_t)(*src++) & 0x3f) &&
928             (src + len) <= src_last &&
929             (dst - dst_origin < (ssize_t)dlen)) {
930                 if (dst != dst_origin)
931                         *dst++ = '.';
932                 warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
933                 memcpy(dst, src, len);
934                 src += len;
935                 dst += len;
936         }
937         *dst = '\0';
938
939         /*
940          * XXX validate that domain name only contains valid characters
941          * for two reasons: 1) correctness, 2) we do not want to pass
942          * possible malicious, unescaped characters like `` to a script
943          * or program that could be exploited that way.
944          */
945
946         return (src - src_origin);
947 }