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