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