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