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