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