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