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