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