]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rtsold/rtsol.c
Fix multiple vulnerabilities in rtsold.
[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                 if (ndo->nd_opt_len == 0) {
407                         warnmsg(LOG_INFO, __func__, "invalid option length 0.");
408                         break;
409                 }
410                 if ((char *)RA_OPT_NEXT_HDR(raoptp) > (char *)icp + msglen) {
411                         warnmsg(LOG_INFO, __func__, "option length overflow.");
412                         break;
413                 }
414
415                 switch (ndo->nd_opt_type) {
416                 case ND_OPT_RDNSS:
417                         rdnss = (struct nd_opt_rdnss *)raoptp;
418
419                         /* Optlen sanity check (Section 5.3.1 in RFC 6106) */
420                         if (rdnss->nd_opt_rdnss_len < 3) {
421                                 warnmsg(LOG_INFO, __func__,
422                                         "too short RDNSS option"
423                                         "in RA from %s was ignored.",
424                                         inet_ntop(AF_INET6, &from.sin6_addr,
425                                             ntopbuf, sizeof(ntopbuf)));
426                                 break;
427                         }
428
429                         addr = (struct in6_addr *)(void *)(raoptp + sizeof(*rdnss));
430                         while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
431                                 if (inet_ntop(AF_INET6, addr, ntopbuf,
432                                         sizeof(ntopbuf)) == NULL) {
433                                         warnmsg(LOG_INFO, __func__,
434                                             "an invalid address in RDNSS option"
435                                             " in RA from %s was ignored.",
436                                             inet_ntop(AF_INET6, &from.sin6_addr,
437                                                 ntopbuf, sizeof(ntopbuf)));
438                                         addr++;
439                                         continue;
440                                 }
441                                 if (IN6_IS_ADDR_LINKLOCAL(addr))
442                                         /* XXX: % has to be escaped here */
443                                         l = snprintf(nsbuf, sizeof(nsbuf),
444                                             "%s%c%s", ntopbuf,
445                                             SCOPE_DELIMITER,
446                                             ifi->ifname);
447                                 else
448                                         l = snprintf(nsbuf, sizeof(nsbuf),
449                                             "%s", ntopbuf);
450                                 if (l < 0 || (size_t)l >= sizeof(nsbuf)) {
451                                         warnmsg(LOG_ERR, __func__,
452                                             "address copying error in "
453                                             "RDNSS option: %d.", l);
454                                         addr++;
455                                         continue;
456                                 }
457                                 warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
458                                     nsbuf);
459
460                                 newent_rao = 0;
461                                 rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
462                                     strlen(nsbuf));
463                                 if (rao == NULL) {
464                                         ELM_MALLOC(rao, break);
465                                         rao->rao_type = ndo->nd_opt_type;
466                                         rao->rao_len = strlen(nsbuf);
467                                         rao->rao_msg = strdup(nsbuf);
468                                         if (rao->rao_msg == NULL) {
469                                                 warnmsg(LOG_ERR, __func__,
470                                                     "strdup failed: %s",
471                                                     strerror(errno));
472                                                 free(rao);
473                                                 addr++;
474                                                 continue;
475                                         }
476                                         newent_rao = 1;
477                                 }
478                                 /* Set expiration timer */
479                                 memset(&rao->rao_expire, 0,
480                                     sizeof(rao->rao_expire));
481                                 memset(&lifetime, 0, sizeof(lifetime));
482                                 lifetime.tv_sec =
483                                     ntohl(rdnss->nd_opt_rdnss_lifetime);
484                                 TS_ADD(&now, &lifetime, &rao->rao_expire);
485
486                                 if (newent_rao)
487                                         TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
488                                             rao, rao_next);
489                                 addr++;
490                         }
491                         break;
492                 case ND_OPT_DNSSL:
493                         dnssl = (struct nd_opt_dnssl *)raoptp;
494
495                         /* Optlen sanity check (Section 5.3.1 in RFC 6106) */
496                         if (dnssl->nd_opt_dnssl_len < 2) {
497                                 warnmsg(LOG_INFO, __func__,
498                                         "too short DNSSL option"
499                                         "in RA from %s was ignored.",
500                                         inet_ntop(AF_INET6, &from.sin6_addr,
501                                             ntopbuf, sizeof(ntopbuf)));
502                                 break;
503                         }
504
505                         /*
506                          * Ensure NUL-termination in DNSSL in case of
507                          * malformed field.
508                          */
509                         p = (char *)RA_OPT_NEXT_HDR(raoptp);
510                         *(p - 1) = '\0';
511
512                         p = raoptp + sizeof(*dnssl);
513                         while (1 < (len = dname_labeldec(dname, sizeof(dname),
514                             p))) {
515                                 /* length == 1 means empty string */
516                                 warnmsg(LOG_DEBUG, __func__, "dname = %s",
517                                     dname);
518
519                                 newent_rao = 0;
520                                 rao = find_raopt(rai, ndo->nd_opt_type, dname,
521                                     strlen(dname));
522                                 if (rao == NULL) {
523                                         ELM_MALLOC(rao, break);
524                                         rao->rao_type = ndo->nd_opt_type;
525                                         rao->rao_len = strlen(dname);
526                                         rao->rao_msg = strdup(dname);
527                                         if (rao->rao_msg == NULL) {
528                                                 warnmsg(LOG_ERR, __func__,
529                                                     "strdup failed: %s",
530                                                     strerror(errno));
531                                                 free(rao);
532                                                 addr++;
533                                                 continue;
534                                         }
535                                         newent_rao = 1;
536                                 }
537                                 /* Set expiration timer */
538                                 memset(&rao->rao_expire, 0,
539                                     sizeof(rao->rao_expire));
540                                 memset(&lifetime, 0, sizeof(lifetime));
541                                 lifetime.tv_sec =
542                                     ntohl(dnssl->nd_opt_dnssl_lifetime);
543                                 TS_ADD(&now, &lifetime, &rao->rao_expire);
544
545                                 if (newent_rao)
546                                         TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
547                                             rao, rao_next);
548                                 p += len;
549                         }
550                         break;
551                 default:  
552                         /* nothing to do for other options */
553                         break;
554                 }
555                 raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
556         }
557         if (newent_rai)
558                 TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next);
559
560         ra_opt_handler(ifi);
561         ifi->racnt++;
562
563         switch (ifi->state) {
564         case IFS_IDLE:          /* should be ignored */
565         case IFS_DELAY:         /* right? */
566                 break;
567         case IFS_PROBE:
568                 ifi->state = IFS_IDLE;
569                 ifi->probes = 0;
570                 rtsol_timer_update(ifi);
571                 break;
572         }
573 }
574
575 static char resstr_ns_prefix[] = "nameserver ";
576 static char resstr_sh_prefix[] = "search ";
577 static char resstr_nl[] = "\n";
578 static char resstr_sp[] = " ";
579
580 int
581 ra_opt_handler(struct ifinfo *ifi)
582 {
583         struct ra_opt *rao;
584         struct rainfo *rai;
585         struct script_msg *smp1, *smp2, *smp3;
586         struct timespec now;
587         struct script_msg_head_t sm_rdnss_head =
588             TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
589         struct script_msg_head_t sm_dnssl_head =
590             TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
591
592         int dcount, dlen;
593
594         dcount = 0;
595         dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
596         clock_gettime(CLOCK_MONOTONIC_FAST, &now);
597
598         /*
599          * All options from multiple RAs with the same or different
600          * source addresses on a single interface will be gathered and
601          * handled, not overridden.  [RFC 4861 6.3.4]
602          */
603         TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
604                 TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
605                         switch (rao->rao_type) {
606                         case ND_OPT_RDNSS:
607                                 if (TS_CMP(&now, &rao->rao_expire, >)) {
608                                         warnmsg(LOG_INFO, __func__,
609                                             "expired rdnss entry: %s",
610                                             (char *)rao->rao_msg);
611                                         break;
612                                 }
613                                 ELM_MALLOC(smp1, continue);
614                                 ELM_MALLOC(smp2, goto free1);
615                                 ELM_MALLOC(smp3, goto free2);
616                                 smp1->sm_msg = resstr_ns_prefix;
617                                 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1,
618                                     sm_next);
619                                 smp2->sm_msg = rao->rao_msg;
620                                 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2,
621                                     sm_next);
622                                 smp3->sm_msg = resstr_nl;
623                                 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3,
624                                     sm_next);
625                                 ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED;
626                                 break;
627                         case ND_OPT_DNSSL:
628                                 if (TS_CMP(&now, &rao->rao_expire, >)) {
629                                         warnmsg(LOG_INFO, __func__,
630                                             "expired dnssl entry: %s",
631                                             (char *)rao->rao_msg);
632                                         break;
633                                 }
634                                 dcount++;
635                                 /* Check resolv.conf(5) restrictions. */
636                                 if (dcount > 6) {
637                                         warnmsg(LOG_INFO, __func__,
638                                             "dnssl entry exceeding maximum count (%d>6)"
639                                             ": %s", dcount, (char *)rao->rao_msg);
640                                         break;
641                                 }
642                                 if (256 < dlen + strlen(rao->rao_msg) +
643                                     strlen(resstr_sp)) {
644                                         warnmsg(LOG_INFO, __func__,
645                                             "dnssl entry exceeding maximum length "
646                                             "(>256): %s", (char *)rao->rao_msg);
647                                         break;
648                                 }
649                                 ELM_MALLOC(smp1, continue);
650                                 ELM_MALLOC(smp2, goto free1);
651                                 if (TAILQ_EMPTY(&sm_dnssl_head)) {
652                                         ELM_MALLOC(smp3, goto free2);
653                                         smp3->sm_msg = resstr_sh_prefix;
654                                         TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
655                                             sm_next);
656                                 }
657                                 smp1->sm_msg = rao->rao_msg;
658                                 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
659                                     sm_next);
660                                 smp2->sm_msg = resstr_sp;
661                                 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
662                                     sm_next);
663                                 dlen += strlen(rao->rao_msg) +
664                                     strlen(resstr_sp);
665                                 ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
666                                 break;
667                         }
668                         continue;
669 free2:
670                         free(smp2);
671 free1:
672                         free(smp1);
673                 }
674                 /* Call the script for each information source. */
675                 if (uflag)
676                         ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head,
677                             &sm_dnssl_head);
678         }
679         /* Call the script for each interface. */
680         if (!uflag)
681                 ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head,
682                     &sm_dnssl_head);
683         return (0);
684 }
685
686 char *
687 make_rsid(const char *ifname, const char *origin, struct rainfo *rai)
688 {
689         char hbuf[NI_MAXHOST];
690         
691         if (rai == NULL)
692                 sprintf(rsid, "%s:%s", ifname, origin);
693         else {
694                 if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr))
695                         return (NULL);
696                 if (getnameinfo((struct sockaddr *)&rai->rai_saddr,
697                         rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0,
698                         NI_NUMERICHOST) != 0)
699                         return (NULL);
700                 sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf);
701         }
702         warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid);
703         return (rsid);
704 }
705
706 int
707 ra_opt_rdnss_dispatch(struct ifinfo *ifi, struct rainfo *rai,
708     struct script_msg_head_t *sm_rdnss_head,
709     struct script_msg_head_t *sm_dnssl_head)
710 {
711         struct script_msg *smp1;
712         const char *r;
713         int error;
714
715         error = 0;
716         /* Add \n for DNSSL list. */
717         if (!TAILQ_EMPTY(sm_dnssl_head)) {
718                 ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit);
719                 smp1->sm_msg = resstr_nl;
720                 TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next);
721         }
722         TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next);
723
724         r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, uflag ? rai : NULL);
725         if (r == NULL) {
726                 warnmsg(LOG_ERR, __func__, "make_rsid() failed.  "
727                     "Script was not invoked.");
728                 error = 1;
729                 goto ra_opt_rdnss_freeit;
730         }
731         if (!TAILQ_EMPTY(sm_rdnss_head))
732                 CALL_SCRIPT(RESADD, sm_rdnss_head);
733         else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
734             ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
735                 CALL_SCRIPT(RESDEL, NULL);
736                 ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
737                 ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
738         }
739
740 ra_opt_rdnss_freeit:
741         /* Clear script message queue. */
742         if (!TAILQ_EMPTY(sm_rdnss_head)) {
743                 while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) {
744                         TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next);
745                         free(smp1);
746                 }
747         }
748         if (!TAILQ_EMPTY(sm_dnssl_head)) {
749                 while ((smp1 = TAILQ_FIRST(sm_dnssl_head)) != NULL) {
750                         TAILQ_REMOVE(sm_dnssl_head, smp1, sm_next);
751                         free(smp1);
752                 }
753         }
754         return (error);
755 }
756
757 static struct ra_opt *
758 find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
759 {
760         struct ra_opt *rao;
761
762         TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
763                 if (rao->rao_type == type &&
764                     rao->rao_len == strlen(msg) &&
765                     memcmp(rao->rao_msg, msg, len) == 0)
766                         break;
767         }
768
769         return (rao);
770 }
771
772 static void
773 call_script(const int argc, const char *const argv[],
774     struct script_msg_head_t *sm_head)
775 {
776         const char *scriptpath;
777         int fd[2];
778         int error;
779         pid_t pid, wpid;
780
781         if ((scriptpath = argv[0]) == NULL)
782                 return;
783
784         fd[0] = fd[1] = -1;
785         if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) {
786                 error = pipe(fd);
787                 if (error) {
788                         warnmsg(LOG_ERR, __func__,
789                             "failed to create a pipe: %s", strerror(errno));
790                         return;
791                 }
792         }
793
794         /* launch the script */
795         pid = fork();
796         if (pid < 0) {
797                 warnmsg(LOG_ERR, __func__,
798                     "failed to fork: %s", strerror(errno));
799                 return;
800         } else if (pid) {       /* parent */
801                 int wstatus;
802
803                 if (fd[0] != -1) {      /* Send message to the child if any. */
804                         ssize_t len;
805                         struct script_msg *smp;
806
807                         close(fd[0]);
808                         TAILQ_FOREACH(smp, sm_head, sm_next) {
809                                 len = strlen(smp->sm_msg);
810                                 warnmsg(LOG_DEBUG, __func__,
811                                     "write to child = %s(%zd)",
812                                     smp->sm_msg, len);
813                                 if (write(fd[1], smp->sm_msg, len) != len) {
814                                         warnmsg(LOG_ERR, __func__,
815                                             "write to child failed: %s",
816                                             strerror(errno));
817                                         break;
818                                 }
819                         }
820                         close(fd[1]);
821                 }
822                 do {
823                         wpid = wait(&wstatus);
824                 } while (wpid != pid && wpid > 0);
825
826                 if (wpid < 0)
827                         warnmsg(LOG_ERR, __func__,
828                             "wait: %s", strerror(errno));
829                 else
830                         warnmsg(LOG_DEBUG, __func__,
831                             "script \"%s\" terminated", scriptpath);
832         } else {                /* child */
833                 int nullfd;
834                 char **_argv;
835
836                 if (safefile(scriptpath)) {
837                         warnmsg(LOG_ERR, __func__,
838                             "script \"%s\" cannot be executed safely",
839                             scriptpath);
840                         exit(1);
841                 }
842                 nullfd = open("/dev/null", O_RDWR);
843                 if (nullfd < 0) {
844                         warnmsg(LOG_ERR, __func__,
845                             "open /dev/null: %s", strerror(errno));
846                         exit(1);
847                 }
848                 if (fd[0] != -1) {      /* Receive message from STDIN if any. */
849                         close(fd[1]);
850                         if (fd[0] != STDIN_FILENO) {
851                                 /* Connect a pipe read-end to child's STDIN. */
852                                 if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
853                                         warnmsg(LOG_ERR, __func__,
854                                             "dup2 STDIN: %s", strerror(errno));
855                                         exit(1);
856                                 }
857                                 close(fd[0]);
858                         }
859                 } else
860                         dup2(nullfd, STDIN_FILENO);
861         
862                 dup2(nullfd, STDOUT_FILENO);
863                 dup2(nullfd, STDERR_FILENO);
864                 if (nullfd > STDERR_FILENO)
865                         close(nullfd);
866
867                 _argv = malloc(sizeof(*_argv) * argc);
868                 if (_argv == NULL) {
869                         warnmsg(LOG_ERR, __func__,
870                                 "malloc: %s", strerror(errno));
871                         exit(1);
872                 }
873                 memcpy(_argv, argv, (size_t)argc);
874                 execv(scriptpath, (char *const *)_argv);
875                 warnmsg(LOG_ERR, __func__, "child: exec failed: %s",
876                     strerror(errno));
877                 exit(1);
878         }
879
880         return;
881 }
882
883 static int
884 safefile(const char *path)
885 {
886         struct stat s;
887         uid_t myuid;
888
889         /* no setuid */
890         if (getuid() != geteuid()) {
891                 warnmsg(LOG_NOTICE, __func__,
892                     "setuid'ed execution not allowed\n");
893                 return (-1);
894         }
895
896         if (lstat(path, &s) != 0) {
897                 warnmsg(LOG_NOTICE, __func__, "lstat failed: %s",
898                     strerror(errno));
899                 return (-1);
900         }
901
902         /* the file must be owned by the running uid */
903         myuid = getuid();
904         if (s.st_uid != myuid) {
905                 warnmsg(LOG_NOTICE, __func__,
906                     "%s has invalid owner uid\n", path);
907                 return (-1);
908         }
909
910         switch (s.st_mode & S_IFMT) {
911         case S_IFREG:
912                 break;
913         default:
914                 warnmsg(LOG_NOTICE, __func__,
915                     "%s is an invalid file type 0x%o\n",
916                     path, (s.st_mode & S_IFMT));
917                 return (-1);
918         }
919
920         return (0);
921 }
922
923 /* Decode domain name label encoding in RFC 1035 Section 3.1 */
924 static size_t
925 dname_labeldec(char *dst, size_t dlen, const char *src)
926 {
927         size_t len;
928         const char *src_origin;
929         const char *src_last;
930         const char *dst_origin;
931
932         src_origin = src;
933         src_last = strchr(src, '\0');
934         dst_origin = dst;
935         memset(dst, '\0', dlen);
936         while ((len = (*src++) & 0x3f) &&
937             src + len <= src_last &&
938             len + 1 + (dst == dst_origin ? 0 : 1) <= dlen) {
939                 if (dst != dst_origin) {
940                         *dst++ = '.';
941                         dlen--;
942                 }
943                 warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
944                 memcpy(dst, src, len);
945                 src += len;
946                 dst += len;
947                 dlen -= len;
948         }
949         *dst = '\0';
950
951         /*
952          * XXX validate that domain name only contains valid characters
953          * for two reasons: 1) correctness, 2) we do not want to pass
954          * possible malicious, unescaped characters like `` to a script
955          * or program that could be exploited that way.
956          */
957
958         return (src - src_origin);
959 }