xref: /freebsd/usr.sbin/rtadvd/rtadvd.c (revision 10b9d77bf1ccf2f3affafa6261692cb92cf7e992)
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 down,
671 	 * just discard the data.
672 	 */
673 	if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
674 		syslog(LOG_INFO,
675 		       "<%s> received data on a disabled interface (%s)",
676 		       __func__,
677 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
678 		return;
679 	}
680 
681 #ifdef OLDRAWSOCKET
682 	if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) {
683 		syslog(LOG_ERR,
684 		       "<%s> packet size(%d) is too short",
685 		       __func__, i);
686 		return;
687 	}
688 
689 	ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base;
690 	icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */
691 #else
692 	if (i < sizeof(struct icmp6_hdr)) {
693 		syslog(LOG_ERR,
694 		       "<%s> packet size(%d) is too short",
695 		       __func__, i);
696 		return;
697 	}
698 
699 	icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
700 #endif
701 
702 	switch (icp->icmp6_type) {
703 	case ND_ROUTER_SOLICIT:
704 		/*
705 		 * Message verification - RFC-2461 6.1.1
706 		 * XXX: these checks must be done in the kernel as well,
707 		 *      but we can't completely rely on them.
708 		 */
709 		if (*hlimp != 255) {
710 			syslog(LOG_NOTICE,
711 			    "<%s> RS with invalid hop limit(%d) "
712 			    "received from %s on %s",
713 			    __func__, *hlimp,
714 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
715 			    INET6_ADDRSTRLEN),
716 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
717 			return;
718 		}
719 		if (icp->icmp6_code) {
720 			syslog(LOG_NOTICE,
721 			    "<%s> RS with invalid ICMP6 code(%d) "
722 			    "received from %s on %s",
723 			    __func__, icp->icmp6_code,
724 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
725 			    INET6_ADDRSTRLEN),
726 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
727 			return;
728 		}
729 		if (i < sizeof(struct nd_router_solicit)) {
730 			syslog(LOG_NOTICE,
731 			    "<%s> RS from %s on %s does not have enough "
732 			    "length (len = %d)",
733 			    __func__,
734 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
735 			    INET6_ADDRSTRLEN),
736 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
737 			return;
738 		}
739 		rs_input(i, (struct nd_router_solicit *)icp, pi, &rcvfrom);
740 		break;
741 	case ND_ROUTER_ADVERT:
742 		/*
743 		 * Message verification - RFC-2461 6.1.2
744 		 * XXX: there's a same dilemma as above...
745 		 */
746 		if (*hlimp != 255) {
747 			syslog(LOG_NOTICE,
748 			    "<%s> RA with invalid hop limit(%d) "
749 			    "received from %s on %s",
750 			    __func__, *hlimp,
751 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
752 			    INET6_ADDRSTRLEN),
753 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
754 			return;
755 		}
756 		if (icp->icmp6_code) {
757 			syslog(LOG_NOTICE,
758 			    "<%s> RA with invalid ICMP6 code(%d) "
759 			    "received from %s on %s",
760 			    __func__, icp->icmp6_code,
761 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
762 			    INET6_ADDRSTRLEN),
763 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
764 			return;
765 		}
766 		if (i < sizeof(struct nd_router_advert)) {
767 			syslog(LOG_NOTICE,
768 			    "<%s> RA from %s on %s does not have enough "
769 			    "length (len = %d)",
770 			    __func__,
771 			    inet_ntop(AF_INET6, &rcvfrom.sin6_addr, ntopbuf,
772 			    INET6_ADDRSTRLEN),
773 			    if_indextoname(pi->ipi6_ifindex, ifnamebuf), i);
774 			return;
775 		}
776 		ra_input(i, (struct nd_router_advert *)icp, pi, &rcvfrom);
777 		break;
778 	case ICMP6_ROUTER_RENUMBERING:
779 		if (accept_rr == 0) {
780 			syslog(LOG_ERR, "<%s> received a router renumbering "
781 			    "message, but not allowed to be accepted",
782 			    __func__);
783 			break;
784 		}
785 		rr_input(i, (struct icmp6_router_renum *)icp, pi, &rcvfrom,
786 			 &dst);
787 		break;
788 	default:
789 		/*
790 		 * Note that this case is POSSIBLE, especially just
791 		 * after invocation of the daemon. This is because we
792 		 * could receive message after opening the socket and
793 		 * before setting ICMP6 type filter(see sock_open()).
794 		 */
795 		syslog(LOG_ERR, "<%s> invalid icmp type(%d)",
796 		    __func__, icp->icmp6_type);
797 		return;
798 	}
799 
800 	return;
801 }
802 
803 static void
804 rs_input(int len, struct nd_router_solicit *rs,
805 	 struct in6_pktinfo *pi, struct sockaddr_in6 *from)
806 {
807 	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
808 	union nd_opts ndopts;
809 	struct rainfo *ra;
810 	struct soliciter *sol;
811 
812 	syslog(LOG_DEBUG,
813 	       "<%s> RS received from %s on %s",
814 	       __func__,
815 	       inet_ntop(AF_INET6, &from->sin6_addr,
816 			 ntopbuf, INET6_ADDRSTRLEN),
817 	       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
818 
819 	/* ND option check */
820 	memset(&ndopts, 0, sizeof(ndopts));
821 	if (nd6_options((struct nd_opt_hdr *)(rs + 1),
822 			len - sizeof(struct nd_router_solicit),
823 			&ndopts, NDOPT_FLAG_SRCLINKADDR)) {
824 		syslog(LOG_INFO,
825 		       "<%s> ND option check failed for an RS from %s on %s",
826 		       __func__,
827 		       inet_ntop(AF_INET6, &from->sin6_addr,
828 				 ntopbuf, INET6_ADDRSTRLEN),
829 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
830 		return;
831 	}
832 
833 	/*
834 	 * If the IP source address is the unspecified address, there
835 	 * must be no source link-layer address option in the message.
836 	 * (RFC-2461 6.1.1)
837 	 */
838 	if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) &&
839 	    ndopts.nd_opts_src_lladdr) {
840 		syslog(LOG_INFO,
841 		       "<%s> RS from unspecified src on %s has a link-layer"
842 		       " address option",
843 		       __func__,
844 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
845 		goto done;
846 	}
847 
848 	ra = ralist;
849 	while (ra != NULL) {
850 		if (pi->ipi6_ifindex == ra->ifindex)
851 			break;
852 		ra = ra->next;
853 	}
854 	if (ra == NULL) {
855 		syslog(LOG_INFO,
856 		       "<%s> RS received on non advertising interface(%s)",
857 		       __func__,
858 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
859 		goto done;
860 	}
861 
862 	ra->rsinput++;		/* increment statistics */
863 
864 	/*
865 	 * Decide whether to send RA according to the rate-limit
866 	 * consideration.
867 	 */
868 
869 	/* record sockaddr waiting for RA, if possible */
870 	sol = (struct soliciter *)malloc(sizeof(*sol));
871 	if (sol) {
872 		sol->addr = *from;
873 		/* XXX RFC2553 need clarification on flowinfo */
874 		sol->addr.sin6_flowinfo = 0;
875 		sol->next = ra->soliciter;
876 		ra->soliciter = sol;
877 	}
878 
879 	/*
880 	 * If there is already a waiting RS packet, don't
881 	 * update the timer.
882 	 */
883 	if (ra->waiting++)
884 		goto done;
885 
886 	set_short_delay(ra);
887 
888   done:
889 	free_ndopts(&ndopts);
890 	return;
891 }
892 
893 static void
894 set_short_delay(rai)
895 	struct rainfo *rai;
896 {
897 	long delay;	/* must not be greater than 1000000 */
898 	struct timeval interval, now, min_delay, tm_tmp, *rest;
899 
900 	/*
901 	 * Compute a random delay. If the computed value
902 	 * corresponds to a time later than the time the next
903 	 * multicast RA is scheduled to be sent, ignore the random
904 	 * delay and send the advertisement at the
905 	 * already-scheduled time. RFC-2461 6.2.6
906 	 */
907 #ifdef HAVE_ARC4RANDOM
908 	delay = arc4random_uniform(MAX_RA_DELAY_TIME);
909 #else
910 	delay = random() % MAX_RA_DELAY_TIME;
911 #endif
912 	interval.tv_sec = 0;
913 	interval.tv_usec = delay;
914 	rest = rtadvd_timer_rest(rai->timer);
915 	if (TIMEVAL_LT(*rest, interval)) {
916 		syslog(LOG_DEBUG, "<%s> random delay is larger than "
917 		    "the rest of the current timer", __func__);
918 		interval = *rest;
919 	}
920 
921 	/*
922 	 * If we sent a multicast Router Advertisement within
923 	 * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
924 	 * the advertisement to be sent at a time corresponding to
925 	 * MIN_DELAY_BETWEEN_RAS plus the random value after the
926 	 * previous advertisement was sent.
927 	 */
928 	gettimeofday(&now, NULL);
929 	TIMEVAL_SUB(&now, &rai->lastsent, &tm_tmp);
930 	min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
931 	min_delay.tv_usec = 0;
932 	if (TIMEVAL_LT(tm_tmp, min_delay)) {
933 		TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay);
934 		TIMEVAL_ADD(&min_delay, &interval, &interval);
935 	}
936 	rtadvd_set_timer(&interval, rai->timer);
937 }
938 
939 static void
940 ra_input(int len, struct nd_router_advert *ra,
941 	 struct in6_pktinfo *pi, struct sockaddr_in6 *from)
942 {
943 	struct rainfo *rai;
944 	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
945 	union nd_opts ndopts;
946 	char *on_off[] = {"OFF", "ON"};
947 	u_int32_t reachabletime, retranstimer, mtu;
948 	int inconsistent = 0;
949 
950 	syslog(LOG_DEBUG,
951 	       "<%s> RA received from %s on %s",
952 	       __func__,
953 	       inet_ntop(AF_INET6, &from->sin6_addr,
954 			 ntopbuf, INET6_ADDRSTRLEN),
955 	       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
956 
957 	/* ND option check */
958 	memset(&ndopts, 0, sizeof(ndopts));
959 	if (nd6_options((struct nd_opt_hdr *)(ra + 1),
960 			len - sizeof(struct nd_router_advert),
961 			&ndopts, NDOPT_FLAG_SRCLINKADDR |
962 			NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) {
963 		syslog(LOG_INFO,
964 		       "<%s> ND option check failed for an RA from %s on %s",
965 		       __func__,
966 		       inet_ntop(AF_INET6, &from->sin6_addr,
967 				 ntopbuf, INET6_ADDRSTRLEN),
968 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
969 		return;
970 	}
971 
972 	/*
973 	 * RA consistency check according to RFC-2461 6.2.7
974 	 */
975 	if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == 0) {
976 		syslog(LOG_INFO,
977 		       "<%s> received RA from %s on non-advertising"
978 		       " interface(%s)",
979 		       __func__,
980 		       inet_ntop(AF_INET6, &from->sin6_addr,
981 				 ntopbuf, INET6_ADDRSTRLEN),
982 		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
983 		goto done;
984 	}
985 	rai->rainput++;		/* increment statistics */
986 
987 	/* Cur Hop Limit value */
988 	if (ra->nd_ra_curhoplimit && rai->hoplimit &&
989 	    ra->nd_ra_curhoplimit != rai->hoplimit) {
990 		syslog(LOG_INFO,
991 		       "<%s> CurHopLimit inconsistent on %s:"
992 		       " %d from %s, %d from us",
993 		       __func__,
994 		       rai->ifname,
995 		       ra->nd_ra_curhoplimit,
996 		       inet_ntop(AF_INET6, &from->sin6_addr,
997 				 ntopbuf, INET6_ADDRSTRLEN),
998 		       rai->hoplimit);
999 		inconsistent++;
1000 	}
1001 	/* M flag */
1002 	if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
1003 	    rai->managedflg) {
1004 		syslog(LOG_INFO,
1005 		       "<%s> M flag inconsistent on %s:"
1006 		       " %s from %s, %s from us",
1007 		       __func__,
1008 		       rai->ifname,
1009 		       on_off[!rai->managedflg],
1010 		       inet_ntop(AF_INET6, &from->sin6_addr,
1011 				 ntopbuf, INET6_ADDRSTRLEN),
1012 		       on_off[rai->managedflg]);
1013 		inconsistent++;
1014 	}
1015 	/* O flag */
1016 	if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
1017 	    rai->otherflg) {
1018 		syslog(LOG_INFO,
1019 		       "<%s> O flag inconsistent on %s:"
1020 		       " %s from %s, %s from us",
1021 		       __func__,
1022 		       rai->ifname,
1023 		       on_off[!rai->otherflg],
1024 		       inet_ntop(AF_INET6, &from->sin6_addr,
1025 				 ntopbuf, INET6_ADDRSTRLEN),
1026 		       on_off[rai->otherflg]);
1027 		inconsistent++;
1028 	}
1029 	/* Reachable Time */
1030 	reachabletime = ntohl(ra->nd_ra_reachable);
1031 	if (reachabletime && rai->reachabletime &&
1032 	    reachabletime != rai->reachabletime) {
1033 		syslog(LOG_INFO,
1034 		       "<%s> ReachableTime inconsistent on %s:"
1035 		       " %d from %s, %d from us",
1036 		       __func__,
1037 		       rai->ifname,
1038 		       reachabletime,
1039 		       inet_ntop(AF_INET6, &from->sin6_addr,
1040 				 ntopbuf, INET6_ADDRSTRLEN),
1041 		       rai->reachabletime);
1042 		inconsistent++;
1043 	}
1044 	/* Retrans Timer */
1045 	retranstimer = ntohl(ra->nd_ra_retransmit);
1046 	if (retranstimer && rai->retranstimer &&
1047 	    retranstimer != rai->retranstimer) {
1048 		syslog(LOG_INFO,
1049 		       "<%s> RetranceTimer inconsistent on %s:"
1050 		       " %d from %s, %d from us",
1051 		       __func__,
1052 		       rai->ifname,
1053 		       retranstimer,
1054 		       inet_ntop(AF_INET6, &from->sin6_addr,
1055 				 ntopbuf, INET6_ADDRSTRLEN),
1056 		       rai->retranstimer);
1057 		inconsistent++;
1058 	}
1059 	/* Values in the MTU options */
1060 	if (ndopts.nd_opts_mtu) {
1061 		mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
1062 		if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
1063 			syslog(LOG_INFO,
1064 			       "<%s> MTU option value inconsistent on %s:"
1065 			       " %d from %s, %d from us",
1066 			       __func__,
1067 			       rai->ifname, mtu,
1068 			       inet_ntop(AF_INET6, &from->sin6_addr,
1069 					 ntopbuf, INET6_ADDRSTRLEN),
1070 			       rai->linkmtu);
1071 			inconsistent++;
1072 		}
1073 	}
1074 	/* Preferred and Valid Lifetimes for prefixes */
1075 	{
1076 		struct nd_optlist *optp = ndopts.nd_opts_list;
1077 
1078 		if (ndopts.nd_opts_pi) {
1079 			if (prefix_check(ndopts.nd_opts_pi, rai, from))
1080 				inconsistent++;
1081 		}
1082 		while (optp) {
1083 			if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
1084 					 rai, from))
1085 				inconsistent++;
1086 			optp = optp->next;
1087 		}
1088 	}
1089 
1090 	if (inconsistent)
1091 		rai->rainconsistent++;
1092 
1093   done:
1094 	free_ndopts(&ndopts);
1095 	return;
1096 }
1097 
1098 /* return a non-zero value if the received prefix is inconsitent with ours */
1099 static int
1100 prefix_check(struct nd_opt_prefix_info *pinfo,
1101 	     struct rainfo *rai, struct sockaddr_in6 *from)
1102 {
1103 	u_int32_t preferred_time, valid_time;
1104 	struct prefix *pp;
1105 	int inconsistent = 0;
1106 	u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
1107 	struct timeval now;
1108 
1109 #if 0				/* impossible */
1110 	if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION)
1111 		return(0);
1112 #endif
1113 
1114 	/*
1115 	 * log if the adveritsed prefix has link-local scope(sanity check?)
1116 	 */
1117 	if (IN6_IS_ADDR_LINKLOCAL(&pinfo->nd_opt_pi_prefix)) {
1118 		syslog(LOG_INFO,
1119 		       "<%s> link-local prefix %s/%d is advertised "
1120 		       "from %s on %s",
1121 		       __func__,
1122 		       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1123 				 prefixbuf, INET6_ADDRSTRLEN),
1124 		       pinfo->nd_opt_pi_prefix_len,
1125 		       inet_ntop(AF_INET6, &from->sin6_addr,
1126 				 ntopbuf, INET6_ADDRSTRLEN),
1127 		       rai->ifname);
1128 	}
1129 
1130 	if ((pp = find_prefix(rai, &pinfo->nd_opt_pi_prefix,
1131 			      pinfo->nd_opt_pi_prefix_len)) == NULL) {
1132 		syslog(LOG_INFO,
1133 		       "<%s> prefix %s/%d from %s on %s is not in our list",
1134 		       __func__,
1135 		       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1136 				 prefixbuf, INET6_ADDRSTRLEN),
1137 		       pinfo->nd_opt_pi_prefix_len,
1138 		       inet_ntop(AF_INET6, &from->sin6_addr,
1139 				 ntopbuf, INET6_ADDRSTRLEN),
1140 		       rai->ifname);
1141 		return(0);
1142 	}
1143 
1144 	preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
1145 	if (pp->pltimeexpire) {
1146 		/*
1147 		 * The lifetime is decremented in real time, so we should
1148 		 * compare the expiration time.
1149 		 * (RFC 2461 Section 6.2.7.)
1150 		 * XXX: can we really expect that all routers on the link
1151 		 * have synchronized clocks?
1152 		 */
1153 		gettimeofday(&now, NULL);
1154 		preferred_time += now.tv_sec;
1155 
1156 		if (!pp->timer && rai->clockskew &&
1157 		    abs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
1158 			syslog(LOG_INFO,
1159 			       "<%s> preferred lifetime for %s/%d"
1160 			       " (decr. in real time) inconsistent on %s:"
1161 			       " %d from %s, %ld from us",
1162 			       __func__,
1163 			       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1164 					 prefixbuf, INET6_ADDRSTRLEN),
1165 			       pinfo->nd_opt_pi_prefix_len,
1166 			       rai->ifname, preferred_time,
1167 			       inet_ntop(AF_INET6, &from->sin6_addr,
1168 					 ntopbuf, INET6_ADDRSTRLEN),
1169 			       pp->pltimeexpire);
1170 			inconsistent++;
1171 		}
1172 	} else if (!pp->timer && preferred_time != pp->preflifetime) {
1173 		syslog(LOG_INFO,
1174 		       "<%s> preferred lifetime for %s/%d"
1175 		       " inconsistent on %s:"
1176 		       " %d from %s, %d from us",
1177 		       __func__,
1178 		       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1179 				 prefixbuf, INET6_ADDRSTRLEN),
1180 		       pinfo->nd_opt_pi_prefix_len,
1181 		       rai->ifname, preferred_time,
1182 		       inet_ntop(AF_INET6, &from->sin6_addr,
1183 				 ntopbuf, INET6_ADDRSTRLEN),
1184 		       pp->preflifetime);
1185 	}
1186 
1187 	valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
1188 	if (pp->vltimeexpire) {
1189 		gettimeofday(&now, NULL);
1190 		valid_time += now.tv_sec;
1191 
1192 		if (!pp->timer && rai->clockskew &&
1193 		    abs(valid_time - pp->vltimeexpire) > rai->clockskew) {
1194 			syslog(LOG_INFO,
1195 			       "<%s> valid lifetime for %s/%d"
1196 			       " (decr. in real time) inconsistent on %s:"
1197 			       " %d from %s, %ld from us",
1198 			       __func__,
1199 			       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1200 					 prefixbuf, INET6_ADDRSTRLEN),
1201 			       pinfo->nd_opt_pi_prefix_len,
1202 			       rai->ifname, preferred_time,
1203 			       inet_ntop(AF_INET6, &from->sin6_addr,
1204 					 ntopbuf, INET6_ADDRSTRLEN),
1205 			       pp->vltimeexpire);
1206 			inconsistent++;
1207 		}
1208 	} else if (!pp->timer && valid_time != pp->validlifetime) {
1209 		syslog(LOG_INFO,
1210 		       "<%s> valid lifetime for %s/%d"
1211 		       " inconsistent on %s:"
1212 		       " %d from %s, %d from us",
1213 		       __func__,
1214 		       inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
1215 				 prefixbuf, INET6_ADDRSTRLEN),
1216 		       pinfo->nd_opt_pi_prefix_len,
1217 		       rai->ifname, valid_time,
1218 		       inet_ntop(AF_INET6, &from->sin6_addr,
1219 				 ntopbuf, INET6_ADDRSTRLEN),
1220 		       pp->validlifetime);
1221 		inconsistent++;
1222 	}
1223 
1224 	return(inconsistent);
1225 }
1226 
1227 struct prefix *
1228 find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
1229 {
1230 	struct prefix *pp;
1231 	int bytelen, bitlen;
1232 	u_char bitmask;
1233 
1234 	for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) {
1235 		if (plen != pp->prefixlen)
1236 			continue;
1237 		bytelen = plen / 8;
1238 		bitlen = plen % 8;
1239 		bitmask = 0xff << (8 - bitlen);
1240 		if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen))
1241 			continue;
1242 		if (bitlen == 0 ||
1243 		    ((prefix->s6_addr[bytelen] & bitmask) ==
1244 		     (pp->prefix.s6_addr[bytelen] & bitmask))) {
1245 			return(pp);
1246 		}
1247 	}
1248 
1249 	return(NULL);
1250 }
1251 
1252 /* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */
1253 int
1254 prefix_match(struct in6_addr *p0, int plen0,
1255 	     struct in6_addr *p1, int plen1)
1256 {
1257 	int bytelen, bitlen;
1258 	u_char bitmask;
1259 
1260 	if (plen0 < plen1)
1261 		return(0);
1262 	bytelen = plen1 / 8;
1263 	bitlen = plen1 % 8;
1264 	bitmask = 0xff << (8 - bitlen);
1265 	if (memcmp((void *)p0, (void *)p1, bytelen))
1266 		return(0);
1267 	if (bitlen == 0 ||
1268 	    ((p0->s6_addr[bytelen] & bitmask) ==
1269 	     (p1->s6_addr[bytelen] & bitmask))) {
1270 		return(1);
1271 	}
1272 
1273 	return(0);
1274 }
1275 
1276 static int
1277 nd6_options(struct nd_opt_hdr *hdr, int limit,
1278 	    union nd_opts *ndopts, u_int32_t optflags)
1279 {
1280 	int optlen = 0;
1281 
1282 	for (; limit > 0; limit -= optlen) {
1283 		if (limit < sizeof(struct nd_opt_hdr)) {
1284 			syslog(LOG_INFO, "<%s> short option header", __func__);
1285 			goto bad;
1286 		}
1287 
1288 		hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen);
1289 		if (hdr->nd_opt_len == 0) {
1290 			syslog(LOG_INFO,
1291 			    "<%s> bad ND option length(0) (type = %d)",
1292 			    __func__, hdr->nd_opt_type);
1293 			goto bad;
1294 		}
1295 		optlen = hdr->nd_opt_len << 3;
1296 		if (optlen > limit) {
1297 			syslog(LOG_INFO, "<%s> short option", __func__);
1298 			goto bad;
1299 		}
1300 
1301 		if (hdr->nd_opt_type > ND_OPT_MTU) {
1302 			syslog(LOG_INFO, "<%s> unknown ND option(type %d)",
1303 			    __func__, hdr->nd_opt_type);
1304 			continue;
1305 		}
1306 
1307 		if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
1308 			syslog(LOG_INFO, "<%s> unexpected ND option(type %d)",
1309 			    __func__, hdr->nd_opt_type);
1310 			continue;
1311 		}
1312 
1313 		/*
1314 		 * Option length check.  Do it here for all fixed-length
1315 		 * options.
1316 		 */
1317 		if ((hdr->nd_opt_type == ND_OPT_MTU &&
1318 		    (optlen != sizeof(struct nd_opt_mtu))) ||
1319 		    ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
1320 		    optlen != sizeof(struct nd_opt_prefix_info)))) {
1321 			syslog(LOG_INFO, "<%s> invalid option length",
1322 			    __func__);
1323 			continue;
1324 		}
1325 
1326 		switch (hdr->nd_opt_type) {
1327 		case ND_OPT_TARGET_LINKADDR:
1328 		case ND_OPT_REDIRECTED_HEADER:
1329 			break;	/* we don't care about these options */
1330 		case ND_OPT_SOURCE_LINKADDR:
1331 		case ND_OPT_MTU:
1332 			if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
1333 				syslog(LOG_INFO,
1334 				    "<%s> duplicated ND option (type = %d)",
1335 				    __func__, hdr->nd_opt_type);
1336 			}
1337 			ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
1338 			break;
1339 		case ND_OPT_PREFIX_INFORMATION:
1340 		{
1341 			struct nd_optlist *pfxlist;
1342 
1343 			if (ndopts->nd_opts_pi == 0) {
1344 				ndopts->nd_opts_pi =
1345 				    (struct nd_opt_prefix_info *)hdr;
1346 				continue;
1347 			}
1348 			if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) {
1349 				syslog(LOG_ERR, "<%s> can't allocate memory",
1350 				    __func__);
1351 				goto bad;
1352 			}
1353 			pfxlist->next = ndopts->nd_opts_list;
1354 			pfxlist->opt = hdr;
1355 			ndopts->nd_opts_list = pfxlist;
1356 
1357 			break;
1358 		}
1359 		default:	/* impossible */
1360 			break;
1361 		}
1362 	}
1363 
1364 	return(0);
1365 
1366   bad:
1367 	free_ndopts(ndopts);
1368 
1369 	return(-1);
1370 }
1371 
1372 static void
1373 free_ndopts(union nd_opts *ndopts)
1374 {
1375 	struct nd_optlist *opt = ndopts->nd_opts_list, *next;
1376 
1377 	while (opt) {
1378 		next = opt->next;
1379 		free(opt);
1380 		opt = next;
1381 	}
1382 }
1383 
1384 void
1385 sock_open()
1386 {
1387 	struct icmp6_filter filt;
1388 	struct ipv6_mreq mreq;
1389 	struct rainfo *ra = ralist;
1390 	int on;
1391 	/* XXX: should be max MTU attached to the node */
1392 	static u_char answer[1500];
1393 
1394 	rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1395 				CMSG_SPACE(sizeof(int));
1396 	rcvcmsgbuf = (u_char *)malloc(rcvcmsgbuflen);
1397 	if (rcvcmsgbuf == NULL) {
1398 		syslog(LOG_ERR, "<%s> not enough core", __func__);
1399 		exit(1);
1400 	}
1401 
1402 	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1403 				CMSG_SPACE(sizeof(int));
1404 	sndcmsgbuf = (u_char *)malloc(sndcmsgbuflen);
1405 	if (sndcmsgbuf == NULL) {
1406 		syslog(LOG_ERR, "<%s> not enough core", __func__);
1407 		exit(1);
1408 	}
1409 
1410 	if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
1411 		syslog(LOG_ERR, "<%s> socket: %s", __func__,
1412 		       strerror(errno));
1413 		exit(1);
1414 	}
1415 
1416 	/* specify to tell receiving interface */
1417 	on = 1;
1418 #ifdef IPV6_RECVPKTINFO
1419 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
1420 		       sizeof(on)) < 0) {
1421 		syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s",
1422 		       __func__, strerror(errno));
1423 		exit(1);
1424 	}
1425 #else  /* old adv. API */
1426 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
1427 		       sizeof(on)) < 0) {
1428 		syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s",
1429 		       __func__, strerror(errno));
1430 		exit(1);
1431 	}
1432 #endif
1433 
1434 	on = 1;
1435 	/* specify to tell value of hoplimit field of received IP6 hdr */
1436 #ifdef IPV6_RECVHOPLIMIT
1437 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
1438 		       sizeof(on)) < 0) {
1439 		syslog(LOG_ERR, "<%s> IPV6_RECVHOPLIMIT: %s",
1440 		       __func__, strerror(errno));
1441 		exit(1);
1442 	}
1443 #else  /* old adv. API */
1444 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
1445 		       sizeof(on)) < 0) {
1446 		syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s",
1447 		       __func__, strerror(errno));
1448 		exit(1);
1449 	}
1450 #endif
1451 
1452 	ICMP6_FILTER_SETBLOCKALL(&filt);
1453 	ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
1454 	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
1455 	if (accept_rr)
1456 		ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt);
1457 	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
1458 		       sizeof(filt)) < 0) {
1459 		syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s",
1460 		       __func__, strerror(errno));
1461 		exit(1);
1462 	}
1463 
1464 	/*
1465 	 * join all routers multicast address on each advertising interface.
1466 	 */
1467 	if (inet_pton(AF_INET6, ALLROUTERS_LINK,
1468 		      &mreq.ipv6mr_multiaddr.s6_addr)
1469 	    != 1) {
1470 		syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1471 		       __func__);
1472 		exit(1);
1473 	}
1474 	while (ra) {
1475 		mreq.ipv6mr_interface = ra->ifindex;
1476 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
1477 			       sizeof(mreq)) < 0) {
1478 			syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s",
1479 			       __func__, ra->ifname, strerror(errno));
1480 			exit(1);
1481 		}
1482 		ra = ra->next;
1483 	}
1484 
1485 	/*
1486 	 * When attending router renumbering, join all-routers site-local
1487 	 * multicast group.
1488 	 */
1489 	if (accept_rr) {
1490 		if (inet_pton(AF_INET6, ALLROUTERS_SITE,
1491 			      &in6a_site_allrouters) != 1) {
1492 			syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)",
1493 			       __func__);
1494 			exit(1);
1495 		}
1496 		mreq.ipv6mr_multiaddr = in6a_site_allrouters;
1497 		if (mcastif) {
1498 			if ((mreq.ipv6mr_interface = if_nametoindex(mcastif))
1499 			    == 0) {
1500 				syslog(LOG_ERR,
1501 				       "<%s> invalid interface: %s",
1502 				       __func__, mcastif);
1503 				exit(1);
1504 			}
1505 		} else
1506 			mreq.ipv6mr_interface = ralist->ifindex;
1507 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1508 			       &mreq, sizeof(mreq)) < 0) {
1509 			syslog(LOG_ERR,
1510 			       "<%s> IPV6_JOIN_GROUP(site) on %s: %s",
1511 			       __func__,
1512 			       mcastif ? mcastif : ralist->ifname,
1513 			       strerror(errno));
1514 			exit(1);
1515 		}
1516 	}
1517 
1518 	/* initialize msghdr for receiving packets */
1519 	rcviov[0].iov_base = (caddr_t)answer;
1520 	rcviov[0].iov_len = sizeof(answer);
1521 	rcvmhdr.msg_name = (caddr_t)&rcvfrom;
1522 	rcvmhdr.msg_namelen = sizeof(rcvfrom);
1523 	rcvmhdr.msg_iov = rcviov;
1524 	rcvmhdr.msg_iovlen = 1;
1525 	rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
1526 	rcvmhdr.msg_controllen = rcvcmsgbuflen;
1527 
1528 	/* initialize msghdr for sending packets */
1529 	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
1530 	sndmhdr.msg_iov = sndiov;
1531 	sndmhdr.msg_iovlen = 1;
1532 	sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
1533 	sndmhdr.msg_controllen = sndcmsgbuflen;
1534 
1535 	return;
1536 }
1537 
1538 /* open a routing socket to watch the routing table */
1539 static void
1540 rtsock_open()
1541 {
1542 	if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
1543 		syslog(LOG_ERR,
1544 		       "<%s> socket: %s", __func__, strerror(errno));
1545 		exit(1);
1546 	}
1547 }
1548 
1549 struct rainfo *
1550 if_indextorainfo(int idx)
1551 {
1552 	struct rainfo *rai = ralist;
1553 
1554 	for (rai = ralist; rai; rai = rai->next) {
1555 		if (rai->ifindex == idx)
1556 			return(rai);
1557 	}
1558 
1559 	return(NULL);		/* search failed */
1560 }
1561 
1562 static void
1563 ra_output(rainfo)
1564 struct rainfo *rainfo;
1565 {
1566 	int i;
1567 	struct cmsghdr *cm;
1568 	struct in6_pktinfo *pi;
1569 	struct soliciter *sol, *nextsol;
1570 
1571 	if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
1572 		syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA",
1573 		       __func__, rainfo->ifname);
1574 		return;
1575 	}
1576 
1577 	make_packet(rainfo);	/* XXX: inefficient */
1578 
1579 	sndmhdr.msg_name = (caddr_t)&sin6_allnodes;
1580 	sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data;
1581 	sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
1582 
1583 	cm = CMSG_FIRSTHDR(&sndmhdr);
1584 	/* specify the outgoing interface */
1585 	cm->cmsg_level = IPPROTO_IPV6;
1586 	cm->cmsg_type = IPV6_PKTINFO;
1587 	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1588 	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1589 	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));	/*XXX*/
1590 	pi->ipi6_ifindex = rainfo->ifindex;
1591 
1592 	/* specify the hop limit of the packet */
1593 	{
1594 		int hoplimit = 255;
1595 
1596 		cm = CMSG_NXTHDR(&sndmhdr, cm);
1597 		cm->cmsg_level = IPPROTO_IPV6;
1598 		cm->cmsg_type = IPV6_HOPLIMIT;
1599 		cm->cmsg_len = CMSG_LEN(sizeof(int));
1600 		memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1601 	}
1602 
1603 	syslog(LOG_DEBUG,
1604 	       "<%s> send RA on %s, # of waitings = %d",
1605 	       __func__, rainfo->ifname, rainfo->waiting);
1606 
1607 	i = sendmsg(sock, &sndmhdr, 0);
1608 
1609 	if (i < 0 || i != rainfo->ra_datalen)  {
1610 		if (i < 0) {
1611 			syslog(LOG_ERR, "<%s> sendmsg on %s: %s",
1612 			       __func__, rainfo->ifname,
1613 			       strerror(errno));
1614 		}
1615 	}
1616 	/* update counter */
1617 	if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
1618 		rainfo->initcounter++;
1619 	rainfo->raoutput++;
1620 
1621 	/*
1622 	 * unicast advertisements
1623 	 * XXX commented out.  reason: though spec does not forbit it, unicast
1624 	 * advert does not really help
1625 	 */
1626 	for (sol = rainfo->soliciter; sol; sol = nextsol) {
1627 		nextsol = sol->next;
1628 
1629 		sol->next = NULL;
1630 		free(sol);
1631 	}
1632 	rainfo->soliciter = NULL;
1633 
1634 	/* update timestamp */
1635 	gettimeofday(&rainfo->lastsent, NULL);
1636 
1637 	/* reset waiting conter */
1638 	rainfo->waiting = 0;
1639 }
1640 
1641 /* process RA timer */
1642 struct rtadvd_timer *
1643 ra_timeout(void *data)
1644 {
1645 	struct rainfo *rai = (struct rainfo *)data;
1646 
1647 #ifdef notyet
1648 	/* if necessary, reconstruct the packet. */
1649 #endif
1650 
1651 	syslog(LOG_DEBUG,
1652 	       "<%s> RA timer on %s is expired",
1653 	       __func__, rai->ifname);
1654 
1655 	ra_output(rai);
1656 
1657 	return(rai->timer);
1658 }
1659 
1660 /* update RA timer */
1661 void
1662 ra_timer_update(void *data, struct timeval *tm)
1663 {
1664 	struct rainfo *rai = (struct rainfo *)data;
1665 	long interval;
1666 
1667 	/*
1668 	 * Whenever a multicast advertisement is sent from an interface,
1669 	 * the timer is reset to a uniformly-distributed random value
1670 	 * between the interface's configured MinRtrAdvInterval and
1671 	 * MaxRtrAdvInterval (RFC2461 6.2.4).
1672 	 */
1673 	interval = rai->mininterval;
1674 #ifdef HAVE_ARC4RANDOM
1675 	interval += arc4random_uniform(rai->maxinterval - rai->mininterval);
1676 #else
1677 	interval += random() % (rai->maxinterval - rai->mininterval);
1678 #endif
1679 
1680 	/*
1681 	 * For the first few advertisements (up to
1682 	 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
1683 	 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer
1684 	 * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
1685 	 * (RFC-2461 6.2.4)
1686 	 */
1687 	if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS &&
1688 	    interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)
1689 		interval = MAX_INITIAL_RTR_ADVERT_INTERVAL;
1690 
1691 	tm->tv_sec = interval;
1692 	tm->tv_usec = 0;
1693 
1694 	syslog(LOG_DEBUG,
1695 	       "<%s> RA timer on %s is set to %ld:%ld",
1696 	       __func__, rai->ifname,
1697 	       (long int)tm->tv_sec, (long int)tm->tv_usec);
1698 
1699 	return;
1700 }
1701