]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - usr.sbin/rtadvd/rtadvd.c
Merge from head to stable/8:
[FreeBSD/stable/8.git] / usr.sbin / rtadvd / rtadvd.c
1 /*      $FreeBSD$       */
2 /*      $KAME: rtadvd.c,v 1.82 2003/08/05 12:34:23 itojun Exp $ */
3
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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
33 #include <sys/param.h>
34 #include <sys/socket.h>
35 #include <sys/uio.h>
36 #include <sys/time.h>
37 #include <sys/queue.h>
38
39 #include <net/if.h>
40 #include <net/route.h>
41 #include <net/if_dl.h>
42 #include <netinet/in.h>
43 #include <netinet/ip6.h>
44 #include <netinet6/ip6_var.h>
45 #include <netinet/icmp6.h>
46
47 #include <arpa/inet.h>
48
49 #include <time.h>
50 #include <unistd.h>
51 #include <stdio.h>
52 #include <err.h>
53 #include <errno.h>
54 #include <libutil.h>
55 #include <string.h>
56 #include <stdlib.h>
57 #include <syslog.h>
58 #ifdef HAVE_POLL_H
59 #include <poll.h>
60 #endif
61
62 #include "rtadvd.h"
63 #include "rrenum.h"
64 #include "advcap.h"
65 #include "timer.h"
66 #include "if.h"
67 #include "config.h"
68 #include "dump.h"
69
70 struct msghdr rcvmhdr;
71 static u_char *rcvcmsgbuf;
72 static size_t rcvcmsgbuflen;
73 static u_char *sndcmsgbuf = NULL;
74 static size_t sndcmsgbuflen;
75 volatile sig_atomic_t do_dump;
76 volatile sig_atomic_t do_die;
77 struct msghdr sndmhdr;
78 struct iovec rcviov[2];
79 struct iovec sndiov[2];
80 struct sockaddr_in6 rcvfrom;
81 struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
82 struct in6_addr in6a_site_allrouters;
83 static char *dumpfilename = "/var/run/rtadvd.dump";
84 static char *pidfilename = "/var/run/rtadvd.pid";
85 static struct pidfh *pfh;
86 static char *mcastif;
87 int sock;
88 int rtsock = -1;
89 int accept_rr = 0;
90 int dflag = 0, sflag = 0;
91
92 u_char *conffile = NULL;
93
94 struct rainfo *ralist = NULL;
95 struct nd_optlist {
96         struct nd_optlist *next;
97         struct nd_opt_hdr *opt;
98 };
99 union nd_opts {
100         struct nd_opt_hdr *nd_opt_array[9];
101         struct {
102                 struct nd_opt_hdr *zero;
103                 struct nd_opt_hdr *src_lladdr;
104                 struct nd_opt_hdr *tgt_lladdr;
105                 struct nd_opt_prefix_info *pi;
106                 struct nd_opt_rd_hdr *rh;
107                 struct nd_opt_mtu *mtu;
108                 struct nd_optlist *list;
109         } nd_opt_each;
110 };
111 #define nd_opts_src_lladdr      nd_opt_each.src_lladdr
112 #define nd_opts_tgt_lladdr      nd_opt_each.tgt_lladdr
113 #define nd_opts_pi              nd_opt_each.pi
114 #define nd_opts_rh              nd_opt_each.rh
115 #define nd_opts_mtu             nd_opt_each.mtu
116 #define nd_opts_list            nd_opt_each.list
117
118 #define NDOPT_FLAG_SRCLINKADDR 0x1
119 #define NDOPT_FLAG_TGTLINKADDR 0x2
120 #define NDOPT_FLAG_PREFIXINFO 0x4
121 #define NDOPT_FLAG_RDHDR 0x8
122 #define NDOPT_FLAG_MTU 0x10
123
124 u_int32_t ndopt_flags[] = {
125         0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR,
126         NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU,
127 };
128
129 int main(int, char *[]);
130 static void set_die(int);
131 static void die(void);
132 static void sock_open(void);
133 static void rtsock_open(void);
134 static void rtadvd_input(void);
135 static void rs_input(int, struct nd_router_solicit *,
136                           struct in6_pktinfo *, struct sockaddr_in6 *);
137 static void ra_input(int, struct nd_router_advert *,
138                           struct in6_pktinfo *, struct sockaddr_in6 *);
139 static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
140                              struct sockaddr_in6 *);
141 static int nd6_options(struct nd_opt_hdr *, int,
142                             union nd_opts *, u_int32_t);
143 static void free_ndopts(union nd_opts *);
144 static void ra_output(struct rainfo *);
145 static void rtmsg_input(void);
146 static void rtadvd_set_dump_file(int);
147 static void set_short_delay(struct rainfo *);
148
149 int
150 main(argc, argv)
151         int argc;
152         char *argv[];
153 {
154 #ifdef HAVE_POLL_H
155         struct pollfd set[2];
156 #else
157         fd_set *fdsetp, *selectfdp;
158         int fdmasks;
159         int maxfd = 0;
160 #endif
161         struct timeval *timeout;
162         int i, ch;
163         int fflag = 0, logopt;
164         pid_t pid, otherpid;
165
166         /* get command line options and arguments */
167         while ((ch = getopt(argc, argv, "c:dDF:fMp:Rs")) != -1) {
168                 switch (ch) {
169                 case 'c':
170                         conffile = optarg;
171                         break;
172                 case 'd':
173                         dflag = 1;
174                         break;
175                 case 'D':
176                         dflag = 2;
177                         break;
178                 case 'f':
179                         fflag = 1;
180                         break;
181                 case 'M':
182                         mcastif = optarg;
183                         break;
184                 case 'R':
185                         fprintf(stderr, "rtadvd: "
186                                 "the -R option is currently ignored.\n");
187                         /* accept_rr = 1; */
188                         /* run anyway... */
189                         break;
190                 case 's':
191                         sflag = 1;
192                         break;
193                 case 'p':
194                         pidfilename = optarg;
195                         break;
196                 case 'F':
197                         dumpfilename = optarg;
198                         break;
199                 }
200         }
201         argc -= optind;
202         argv += optind;
203         if (argc == 0) {
204                 fprintf(stderr,
205                         "usage: rtadvd [-dDfMRs] [-c conffile] "
206                         "[-F dumpfile] [-p pidfile] interfaces...\n");
207                 exit(1);
208         }
209
210         logopt = LOG_NDELAY | LOG_PID;
211         if (fflag)
212                 logopt |= LOG_PERROR;
213         openlog("rtadvd", logopt, LOG_DAEMON);
214
215         /* set log level */
216         if (dflag == 0)
217                 (void)setlogmask(LOG_UPTO(LOG_ERR));
218         if (dflag == 1)
219                 (void)setlogmask(LOG_UPTO(LOG_INFO));
220
221         /* timer initialization */
222         rtadvd_timer_init();
223
224 #ifndef HAVE_ARC4RANDOM
225         /* random value initialization */
226 #ifdef __FreeBSD__
227         srandomdev();
228 #else
229         srandom((u_long)time(NULL));
230 #endif
231 #endif
232
233         /* get iflist block from kernel */
234         init_iflist();
235
236         while (argc--)
237                 getconfig(*argv++);
238
239         if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1) {
240                 fprintf(stderr, "fatal: inet_pton failed\n");
241                 exit(1);
242         }
243
244         pfh = pidfile_open(pidfilename, 0600, &otherpid);
245         if (pfh == NULL) {
246                 if (errno == EEXIST)
247                         errx(1, "%s already running, pid: %d",
248                             getprogname(), otherpid);
249                 syslog(LOG_ERR,
250                     "<%s> failed to open the pid log file, run anyway.",
251                     __func__);
252         }
253
254         if (!fflag)
255                 daemon(1, 0);
256
257         sock_open();
258
259         /* record the current PID */
260         pid = getpid();
261         pidfile_write(pfh);
262
263 #ifdef HAVE_POLL_H
264         set[0].fd = sock;
265         set[0].events = POLLIN;
266         if (sflag == 0) {
267                 rtsock_open();
268                 set[1].fd = rtsock;
269                 set[1].events = POLLIN;
270         } else
271                 set[1].fd = -1;
272 #else
273         maxfd = sock;
274         if (sflag == 0) {
275                 rtsock_open();
276                 if (rtsock > sock)
277                         maxfd = rtsock;
278         } else
279                 rtsock = -1;
280
281         fdmasks = howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask);
282         if ((fdsetp = malloc(fdmasks)) == NULL) {
283                 err(1, "malloc");
284                 /*NOTREACHED*/
285         }
286         if ((selectfdp = malloc(fdmasks)) == NULL) {
287                 err(1, "malloc");
288                 /*NOTREACHED*/
289         }
290         memset(fdsetp, 0, fdmasks);
291         FD_SET(sock, fdsetp);
292         if (rtsock >= 0)
293                 FD_SET(rtsock, fdsetp);
294 #endif
295
296         signal(SIGTERM, set_die);
297         signal(SIGUSR1, rtadvd_set_dump_file);
298
299         while (1) {
300 #ifndef HAVE_POLL_H
301                 memcpy(selectfdp, fdsetp, fdmasks); /* reinitialize */
302 #endif
303
304                 if (do_dump) {  /* SIGUSR1 */
305                         do_dump = 0;
306                         rtadvd_dump_file(dumpfilename);
307                 }
308
309                 if (do_die) {
310                         die();
311                         /*NOTREACHED*/
312                 }
313
314                 /* timer expiration check and reset the timer */
315                 timeout = rtadvd_check_timer();
316
317                 if (timeout != NULL) {
318                         syslog(LOG_DEBUG,
319                             "<%s> set timer to %ld:%ld. waiting for "
320                             "inputs or timeout", __func__,
321                             (long int)timeout->tv_sec,
322                             (long int)timeout->tv_usec);
323                 } else {
324                         syslog(LOG_DEBUG,
325                             "<%s> there's no timer. waiting for inputs",
326                             __func__);
327                 }
328
329 #ifdef HAVE_POLL_H
330                 if ((i = poll(set, 2, timeout ? (timeout->tv_sec * 1000 +
331                     timeout->tv_usec / 1000) : INFTIM)) < 0)
332 #else
333                 if ((i = select(maxfd + 1, selectfdp, NULL, NULL,
334                     timeout)) < 0)
335 #endif
336                 {
337                         /* EINTR would occur upon SIGUSR1 for status dump */
338                         if (errno != EINTR)
339                                 syslog(LOG_ERR, "<%s> select: %s",
340                                     __func__, strerror(errno));
341                         continue;
342                 }
343                 if (i == 0)     /* timeout */
344                         continue;
345 #ifdef HAVE_POLL_H
346                 if (rtsock != -1 && set[1].revents & POLLIN)
347 #else
348                 if (rtsock != -1 && FD_ISSET(rtsock, selectfdp))
349 #endif
350                         rtmsg_input();
351 #ifdef HAVE_POLL_H
352                 if (set[0].revents & POLLIN)
353 #else
354                 if (FD_ISSET(sock, selectfdp))
355 #endif
356                         rtadvd_input();
357         }
358         exit(0);                /* NOTREACHED */
359 }
360
361 static void
362 rtadvd_set_dump_file(sig)
363         int sig;
364 {
365         do_dump = 1;
366 }
367
368 static void
369 set_die(sig)
370         int sig;
371 {
372         do_die = 1;
373 }
374
375 static void
376 die()
377 {
378         struct rainfo *ra;
379         int i;
380         const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
381
382         if (dflag > 1) {
383                 syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n",
384                     __func__);
385         }
386
387         for (ra = ralist; ra; ra = ra->next) {
388                 ra->lifetime = 0;
389                 make_packet(ra);
390         }
391         for (i = 0; i < retrans; i++) {
392                 for (ra = ralist; ra; ra = ra->next)
393                         ra_output(ra);
394                 sleep(MIN_DELAY_BETWEEN_RAS);
395         }
396         pidfile_remove(pfh);
397         exit(0);
398         /*NOTREACHED*/
399 }
400
401 static void
402 rtmsg_input()
403 {
404         int n, type, ifindex = 0, plen;
405         size_t len;
406         char msg[2048], *next, *lim;
407         u_char ifname[IF_NAMESIZE];
408         struct prefix *prefix;
409         struct rainfo *rai;
410         struct in6_addr *addr;
411         char addrbuf[INET6_ADDRSTRLEN];
412         int prefixchange = 0;
413
414         n = read(rtsock, msg, sizeof(msg));
415         if (dflag > 1) {
416                 syslog(LOG_DEBUG, "<%s> received a routing message "
417                     "(type = %d, len = %d)", __func__, rtmsg_type(msg), n);
418         }
419         if (n > rtmsg_len(msg)) {
420                 /*
421                  * This usually won't happen for messages received on 
422                  * a routing socket.
423                  */
424                 if (dflag > 1)
425                         syslog(LOG_DEBUG,
426                             "<%s> received data length is larger than "
427                             "1st routing message len. multiple messages? "
428                             "read %d bytes, but 1st msg len = %d",
429                             __func__, n, rtmsg_len(msg));
430 #if 0
431                 /* adjust length */
432                 n = rtmsg_len(msg);
433 #endif
434         }
435
436         lim = msg + n;
437         for (next = msg; next < lim; next += len) {
438                 int oldifflags;
439
440                 next = get_next_msg(next, lim, 0, &len,
441                                     RTADV_TYPE2BITMASK(RTM_ADD) |
442                                     RTADV_TYPE2BITMASK(RTM_DELETE) |
443                                     RTADV_TYPE2BITMASK(RTM_NEWADDR) |
444                                     RTADV_TYPE2BITMASK(RTM_DELADDR) |
445                                     RTADV_TYPE2BITMASK(RTM_IFINFO));
446                 if (len == 0)
447                         break;
448                 type = rtmsg_type(next);
449                 switch (type) {
450                 case RTM_ADD:
451                 case RTM_DELETE:
452                         ifindex = get_rtm_ifindex(next);
453                         break;
454                 case RTM_NEWADDR:
455                 case RTM_DELADDR:
456                         ifindex = get_ifam_ifindex(next);
457                         break;
458                 case RTM_IFINFO:
459                         ifindex = get_ifm_ifindex(next);
460                         break;
461                 default:
462                         /* should not reach here */
463                         if (dflag > 1) {
464                                 syslog(LOG_DEBUG,
465                                        "<%s:%d> unknown rtmsg %d on %s",
466                                        __func__, __LINE__, type,
467                                        if_indextoname(ifindex, ifname));
468                         }
469                         continue;
470                 }
471
472                 if ((rai = if_indextorainfo(ifindex)) == NULL) {
473                         if (dflag > 1) {
474                                 syslog(LOG_DEBUG,
475                                        "<%s> route changed on "
476                                        "non advertising interface(%s)",
477                                        __func__,
478                                        if_indextoname(ifindex, ifname));
479                         }
480                         continue;
481                 }
482                 oldifflags = iflist[ifindex]->ifm_flags;
483
484                 switch (type) {
485                 case RTM_ADD:
486                         /* init ifflags because it may have changed */
487                         iflist[ifindex]->ifm_flags =
488                             if_getflags(ifindex, iflist[ifindex]->ifm_flags);
489
490                         if (sflag)
491                                 break;  /* we aren't interested in prefixes  */
492
493                         addr = get_addr(msg);
494                         plen = get_prefixlen(msg);
495                         /* sanity check for plen */
496                         /* as RFC2373, prefixlen is at least 4 */
497                         if (plen < 4 || plen > 127) {
498                                 syslog(LOG_INFO, "<%s> new interface route's"
499                                     "plen %d is invalid for a prefix",
500                                     __func__, plen);
501                                 break;
502                         }
503                         prefix = find_prefix(rai, addr, plen);
504                         if (prefix) {
505                                 if (prefix->timer) {
506                                         /*
507                                          * If the prefix has been invalidated,
508                                          * make it available again.
509                                          */
510                                         update_prefix(prefix);
511                                         prefixchange = 1;
512                                 } else if (dflag > 1) {
513                                         syslog(LOG_DEBUG,
514                                             "<%s> new prefix(%s/%d) "
515                                             "added on %s, "
516                                             "but it was already in list",
517                                             __func__,
518                                             inet_ntop(AF_INET6, addr,
519                                             (char *)addrbuf, INET6_ADDRSTRLEN),
520                                             plen, rai->ifname);
521                                 }
522                                 break;
523                         }
524                         make_prefix(rai, ifindex, addr, plen);
525                         prefixchange = 1;
526                         break;
527                 case RTM_DELETE:
528                         /* init ifflags because it may have changed */
529                         iflist[ifindex]->ifm_flags =
530                             if_getflags(ifindex, iflist[ifindex]->ifm_flags);
531
532                         if (sflag)
533                                 break;
534
535                         addr = get_addr(msg);
536                         plen = get_prefixlen(msg);
537                         /* sanity check for plen */
538                         /* as RFC2373, prefixlen is at least 4 */
539                         if (plen < 4 || plen > 127) {
540                                 syslog(LOG_INFO,
541                                     "<%s> deleted interface route's "
542                                     "plen %d is invalid for a prefix",
543                                     __func__, plen);
544                                 break;
545                         }
546                         prefix = find_prefix(rai, addr, plen);
547                         if (prefix == NULL) {
548                                 if (dflag > 1) {
549                                         syslog(LOG_DEBUG,
550                                             "<%s> prefix(%s/%d) was "
551                                             "deleted on %s, "
552                                             "but it was not in list",
553                                             __func__,
554                                             inet_ntop(AF_INET6, addr,
555                                             (char *)addrbuf, INET6_ADDRSTRLEN),
556                                             plen, rai->ifname);
557                                 }
558                                 break;
559                         }
560                         invalidate_prefix(prefix);
561                         prefixchange = 1;
562                         break;
563                 case RTM_NEWADDR:
564                 case RTM_DELADDR:
565                         /* init ifflags because it may have changed */
566                         iflist[ifindex]->ifm_flags =
567                             if_getflags(ifindex, iflist[ifindex]->ifm_flags);
568                         break;
569                 case RTM_IFINFO:
570                         iflist[ifindex]->ifm_flags = get_ifm_flags(next);
571                         break;
572                 default:
573                         /* should not reach here */
574                         if (dflag > 1) {
575                                 syslog(LOG_DEBUG,
576                                     "<%s:%d> unknown rtmsg %d on %s",
577                                     __func__, __LINE__, type,
578                                     if_indextoname(ifindex, ifname));
579                         }
580                         return;
581                 }
582
583                 /* check if an interface flag is changed */
584                 if ((oldifflags & IFF_UP) && /* UP to DOWN */
585                     !(iflist[ifindex]->ifm_flags & IFF_UP)) {
586                         syslog(LOG_INFO,
587                             "<%s> interface %s becomes down. stop timer.",
588                             __func__, rai->ifname);
589                         rtadvd_remove_timer(&rai->timer);
590                 } else if (!(oldifflags & IFF_UP) && /* DOWN to UP */
591                          (iflist[ifindex]->ifm_flags & IFF_UP)) {
592                         syslog(LOG_INFO,
593                             "<%s> interface %s becomes up. restart timer.",
594                             __func__, rai->ifname);
595
596                         rai->initcounter = 0; /* reset the counter */
597                         rai->waiting = 0; /* XXX */
598                         rai->timer = rtadvd_add_timer(ra_timeout,
599                             ra_timer_update, rai, rai);
600                         ra_timer_update((void *)rai, &rai->timer->tm);
601                         rtadvd_set_timer(&rai->timer->tm, rai->timer);
602                 } else if (prefixchange &&
603                     (iflist[ifindex]->ifm_flags & IFF_UP)) {
604                         /*
605                          * An advertised prefix has been added or invalidated.
606                          * Will notice the change in a short delay.
607                          */
608                         rai->initcounter = 0;
609                         set_short_delay(rai);
610                 }
611         }
612
613         return;
614 }
615
616 void
617 rtadvd_input()
618 {
619         int i;
620         int *hlimp = NULL;
621 #ifdef OLDRAWSOCKET
622         struct ip6_hdr *ip;
623 #endif 
624         struct icmp6_hdr *icp;
625         int ifindex = 0;
626         struct cmsghdr *cm;
627         struct in6_pktinfo *pi = NULL;
628         u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
629         struct in6_addr dst = in6addr_any;
630
631         /*
632          * Get message. We reset msg_controllen since the field could
633          * be modified if we had received a message before setting
634          * receive options.
635          */
636         rcvmhdr.msg_controllen = rcvcmsgbuflen;
637         if ((i = recvmsg(sock, &rcvmhdr, 0)) < 0)
638                 return;
639
640         /* extract optional information via Advanced API */
641         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr);
642              cm;
643              cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
644                 if (cm->cmsg_level == IPPROTO_IPV6 &&
645                     cm->cmsg_type == IPV6_PKTINFO &&
646                     cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
647                         pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
648                         ifindex = pi->ipi6_ifindex;
649                         dst = pi->ipi6_addr;
650                 }
651                 if (cm->cmsg_level == IPPROTO_IPV6 &&
652                     cm->cmsg_type == IPV6_HOPLIMIT &&
653                     cm->cmsg_len == CMSG_LEN(sizeof(int)))
654                         hlimp = (int *)CMSG_DATA(cm);
655         }
656         if (ifindex == 0) {
657                 syslog(LOG_ERR,
658                        "<%s> failed to get receiving interface",
659                        __func__);
660                 return;
661         }
662         if (hlimp == NULL) {
663                 syslog(LOG_ERR,
664                        "<%s> failed to get receiving hop limit",
665                        __func__);
666                 return;
667         }
668
669         /*
670          * If we happen to receive data on an interface which is now gone
671          * or down, just discard the data.
672          */
673         if (iflist[pi->ipi6_ifindex] == NULL ||
674             (iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
675                 syslog(LOG_INFO,
676                        "<%s> received data on a disabled interface (%s)",
677                        __func__,
678                        (iflist[pi->ipi6_ifindex] == NULL) ? "[gone]" :
679                             if_indextoname(pi->ipi6_ifindex, ifnamebuf));
680                 return;
681         }
682
683 #ifdef OLDRAWSOCKET
684         if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) {
685                 syslog(LOG_ERR,
686                        "<%s> packet size(%d) is too short",
687                        __func__, i);
688                 return;
689         }
690
691         ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base;
692         icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */
693 #else
694         if (i < sizeof(struct icmp6_hdr)) {
695                 syslog(LOG_ERR,
696                        "<%s> packet size(%d) is too short",
697                        __func__, i);
698                 return;
699         }
700
701         icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
702 #endif
703
704         switch (icp->icmp6_type) {
705         case ND_ROUTER_SOLICIT:
706                 /*
707                  * Message verification - RFC-2461 6.1.1
708                  * XXX: these checks must be done in the kernel as well,
709                  *      but we can't completely rely on them.
710                  */
711                 if (*hlimp != 255) {
712                         syslog(LOG_NOTICE,
713                             "<%s> RS with invalid hop limit(%d) "
714                             "received from %s on %s",
715                             __func__, *hlimp,
716                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
717                             INET6_ADDRSTRLEN),
718                             if_indextoname(pi->ipi6_ifindex, ifnamebuf));
719                         return;
720                 }
721                 if (icp->icmp6_code) {
722                         syslog(LOG_NOTICE,
723                             "<%s> RS with invalid ICMP6 code(%d) "
724                             "received from %s on %s",
725                             __func__, icp->icmp6_code,
726                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
727                             INET6_ADDRSTRLEN),
728                             if_indextoname(pi->ipi6_ifindex, ifnamebuf));
729                         return;
730                 }
731                 if (i < sizeof(struct nd_router_solicit)) {
732                         syslog(LOG_NOTICE,
733                             "<%s> RS from %s on %s does not have enough "
734                             "length (len = %d)",
735                             __func__,
736                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
737                             INET6_ADDRSTRLEN),
738                             if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
739                         return;
740                 }
741                 rs_input(i, (struct nd_router_solicit *)icp, pi, &rcvfrom);
742                 break;
743         case ND_ROUTER_ADVERT:
744                 /*
745                  * Message verification - RFC-2461 6.1.2
746                  * XXX: there's a same dilemma as above... 
747                  */
748                 if (*hlimp != 255) {
749                         syslog(LOG_NOTICE,
750                             "<%s> RA with invalid hop limit(%d) "
751                             "received from %s on %s",
752                             __func__, *hlimp,
753                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
754                             INET6_ADDRSTRLEN),
755                             if_indextoname(pi->ipi6_ifindex, ifnamebuf));
756                         return;
757                 }
758                 if (icp->icmp6_code) {
759                         syslog(LOG_NOTICE,
760                             "<%s> RA with invalid ICMP6 code(%d) "
761                             "received from %s on %s",
762                             __func__, icp->icmp6_code,
763                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
764                             INET6_ADDRSTRLEN),
765                             if_indextoname(pi->ipi6_ifindex, ifnamebuf));
766                         return;
767                 }
768                 if (i < sizeof(struct nd_router_advert)) {
769                         syslog(LOG_NOTICE,
770                             "<%s> RA from %s on %s does not have enough "
771                             "length (len = %d)",
772                             __func__,
773                             inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
774                             INET6_ADDRSTRLEN),
775                             if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
776                         return;
777                 }
778                 ra_input(i, (struct nd_router_advert *)icp, pi, &rcvfrom);
779                 break;
780         case ICMP6_ROUTER_RENUMBERING:
781                 if (accept_rr == 0) {
782                         syslog(LOG_ERR, "<%s> received a router renumbering "
783                             "message, but not allowed to be accepted",
784                             __func__);
785                         break;
786                 }
787                 rr_input(i, (struct icmp6_router_renum *)icp, pi, &rcvfrom,
788                          &dst);
789                 break;
790         default:
791                 /*
792                  * Note that this case is POSSIBLE, especially just
793                  * after invocation of the daemon. This is because we
794                  * could receive message after opening the socket and
795                  * before setting ICMP6 type filter(see sock_open()).
796                  */
797                 syslog(LOG_ERR, "<%s> invalid icmp type(%d)",
798                     __func__, icp->icmp6_type);
799                 return;
800         }
801
802         return;
803 }
804
805 static void
806 rs_input(int len, struct nd_router_solicit *rs,
807          struct in6_pktinfo *pi, struct sockaddr_in6 *from)
808 {
809         u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
810         union nd_opts ndopts;
811         struct rainfo *ra;
812         struct soliciter *sol;
813
814         syslog(LOG_DEBUG,
815                "<%s> RS received from %s on %s",
816                __func__,
817                inet_ntop(AF_INET6, &from->sin6_addr,
818                          ntopbuf, INET6_ADDRSTRLEN),
819                if_indextoname(pi->ipi6_ifindex, ifnamebuf));
820
821         /* ND option check */
822         memset(&ndopts, 0, sizeof(ndopts));
823         if (nd6_options((struct nd_opt_hdr *)(rs + 1),
824                         len - sizeof(struct nd_router_solicit),
825                         &ndopts, NDOPT_FLAG_SRCLINKADDR)) {
826                 syslog(LOG_INFO,
827                        "<%s> ND option check failed for an RS from %s on %s",
828                        __func__,
829                        inet_ntop(AF_INET6, &from->sin6_addr,
830                                  ntopbuf, INET6_ADDRSTRLEN),
831                        if_indextoname(pi->ipi6_ifindex, ifnamebuf));
832                 return;
833         }
834
835         /*
836          * If the IP source address is the unspecified address, there
837          * must be no source link-layer address option in the message.
838          * (RFC-2461 6.1.1)
839          */
840         if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) &&
841             ndopts.nd_opts_src_lladdr) {
842                 syslog(LOG_INFO,
843                        "<%s> RS from unspecified src on %s has a link-layer"
844                        " address option",
845                        __func__,
846                        if_indextoname(pi->ipi6_ifindex, ifnamebuf));
847                 goto done;
848         }
849
850         ra = ralist;
851         while (ra != NULL) {
852                 if (pi->ipi6_ifindex == ra->ifindex)
853                         break;
854                 ra = ra->next;
855         }
856         if (ra == NULL) {
857                 syslog(LOG_INFO,
858                        "<%s> RS received on non advertising interface(%s)",
859                        __func__,
860                        if_indextoname(pi->ipi6_ifindex, ifnamebuf));
861                 goto done;
862         }
863
864         ra->rsinput++;          /* increment statistics */
865
866         /*
867          * Decide whether to send RA according to the rate-limit
868          * consideration.
869          */
870
871         /* record sockaddr waiting for RA, if possible */
872         sol = (struct soliciter *)malloc(sizeof(*sol));
873         if (sol) {
874                 sol->addr = *from;
875                 /* XXX RFC2553 need clarification on flowinfo */
876                 sol->addr.sin6_flowinfo = 0;
877                 sol->next = ra->soliciter;
878                 ra->soliciter = sol;
879         }
880
881         /*
882          * If there is already a waiting RS packet, don't
883          * update the timer.
884          */
885         if (ra->waiting++)
886                 goto done;
887
888         set_short_delay(ra);
889
890   done:
891         free_ndopts(&ndopts);
892         return;
893 }
894
895 static void
896 set_short_delay(rai)
897         struct rainfo *rai;
898 {
899         long delay;     /* must not be greater than 1000000 */
900         struct timeval interval, now, min_delay, tm_tmp, *rest;
901
902         /*
903          * Compute a random delay. If the computed value
904          * corresponds to a time later than the time the next
905          * multicast RA is scheduled to be sent, ignore the random
906          * delay and send the advertisement at the
907          * already-scheduled time. RFC-2461 6.2.6
908          */
909 #ifdef HAVE_ARC4RANDOM
910         delay = arc4random_uniform(MAX_RA_DELAY_TIME);
911 #else
912         delay = random() % MAX_RA_DELAY_TIME;
913 #endif
914         interval.tv_sec = 0;
915         interval.tv_usec = delay;
916         rest = rtadvd_timer_rest(rai->timer);
917         if (TIMEVAL_LT(*rest, interval)) {
918                 syslog(LOG_DEBUG, "<%s> random delay is larger than "
919                     "the rest of the current timer", __func__);
920                 interval = *rest;
921         }
922
923         /*
924          * If we sent a multicast Router Advertisement within
925          * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
926          * the advertisement to be sent at a time corresponding to
927          * MIN_DELAY_BETWEEN_RAS plus the random value after the
928          * previous advertisement was sent.
929          */
930         gettimeofday(&now, NULL);
931         TIMEVAL_SUB(&now, &rai->lastsent, &tm_tmp);
932         min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
933         min_delay.tv_usec = 0;
934         if (TIMEVAL_LT(tm_tmp, min_delay)) {
935                 TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay);
936                 TIMEVAL_ADD(&min_delay, &interval, &interval);
937         }
938         rtadvd_set_timer(&interval, rai->timer);
939 }
940
941 static void
942 ra_input(int len, struct nd_router_advert *ra,
943          struct in6_pktinfo *pi, struct sockaddr_in6 *from)
944 {
945         struct rainfo *rai;
946         u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
947         union nd_opts ndopts;
948         char *on_off[] = {"OFF", "ON"};
949         u_int32_t reachabletime, retranstimer, mtu;
950         int inconsistent = 0;
951
952         syslog(LOG_DEBUG,
953                "<%s> RA received from %s on %s",
954                __func__,
955                inet_ntop(AF_INET6, &from->sin6_addr,
956                          ntopbuf, INET6_ADDRSTRLEN),
957                if_indextoname(pi->ipi6_ifindex, ifnamebuf));
958         
959         /* ND option check */
960         memset(&ndopts, 0, sizeof(ndopts));
961         if (nd6_options((struct nd_opt_hdr *)(ra + 1),
962                         len - sizeof(struct nd_router_advert),
963                         &ndopts, NDOPT_FLAG_SRCLINKADDR |
964                         NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
965                 syslog(LOG_INFO,
966                        "<%s> ND option check failed for an RA from %s on %s",
967                        __func__,
968                        inet_ntop(AF_INET6, &from->sin6_addr,
969                                  ntopbuf, INET6_ADDRSTRLEN),
970                        if_indextoname(pi->ipi6_ifindex, ifnamebuf));
971                 return;
972         }
973
974         /*
975          * RA consistency check according to RFC-2461 6.2.7
976          */
977         if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == 0) {
978                 syslog(LOG_INFO,
979                        "<%s> received RA from %s on non-advertising"
980                        " interface(%s)",
981                        __func__,
982                        inet_ntop(AF_INET6, &from->sin6_addr,
983                                  ntopbuf, INET6_ADDRSTRLEN),
984                        if_indextoname(pi->ipi6_ifindex, ifnamebuf));
985                 goto done;
986         }
987         rai->rainput++;         /* increment statistics */
988         
989         /* Cur Hop Limit value */
990         if (ra->nd_ra_curhoplimit && rai->hoplimit &&
991             ra->nd_ra_curhoplimit != rai->hoplimit) {
992                 syslog(LOG_INFO,
993                        "<%s> CurHopLimit inconsistent on %s:"
994                        " %d from %s, %d from us",
995                        __func__,
996                        rai->ifname,
997                        ra->nd_ra_curhoplimit,
998                        inet_ntop(AF_INET6, &from->sin6_addr,
999                                  ntopbuf, INET6_ADDRSTRLEN),
1000                        rai->hoplimit);
1001                 inconsistent++;
1002         }
1003         /* M flag */
1004         if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
1005             rai->managedflg) {
1006                 syslog(LOG_INFO,
1007                        "<%s> M flag inconsistent on %s:"
1008                        " %s from %s, %s from us",
1009                        __func__,
1010                        rai->ifname,
1011                        on_off[!rai->managedflg],
1012                        inet_ntop(AF_INET6, &from->sin6_addr,
1013                                  ntopbuf, INET6_ADDRSTRLEN),
1014                        on_off[rai->managedflg]);
1015                 inconsistent++;
1016         }
1017         /* O flag */
1018         if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
1019             rai->otherflg) {
1020                 syslog(LOG_INFO,
1021                        "<%s> O flag inconsistent on %s:"
1022                        " %s from %s, %s from us",
1023                        __func__,
1024                        rai->ifname,
1025                        on_off[!rai->otherflg],
1026                        inet_ntop(AF_INET6, &from->sin6_addr,
1027                                  ntopbuf, INET6_ADDRSTRLEN),
1028                        on_off[rai->otherflg]);
1029                 inconsistent++;
1030         }
1031         /* Reachable Time */
1032         reachabletime = ntohl(ra->nd_ra_reachable);
1033         if (reachabletime && rai->reachabletime &&
1034             reachabletime != rai->reachabletime) {
1035                 syslog(LOG_INFO,
1036                        "<%s> ReachableTime inconsistent on %s:"
1037                        " %d from %s, %d from us",
1038                        __func__,
1039                        rai->ifname,
1040                        reachabletime,
1041                        inet_ntop(AF_INET6, &from->sin6_addr,
1042                                  ntopbuf, INET6_ADDRSTRLEN),
1043                        rai->reachabletime);
1044                 inconsistent++;
1045         }
1046         /* Retrans Timer */
1047         retranstimer = ntohl(ra->nd_ra_retransmit);
1048         if (retranstimer && rai->retranstimer &&
1049             retranstimer != rai->retranstimer) {
1050                 syslog(LOG_INFO,
1051                        "<%s> RetranceTimer inconsistent on %s:"
1052                        " %d from %s, %d from us",
1053                        __func__,
1054                        rai->ifname,
1055                        retranstimer,
1056                        inet_ntop(AF_INET6, &from->sin6_addr,
1057                                  ntopbuf, INET6_ADDRSTRLEN),
1058                        rai->retranstimer);
1059                 inconsistent++;
1060         }
1061         /* Values in the MTU options */
1062         if (ndopts.nd_opts_mtu) {
1063                 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
1064                 if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
1065                         syslog(LOG_INFO,
1066                                "<%s> MTU option value inconsistent on %s:"
1067                                " %d from %s, %d from us",
1068                                __func__,
1069                                rai->ifname, mtu,
1070                                inet_ntop(AF_INET6, &from->sin6_addr,
1071                                          ntopbuf, INET6_ADDRSTRLEN),
1072                                rai->linkmtu);
1073                         inconsistent++;
1074                 }
1075         }
1076         /* Preferred and Valid Lifetimes for prefixes */
1077         {
1078                 struct nd_optlist *optp = ndopts.nd_opts_list;
1079
1080                 if (ndopts.nd_opts_pi) {
1081                         if (prefix_check(ndopts.nd_opts_pi, rai, from))
1082                                 inconsistent++;
1083                 }
1084                 while (optp) {
1085                         if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
1086                                          rai, from))
1087                                 inconsistent++;
1088                         optp = optp->next;
1089                 }
1090         }
1091
1092         if (inconsistent)
1093                 rai->rainconsistent++;
1094         
1095   done:
1096         free_ndopts(&ndopts);
1097         return;
1098 }
1099
1100 /* return a non-zero value if the received prefix is inconsitent with ours */
1101 static int
1102 prefix_check(struct nd_opt_prefix_info *pinfo,
1103              struct rainfo *rai, struct sockaddr_in6 *from)
1104 {
1105         u_int32_t preferred_time, valid_time;
1106         struct prefix *pp;
1107         int inconsistent = 0;
1108         u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
1109         struct timeval now;
1110
1111 #if 0                           /* impossible */
1112         if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
1113                 return(0);
1114 #endif
1115
1116         /*
1117          * log if the adveritsed prefix has link-local scope(sanity check?)
1118          */
1119         if (IN6_IS_ADDR_LINKLOCAL(&pinfo->nd_opt_pi_prefix)) {
1120                 syslog(LOG_INFO,
1121                        "<%s> link-local prefix %s/%d is advertised "
1122                        "from %s on %s",
1123                        __func__,
1124                        inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1125                                  prefixbuf, INET6_ADDRSTRLEN),
1126                        pinfo->nd_opt_pi_prefix_len,
1127                        inet_ntop(AF_INET6, &from->sin6_addr,
1128                                  ntopbuf, INET6_ADDRSTRLEN),
1129                        rai->ifname);
1130         }
1131
1132         if ((pp = find_prefix(rai, &pinfo->nd_opt_pi_prefix,
1133                               pinfo->nd_opt_pi_prefix_len)) == NULL) {
1134                 syslog(LOG_INFO,
1135                        "<%s> prefix %s/%d from %s on %s is not in our list",
1136                        __func__,
1137                        inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1138                                  prefixbuf, INET6_ADDRSTRLEN),
1139                        pinfo->nd_opt_pi_prefix_len,
1140                        inet_ntop(AF_INET6, &from->sin6_addr,
1141                                  ntopbuf, INET6_ADDRSTRLEN),
1142                        rai->ifname);
1143                 return(0);
1144         }
1145
1146         preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
1147         if (pp->pltimeexpire) {
1148                 /*
1149                  * The lifetime is decremented in real time, so we should
1150                  * compare the expiration time.
1151                  * (RFC 2461 Section 6.2.7.)
1152                  * XXX: can we really expect that all routers on the link
1153                  * have synchronized clocks?
1154                  */
1155                 gettimeofday(&now, NULL);
1156                 preferred_time += now.tv_sec;
1157
1158                 if (!pp->timer && rai->clockskew &&
1159                     abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
1160                         syslog(LOG_INFO,
1161                                "<%s> preferred lifetime for %s/%d"
1162                                " (decr. in real time) inconsistent on %s:"
1163                                " %d from %s, %ld from us",
1164                                __func__,
1165                                inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1166                                          prefixbuf, INET6_ADDRSTRLEN),
1167                                pinfo->nd_opt_pi_prefix_len,
1168                                rai->ifname, preferred_time,
1169                                inet_ntop(AF_INET6, &from->sin6_addr,
1170                                          ntopbuf, INET6_ADDRSTRLEN),
1171                                pp->pltimeexpire);
1172                         inconsistent++;
1173                 }
1174         } else if (!pp->timer && preferred_time != pp->preflifetime) {
1175                 syslog(LOG_INFO,
1176                        "<%s> preferred lifetime for %s/%d"
1177                        " inconsistent on %s:"
1178                        " %d from %s, %d from us",
1179                        __func__,
1180                        inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1181                                  prefixbuf, INET6_ADDRSTRLEN),
1182                        pinfo->nd_opt_pi_prefix_len,
1183                        rai->ifname, preferred_time,
1184                        inet_ntop(AF_INET6, &from->sin6_addr,
1185                                  ntopbuf, INET6_ADDRSTRLEN),
1186                        pp->preflifetime);
1187         }
1188
1189         valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
1190         if (pp->vltimeexpire) {
1191                 gettimeofday(&now, NULL);
1192                 valid_time += now.tv_sec;
1193
1194                 if (!pp->timer && rai->clockskew &&
1195                     abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
1196                         syslog(LOG_INFO,
1197                                "<%s> valid lifetime for %s/%d"
1198                                " (decr. in real time) inconsistent on %s:"
1199                                " %d from %s, %ld from us",
1200                                __func__,
1201                                inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1202                                          prefixbuf, INET6_ADDRSTRLEN),
1203                                pinfo->nd_opt_pi_prefix_len,
1204                                rai->ifname, preferred_time,
1205                                inet_ntop(AF_INET6, &from->sin6_addr,
1206                                          ntopbuf, INET6_ADDRSTRLEN),
1207                                pp->vltimeexpire);
1208                         inconsistent++;
1209                 }
1210         } else if (!pp->timer && valid_time != pp->validlifetime) {
1211                 syslog(LOG_INFO,
1212                        "<%s> valid lifetime for %s/%d"
1213                        " inconsistent on %s:"
1214                        " %d from %s, %d from us",
1215                        __func__,
1216                        inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1217                                  prefixbuf, INET6_ADDRSTRLEN),
1218                        pinfo->nd_opt_pi_prefix_len,
1219                        rai->ifname, valid_time,
1220                        inet_ntop(AF_INET6, &from->sin6_addr,
1221                                  ntopbuf, INET6_ADDRSTRLEN),
1222                        pp->validlifetime);
1223                 inconsistent++;
1224         }
1225
1226         return(inconsistent);
1227 }
1228
1229 struct prefix *
1230 find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
1231 {
1232         struct prefix *pp;
1233         int bytelen, bitlen;
1234         u_char bitmask;
1235
1236         for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) {
1237                 if (plen != pp->prefixlen)
1238                         continue;
1239                 bytelen = plen / 8;
1240                 bitlen = plen % 8;
1241                 bitmask = 0xff << (8 - bitlen);
1242                 if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen))
1243                         continue;
1244                 if (bitlen == 0 ||
1245                     ((prefix->s6_addr[bytelen] & bitmask) == 
1246                      (pp->prefix.s6_addr[bytelen] & bitmask))) {
1247                         return(pp);
1248                 }
1249         }
1250
1251         return(NULL);
1252 }
1253
1254 /* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */
1255 int
1256 prefix_match(struct in6_addr *p0, int plen0,
1257              struct in6_addr *p1, int plen1)
1258 {
1259         int bytelen, bitlen;
1260         u_char bitmask;
1261
1262         if (plen0 < plen1)
1263                 return(0);
1264         bytelen = plen1 / 8;
1265         bitlen = plen1 % 8;
1266         bitmask = 0xff << (8 - bitlen);
1267         if (memcmp((void *)p0, (void *)p1, bytelen))
1268                 return(0);
1269         if (bitlen == 0 ||
1270             ((p0->s6_addr[bytelen] & bitmask) ==
1271              (p1->s6_addr[bytelen] & bitmask))) {
1272                 return(1);
1273         }
1274
1275         return(0);
1276 }
1277
1278 static int
1279 nd6_options(struct nd_opt_hdr *hdr, int limit,
1280             union nd_opts *ndopts, u_int32_t optflags)
1281 {
1282         int optlen = 0;
1283
1284         for (; limit > 0; limit -= optlen) {
1285                 if (limit < sizeof(struct nd_opt_hdr)) {
1286                         syslog(LOG_INFO, "<%s> short option header", __func__);
1287                         goto bad;
1288                 }
1289
1290                 hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen);
1291                 if (hdr->nd_opt_len == 0) {
1292                         syslog(LOG_INFO,
1293                             "<%s> bad ND option length(0) (type = %d)",
1294                             __func__, hdr->nd_opt_type);
1295                         goto bad;
1296                 }
1297                 optlen = hdr->nd_opt_len << 3;
1298                 if (optlen > limit) {
1299                         syslog(LOG_INFO, "<%s> short option", __func__);
1300                         goto bad;
1301                 }
1302
1303                 if (hdr->nd_opt_type > ND_OPT_MTU) {
1304                         syslog(LOG_INFO, "<%s> unknown ND option(type %d)",
1305                             __func__, hdr->nd_opt_type);
1306                         continue;
1307                 }
1308
1309                 if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
1310                         syslog(LOG_INFO, "<%s> unexpected ND option(type %d)",
1311                             __func__, hdr->nd_opt_type);
1312                         continue;
1313                 }
1314
1315                 /*
1316                  * Option length check.  Do it here for all fixed-length
1317                  * options.
1318                  */
1319                 if ((hdr->nd_opt_type == ND_OPT_MTU &&
1320                     (optlen != sizeof(struct nd_opt_mtu))) ||
1321                     ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
1322                     optlen != sizeof(struct nd_opt_prefix_info)))) {
1323                         syslog(LOG_INFO, "<%s> invalid option length",
1324                             __func__);
1325                         continue;
1326                 }
1327
1328                 switch (hdr->nd_opt_type) {
1329                 case ND_OPT_TARGET_LINKADDR:
1330                 case ND_OPT_REDIRECTED_HEADER:
1331                         break;  /* we don't care about these options */
1332                 case ND_OPT_SOURCE_LINKADDR:
1333                 case ND_OPT_MTU:
1334                         if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
1335                                 syslog(LOG_INFO,
1336                                     "<%s> duplicated ND option (type = %d)",
1337                                     __func__, hdr->nd_opt_type);
1338                         }
1339                         ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
1340                         break;
1341                 case ND_OPT_PREFIX_INFORMATION:
1342                 {
1343                         struct nd_optlist *pfxlist;
1344
1345                         if (ndopts->nd_opts_pi == 0) {
1346                                 ndopts->nd_opts_pi =
1347                                     (struct nd_opt_prefix_info *)hdr;
1348                                 continue;
1349                         }
1350                         if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) {
1351                                 syslog(LOG_ERR, "<%s> can't allocate memory",
1352                                     __func__);
1353                                 goto bad;
1354                         }
1355                         pfxlist->next = ndopts->nd_opts_list;
1356                         pfxlist->opt = hdr;
1357                         ndopts->nd_opts_list = pfxlist;
1358
1359                         break;
1360                 }
1361                 default:        /* impossible */
1362                         break;
1363                 }
1364         }
1365
1366         return(0);
1367
1368   bad:
1369         free_ndopts(ndopts);
1370
1371         return(-1);
1372 }
1373
1374 static void
1375 free_ndopts(union nd_opts *ndopts)
1376 {
1377         struct nd_optlist *opt = ndopts->nd_opts_list, *next;
1378
1379         while (opt) {
1380                 next = opt->next;
1381                 free(opt);
1382                 opt = next;
1383         }
1384 }
1385
1386 void
1387 sock_open()
1388 {
1389         struct icmp6_filter filt;
1390         struct ipv6_mreq mreq;
1391         struct rainfo *ra = ralist;
1392         int on;
1393         /* XXX: should be max MTU attached to the node */
1394         static u_char answer[1500];
1395
1396         rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1397                                 CMSG_SPACE(sizeof(int));
1398         rcvcmsgbuf = (u_char *)malloc(rcvcmsgbuflen);
1399         if (rcvcmsgbuf == NULL) {
1400                 syslog(LOG_ERR, "<%s> not enough core", __func__);
1401                 exit(1);
1402         }
1403
1404         sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 
1405                                 CMSG_SPACE(sizeof(int));
1406         sndcmsgbuf = (u_char *)malloc(sndcmsgbuflen);
1407         if (sndcmsgbuf == NULL) {
1408                 syslog(LOG_ERR, "<%s> not enough core", __func__);
1409                 exit(1);
1410         }
1411
1412         if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
1413                 syslog(LOG_ERR, "<%s> socket: %s", __func__,
1414                        strerror(errno));
1415                 exit(1);
1416         }
1417
1418         /* specify to tell receiving interface */
1419         on = 1;
1420 #ifdef IPV6_RECVPKTINFO
1421         if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
1422                        sizeof(on)) < 0) {
1423                 syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s",
1424                        __func__, strerror(errno));
1425                 exit(1);
1426         }
1427 #else  /* old adv. API */
1428         if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
1429                        sizeof(on)) < 0) {
1430                 syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s",
1431                        __func__, strerror(errno));
1432                 exit(1);
1433         }
1434 #endif 
1435
1436         on = 1;
1437         /* specify to tell value of hoplimit field of received IP6 hdr */
1438 #ifdef IPV6_RECVHOPLIMIT
1439         if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
1440                        sizeof(on)) < 0) {
1441                 syslog(LOG_ERR, "<%s> IPV6_RECVHOPLIMIT: %s",
1442                        __func__, strerror(errno));
1443                 exit(1);
1444         }
1445 #else  /* old adv. API */
1446         if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
1447                        sizeof(on)) < 0) {
1448                 syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s",
1449                        __func__, strerror(errno));
1450                 exit(1);
1451         }
1452 #endif
1453
1454         ICMP6_FILTER_SETBLOCKALL(&filt);
1455         ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
1456         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
1457         if (accept_rr)
1458                 ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
1459         if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
1460                        sizeof(filt)) < 0) {
1461                 syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
1462                        __func__, strerror(errno));
1463                 exit(1);
1464         }
1465
1466         /*
1467          * join all routers multicast address on each advertising interface.
1468          */
1469         if (inet_pton(AF_INET6, ALLROUTERS_LINK,
1470                       &mreq.ipv6mr_multiaddr.s6_addr)
1471             != 1) {
1472                 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1473                        __func__);
1474                 exit(1);
1475         }
1476         while (ra) {
1477                 mreq.ipv6mr_interface = ra->ifindex;
1478                 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
1479                                sizeof(mreq)) < 0) {
1480                         syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
1481                                __func__, ra->ifname, strerror(errno));
1482                         exit(1);
1483                 }
1484                 ra = ra->next;
1485         }
1486
1487         /*
1488          * When attending router renumbering, join all-routers site-local
1489          * multicast group. 
1490          */
1491         if (accept_rr) {
1492                 if (inet_pton(AF_INET6, ALLROUTERS_SITE,
1493                               &in6a_site_allrouters) != 1) {
1494                         syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1495                                __func__);
1496                         exit(1);
1497                 }
1498                 mreq.ipv6mr_multiaddr = in6a_site_allrouters;
1499                 if (mcastif) {
1500                         if ((mreq.ipv6mr_interface = if_nametoindex(mcastif))
1501                             == 0) {
1502                                 syslog(LOG_ERR,
1503                                        "<%s> invalid interface: %s",
1504                                        __func__, mcastif);
1505                                 exit(1);
1506                         }
1507                 } else
1508                         mreq.ipv6mr_interface = ralist->ifindex;
1509                 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1510                                &mreq, sizeof(mreq)) < 0) {
1511                         syslog(LOG_ERR,
1512                                "<%s> IPV6_JOIN_GROUP(site) on %s: %s",
1513                                __func__,
1514                                mcastif ? mcastif : ralist->ifname,
1515                                strerror(errno));
1516                         exit(1);
1517                 }
1518         }
1519         
1520         /* initialize msghdr for receiving packets */
1521         rcviov[0].iov_base = (caddr_t)answer;
1522         rcviov[0].iov_len = sizeof(answer);
1523         rcvmhdr.msg_name = (caddr_t)&rcvfrom;
1524         rcvmhdr.msg_namelen = sizeof(rcvfrom);
1525         rcvmhdr.msg_iov = rcviov;
1526         rcvmhdr.msg_iovlen = 1;
1527         rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
1528         rcvmhdr.msg_controllen = rcvcmsgbuflen;
1529
1530         /* initialize msghdr for sending packets */
1531         sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
1532         sndmhdr.msg_iov = sndiov;
1533         sndmhdr.msg_iovlen = 1;
1534         sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
1535         sndmhdr.msg_controllen = sndcmsgbuflen;
1536         
1537         return;
1538 }
1539
1540 /* open a routing socket to watch the routing table */
1541 static void
1542 rtsock_open()
1543 {
1544         if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
1545                 syslog(LOG_ERR,
1546                        "<%s> socket: %s", __func__, strerror(errno));
1547                 exit(1);
1548         }
1549 }
1550
1551 struct rainfo *
1552 if_indextorainfo(int idx)
1553 {
1554         struct rainfo *rai = ralist;
1555
1556         for (rai = ralist; rai; rai = rai->next) {
1557                 if (rai->ifindex == idx)
1558                         return(rai);
1559         }
1560
1561         return(NULL);           /* search failed */
1562 }
1563
1564 static void
1565 ra_output(rainfo)
1566 struct rainfo *rainfo;
1567 {
1568         int i;
1569         struct cmsghdr *cm;
1570         struct in6_pktinfo *pi;
1571         struct soliciter *sol, *nextsol;
1572
1573         if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
1574                 syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
1575                        __func__, rainfo->ifname);
1576                 return;
1577         }
1578
1579         make_packet(rainfo);    /* XXX: inefficient */
1580
1581         sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
1582         sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
1583         sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
1584
1585         cm = CMSG_FIRSTHDR(&sndmhdr);
1586         /* specify the outgoing interface */
1587         cm->cmsg_level = IPPROTO_IPV6;
1588         cm->cmsg_type = IPV6_PKTINFO;
1589         cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1590         pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1591         memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));       /*XXX*/
1592         pi->ipi6_ifindex = rainfo->ifindex;
1593
1594         /* specify the hop limit of the packet */
1595         {
1596                 int hoplimit = 255;
1597
1598                 cm = CMSG_NXTHDR(&sndmhdr, cm);
1599                 cm->cmsg_level = IPPROTO_IPV6;
1600                 cm->cmsg_type = IPV6_HOPLIMIT;
1601                 cm->cmsg_len = CMSG_LEN(sizeof(int));
1602                 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1603         }
1604
1605         syslog(LOG_DEBUG,
1606                "<%s> send RA on %s, # of waitings = %d",
1607                __func__, rainfo->ifname, rainfo->waiting); 
1608
1609         i = sendmsg(sock, &sndmhdr, 0);
1610
1611         if (i < 0 || i != rainfo->ra_datalen)  {
1612                 if (i < 0) {
1613                         syslog(LOG_ERR, "<%s> sendmsg on %s: %s",
1614                                __func__, rainfo->ifname,
1615                                strerror(errno));
1616                 }
1617         }
1618         /* update counter */
1619         if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
1620                 rainfo->initcounter++;
1621         rainfo->raoutput++;
1622
1623         /*
1624          * unicast advertisements
1625          * XXX commented out.  reason: though spec does not forbit it, unicast
1626          * advert does not really help
1627          */
1628         for (sol = rainfo->soliciter; sol; sol = nextsol) {
1629                 nextsol = sol->next;
1630
1631                 sol->next = NULL;
1632                 free(sol);
1633         }
1634         rainfo->soliciter = NULL;
1635
1636         /* update timestamp */
1637         gettimeofday(&rainfo->lastsent, NULL);
1638
1639         /* reset waiting conter */
1640         rainfo->waiting = 0;
1641 }
1642
1643 /* process RA timer */
1644 struct rtadvd_timer *
1645 ra_timeout(void *data)
1646 {
1647         struct rainfo *rai = (struct rainfo *)data;
1648
1649 #ifdef notyet
1650         /* if necessary, reconstruct the packet. */
1651 #endif
1652
1653         syslog(LOG_DEBUG,
1654                "<%s> RA timer on %s is expired",
1655                __func__, rai->ifname);
1656
1657         ra_output(rai);
1658
1659         return(rai->timer);
1660 }
1661
1662 /* update RA timer */
1663 void
1664 ra_timer_update(void *data, struct timeval *tm)
1665 {
1666         struct rainfo *rai = (struct rainfo *)data;
1667         long interval;
1668
1669         /*
1670          * Whenever a multicast advertisement is sent from an interface,
1671          * the timer is reset to a uniformly-distributed random value
1672          * between the interface's configured MinRtrAdvInterval and
1673          * MaxRtrAdvInterval (RFC2461 6.2.4).
1674          */
1675         interval = rai->mininterval; 
1676 #ifdef HAVE_ARC4RANDOM
1677         interval += arc4random_uniform(rai->maxinterval - rai->mininterval);
1678 #else
1679         interval += random() % (rai->maxinterval - rai->mininterval);
1680 #endif
1681
1682         /*
1683          * For the first few advertisements (up to
1684          * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
1685          * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer
1686          * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
1687          * (RFC-2461 6.2.4)
1688          */
1689         if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS &&
1690             interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)
1691                 interval = MAX_INITIAL_RTR_ADVERT_INTERVAL;
1692
1693         tm->tv_sec = interval;
1694         tm->tv_usec = 0;
1695
1696         syslog(LOG_DEBUG,
1697                "<%s> RA timer on %s is set to %ld:%ld",
1698                __func__, rai->ifname,
1699                (long int)tm->tv_sec, (long int)tm->tv_usec);
1700
1701         return;
1702 }