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