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