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