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