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