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