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