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