1 /* $KAME: rtadvd.c,v 1.50 2001/02/04 06:15:15 itojun Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD: src/usr.sbin/rtadvd/rtadvd.c,v 1.3.2.4 2003/04/05 10:31:58 ume Exp $ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/socket.h> 36 #include <sys/uio.h> 37 #include <sys/time.h> 38 #include <sys/queue.h> 39 40 #include <net/if.h> 41 #include <net/route.h> 42 #include <net/if_dl.h> 43 #include <netinet/in.h> 44 #include <netinet/ip6.h> 45 #include <netinet6/ip6_var.h> 46 #include <netinet/icmp6.h> 47 48 #include <arpa/inet.h> 49 50 #include <time.h> 51 #include <unistd.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <err.h> 55 #include <errno.h> 56 #include <string.h> 57 #include <syslog.h> 58 #include "rtadvd.h" 59 #include "rrenum.h" 60 #include "advcap.h" 61 #include "timer.h" 62 #include "if.h" 63 #include "config.h" 64 #include "dump.h" 65 66 struct msghdr rcvmhdr; 67 static u_char *rcvcmsgbuf; 68 static size_t rcvcmsgbuflen; 69 static u_char *sndcmsgbuf = NULL; 70 static size_t sndcmsgbuflen; 71 static int do_dump; 72 static int do_die; 73 struct msghdr sndmhdr; 74 struct iovec rcviov[2]; 75 struct iovec sndiov[2]; 76 struct sockaddr_in6 from; 77 struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6}; 78 struct in6_addr in6a_site_allrouters; 79 static char *dumpfilename = "/var/run/rtadvd.dump"; /* XXX: should be configurable */ 80 static char *pidfilename = "/var/run/rtadvd.pid"; /* should be configurable */ 81 static char *mcastif; 82 int sock; 83 int rtsock = -1; 84 #ifdef MIP6 85 int mobileip6 = 0; 86 #endif 87 int accept_rr = 0; 88 int dflag = 0, sflag = 0; 89 90 u_char *conffile = NULL; 91 92 struct rainfo *ralist = NULL; 93 struct nd_optlist { 94 struct nd_optlist *next; 95 struct nd_opt_hdr *opt; 96 }; 97 union nd_opts { 98 struct nd_opt_hdr *nd_opt_array[7]; 99 struct { 100 struct nd_opt_hdr *zero; 101 struct nd_opt_hdr *src_lladdr; 102 struct nd_opt_hdr *tgt_lladdr; 103 struct nd_opt_prefix_info *pi; 104 struct nd_opt_rd_hdr *rh; 105 struct nd_opt_mtu *mtu; 106 struct nd_optlist *list; 107 } nd_opt_each; 108 }; 109 #define nd_opts_src_lladdr nd_opt_each.src_lladdr 110 #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr 111 #define nd_opts_pi nd_opt_each.pi 112 #define nd_opts_rh nd_opt_each.rh 113 #define nd_opts_mtu nd_opt_each.mtu 114 #define nd_opts_list nd_opt_each.list 115 116 #define NDOPT_FLAG_SRCLINKADDR 0x1 117 #define NDOPT_FLAG_TGTLINKADDR 0x2 118 #define NDOPT_FLAG_PREFIXINFO 0x4 119 #define NDOPT_FLAG_RDHDR 0x8 120 #define NDOPT_FLAG_MTU 0x10 121 122 u_int32_t ndopt_flags[] = { 123 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR, 124 NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU 125 }; 126 127 static void set_die(int); 128 static void die(void); 129 static void sock_open(void); 130 static void rtsock_open(void); 131 static void rtadvd_input(void); 132 static void rs_input(int, struct nd_router_solicit *, 133 struct in6_pktinfo *, struct sockaddr_in6 *); 134 static void ra_input(int, struct nd_router_advert *, 135 struct in6_pktinfo *, struct sockaddr_in6 *); 136 static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *, 137 struct sockaddr_in6 *); 138 static int nd6_options(struct nd_opt_hdr *, int, 139 union nd_opts *, u_int32_t); 140 static void free_ndopts(union nd_opts *); 141 static void ra_output(struct rainfo *); 142 static void rtmsg_input(void); 143 static void rtadvd_set_dump_file(void); 144 145 int 146 main(int argc, char *argv[]) 147 { 148 fd_set fdset; 149 int maxfd = 0; 150 struct timeval *timeout; 151 int i, ch; 152 int fflag = 0; 153 FILE *pidfp; 154 pid_t pid; 155 156 openlog("rtadvd", LOG_NDELAY|LOG_PID, LOG_DAEMON); 157 158 /* get command line options and arguments */ 159 #ifdef MIP6 160 #define OPTIONS "c:dDfM:mRs" 161 #else 162 #define OPTIONS "c:dDfM:Rs" 163 #endif 164 while ((ch = getopt(argc, argv, OPTIONS)) != -1) { 165 #undef OPTIONS 166 switch (ch) { 167 case 'c': 168 conffile = optarg; 169 break; 170 case 'd': 171 dflag = 1; 172 break; 173 case 'D': 174 dflag = 2; 175 break; 176 case 'f': 177 fflag = 1; 178 break; 179 case 'M': 180 mcastif = optarg; 181 break; 182 #ifdef MIP6 183 case 'm': 184 mobileip6 = 1; 185 break; 186 #endif 187 case 'R': 188 fprintf(stderr, "rtadvd: " 189 "the -R option is currently ignored.\n"); 190 /* accept_rr = 1; */ 191 /* run anyway... */ 192 break; 193 case 's': 194 sflag = 1; 195 break; 196 } 197 } 198 argc -= optind; 199 argv += optind; 200 if (argc == 0) { 201 fprintf(stderr, 202 #ifdef MIP6 203 "usage: rtadvd [-dDfMmRs] [-c conffile] " 204 #else 205 "usage: rtadvd [-dDfMRs] [-c conffile] " 206 #endif 207 "interfaces...\n"); 208 exit(1); 209 } 210 211 /* set log level */ 212 if (dflag == 0) 213 setlogmask(LOG_UPTO(LOG_ERR)); 214 if (dflag == 1) 215 setlogmask(LOG_UPTO(LOG_INFO)); 216 217 /* timer initialization */ 218 rtadvd_timer_init(); 219 220 /* random value initialization */ 221 srandom((u_long)time(NULL)); 222 223 /* get iflist block from kernel */ 224 init_iflist(); 225 226 while (argc--) 227 getconfig(*argv++); 228 229 if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1) { 230 fprintf(stderr, "fatal: inet_pton failed\n"); 231 exit(1); 232 } 233 sock_open(); 234 235 if (!fflag) 236 daemon(1, 0); 237 238 /* record the current PID */ 239 pid = getpid(); 240 if ((pidfp = fopen(pidfilename, "w")) == NULL) { 241 syslog(LOG_ERR, 242 "<%s> failed to open a log file(%s), run anyway.", 243 __func__, pidfilename); 244 } else { 245 fprintf(pidfp, "%d\n", pid); 246 fclose(pidfp); 247 } 248 249 FD_ZERO(&fdset); 250 FD_SET(sock, &fdset); 251 maxfd = sock; 252 if (sflag == 0) { 253 rtsock_open(); 254 FD_SET(rtsock, &fdset); 255 if (rtsock > sock) 256 maxfd = rtsock; 257 } else 258 rtsock = -1; 259 260 signal(SIGTERM, (void *)set_die); 261 signal(SIGUSR1, (void *)rtadvd_set_dump_file); 262 263 while (1) { 264 struct fd_set select_fd = fdset; /* reinitialize */ 265 266 if (do_dump) { /* SIGUSR1 */ 267 do_dump = 0; 268 rtadvd_dump_file(dumpfilename); 269 } 270 271 if (do_die) { 272 die(); 273 /*NOTREACHED*/ 274 } 275 276 /* timer expiration check and reset the timer */ 277 timeout = rtadvd_check_timer(); 278 279 if (timeout != NULL) { 280 syslog(LOG_DEBUG, 281 "<%s> set timer to %ld:%ld. waiting for " 282 "inputs or timeout", __func__, 283 (long int)timeout->tv_sec, 284 (long int)timeout->tv_usec); 285 } else { 286 syslog(LOG_DEBUG, 287 "<%s> there's no timer. waiting for inputs", 288 __func__); 289 } 290 291 if ((i = select(maxfd + 1, &select_fd, 292 NULL, NULL, timeout)) < 0) { 293 /* EINTR would occur upon SIGUSR1 for status dump */ 294 if (errno != EINTR) 295 syslog(LOG_ERR, "<%s> select: %s", 296 __func__, strerror(errno)); 297 continue; 298 } 299 if (i == 0) /* timeout */ 300 continue; 301 if (rtsock != -1 && FD_ISSET(rtsock, &select_fd)) 302 rtmsg_input(); 303 if (FD_ISSET(sock, &select_fd)) 304 rtadvd_input(); 305 } 306 exit(0); /* NOTREACHED */ 307 } 308 309 static void 310 rtadvd_set_dump_file(void) 311 { 312 do_dump = 1; 313 } 314 315 static void 316 set_die(int sig) 317 { 318 do_die = 1; 319 } 320 321 static void 322 die(void) 323 { 324 struct rainfo *ra; 325 int i; 326 const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS; 327 328 if (dflag > 1) { 329 syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n", 330 __func__); 331 } 332 333 for (ra = ralist; ra; ra = ra->next) { 334 ra->lifetime = 0; 335 make_packet(ra); 336 } 337 for (i = 0; i < retrans; i++) { 338 for (ra = ralist; ra; ra = ra->next) 339 ra_output(ra); 340 sleep(MIN_DELAY_BETWEEN_RAS); 341 } 342 exit(0); 343 /*NOTREACHED*/ 344 } 345 346 static void 347 rtmsg_input(void) 348 { 349 int n, type, ifindex = 0, plen; 350 size_t len; 351 char msg[2048], *next, *lim; 352 u_char ifname[IF_NAMESIZE]; 353 struct prefix *prefix; 354 struct rainfo *rai; 355 struct in6_addr *addr; 356 char addrbuf[INET6_ADDRSTRLEN]; 357 358 n = read(rtsock, msg, sizeof(msg)); 359 if (dflag > 1) { 360 syslog(LOG_DEBUG, "<%s> received a routing message " 361 "(type = %d, len = %d)", __func__, rtmsg_type(msg), n); 362 } 363 if (n > rtmsg_len(msg)) { 364 /* 365 * This usually won't happen for messages received on 366 * a routing socket. 367 */ 368 if (dflag > 1) 369 syslog(LOG_DEBUG, 370 "<%s> received data length is larger than " 371 "1st routing message len. multiple messages? " 372 "read %d bytes, but 1st msg len = %d", 373 __func__, n, rtmsg_len(msg)); 374 #if 0 375 /* adjust length */ 376 n = rtmsg_len(msg); 377 #endif 378 } 379 380 lim = msg + n; 381 for (next = msg; next < lim; next += len) { 382 int oldifflags; 383 384 next = get_next_msg(next, lim, 0, &len, 385 RTADV_TYPE2BITMASK(RTM_ADD) | 386 RTADV_TYPE2BITMASK(RTM_DELETE) | 387 RTADV_TYPE2BITMASK(RTM_NEWADDR) | 388 RTADV_TYPE2BITMASK(RTM_DELADDR) | 389 RTADV_TYPE2BITMASK(RTM_IFINFO)); 390 if (len == 0) 391 break; 392 type = rtmsg_type(next); 393 switch (type) { 394 case RTM_ADD: 395 case RTM_DELETE: 396 ifindex = get_rtm_ifindex(next); 397 break; 398 case RTM_NEWADDR: 399 case RTM_DELADDR: 400 ifindex = get_ifam_ifindex(next); 401 break; 402 case RTM_IFINFO: 403 ifindex = get_ifm_ifindex(next); 404 break; 405 default: 406 /* should not reach here */ 407 if (dflag > 1) { 408 syslog(LOG_DEBUG, 409 "<%s:%d> unknown rtmsg %d on %s", 410 __func__, __LINE__, type, 411 if_indextoname(ifindex, ifname)); 412 } 413 continue; 414 } 415 416 if ((rai = if_indextorainfo(ifindex)) == NULL) { 417 if (dflag > 1) { 418 syslog(LOG_DEBUG, 419 "<%s> route changed on " 420 "non advertising interface(%s)", 421 __func__, 422 if_indextoname(ifindex, ifname)); 423 } 424 continue; 425 } 426 oldifflags = iflist[ifindex]->ifm_flags; 427 428 switch (type) { 429 case RTM_ADD: 430 /* init ifflags because it may have changed */ 431 iflist[ifindex]->ifm_flags = 432 if_getflags(ifindex, iflist[ifindex]->ifm_flags); 433 434 if (sflag) 435 break; /* we aren't interested in prefixes */ 436 437 addr = get_addr(msg); 438 plen = get_prefixlen(msg); 439 /* sanity check for plen */ 440 /* as RFC2373, prefixlen is at least 4 */ 441 if (plen < 4 || plen > 127) { 442 syslog(LOG_INFO, "<%s> new interface route's" 443 "plen %d is invalid for a prefix", 444 __func__, plen); 445 break; 446 } 447 prefix = find_prefix(rai, addr, plen); 448 if (prefix) { 449 if (prefix->timer) { 450 /* 451 * If the prefix has been invalidated, 452 * make it available again. 453 */ 454 update_prefix(prefix); 455 } else if (dflag > 1) { 456 syslog(LOG_DEBUG, 457 "<%s> new prefix(%s/%d) " 458 "added on %s, " 459 "but it was already in list", 460 __func__, 461 inet_ntop(AF_INET6, addr, 462 (char *)addrbuf, INET6_ADDRSTRLEN), 463 plen, rai->ifname); 464 } 465 break; 466 } 467 make_prefix(rai, ifindex, addr, plen); 468 break; 469 case RTM_DELETE: 470 /* init ifflags because it may have changed */ 471 iflist[ifindex]->ifm_flags = 472 if_getflags(ifindex, iflist[ifindex]->ifm_flags); 473 474 if (sflag) 475 break; 476 477 addr = get_addr(msg); 478 plen = get_prefixlen(msg); 479 /* sanity check for plen */ 480 /* as RFC2373, prefixlen is at least 4 */ 481 if (plen < 4 || plen > 127) { 482 syslog(LOG_INFO, 483 "<%s> deleted interface route's " 484 "plen %d is invalid for a prefix", 485 __func__, plen); 486 break; 487 } 488 prefix = find_prefix(rai, addr, plen); 489 if (prefix == NULL) { 490 if (dflag > 1) { 491 syslog(LOG_DEBUG, 492 "<%s> prefix(%s/%d) was " 493 "deleted on %s, " 494 "but it was not in list", 495 __func__, 496 inet_ntop(AF_INET6, addr, 497 (char *)addrbuf, INET6_ADDRSTRLEN), 498 plen, rai->ifname); 499 } 500 break; 501 } 502 invalidate_prefix(prefix); 503 break; 504 case RTM_NEWADDR: 505 case RTM_DELADDR: 506 /* init ifflags because it may have changed */ 507 iflist[ifindex]->ifm_flags = 508 if_getflags(ifindex, iflist[ifindex]->ifm_flags); 509 break; 510 case RTM_IFINFO: 511 iflist[ifindex]->ifm_flags = get_ifm_flags(next); 512 break; 513 default: 514 /* should not reach here */ 515 if (dflag > 1) { 516 syslog(LOG_DEBUG, 517 "<%s:%d> unknown rtmsg %d on %s", 518 __func__, __LINE__, type, 519 if_indextoname(ifindex, ifname)); 520 } 521 return; 522 } 523 524 /* check if an interface flag is changed */ 525 if ((oldifflags & IFF_UP) != 0 && /* UP to DOWN */ 526 (iflist[ifindex]->ifm_flags & IFF_UP) == 0) { 527 syslog(LOG_INFO, 528 "<%s> interface %s becomes down. stop timer.", 529 __func__, rai->ifname); 530 rtadvd_remove_timer(&rai->timer); 531 } else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */ 532 (iflist[ifindex]->ifm_flags & IFF_UP) != 0) { 533 syslog(LOG_INFO, 534 "<%s> interface %s becomes up. restart timer.", 535 __func__, rai->ifname); 536 537 rai->initcounter = 0; /* reset the counter */ 538 rai->waiting = 0; /* XXX */ 539 rai->timer = rtadvd_add_timer(ra_timeout, 540 ra_timer_update, rai, rai); 541 ra_timer_update(rai, &rai->timer->tm); 542 rtadvd_set_timer(&rai->timer->tm, rai->timer); 543 } 544 } 545 546 return; 547 } 548 549 void 550 rtadvd_input(void) 551 { 552 int i; 553 int *hlimp = NULL; 554 #ifdef OLDRAWSOCKET 555 struct ip6_hdr *ip; 556 #endif 557 struct icmp6_hdr *icp; 558 int ifindex = 0; 559 struct cmsghdr *cm; 560 struct in6_pktinfo *pi = NULL; 561 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 562 struct in6_addr dst = in6addr_any; 563 564 /* 565 * Get message. We reset msg_controllen since the field could 566 * be modified if we had received a message before setting 567 * receive options. 568 */ 569 rcvmhdr.msg_controllen = rcvcmsgbuflen; 570 if ((i = recvmsg(sock, &rcvmhdr, 0)) < 0) 571 return; 572 573 /* extract optional information via Advanced API */ 574 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); 575 cm; 576 cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) { 577 if (cm->cmsg_level == IPPROTO_IPV6 && 578 cm->cmsg_type == IPV6_PKTINFO && 579 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 580 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 581 ifindex = pi->ipi6_ifindex; 582 dst = pi->ipi6_addr; 583 } 584 if (cm->cmsg_level == IPPROTO_IPV6 && 585 cm->cmsg_type == IPV6_HOPLIMIT && 586 cm->cmsg_len == CMSG_LEN(sizeof(int))) 587 hlimp = (int *)CMSG_DATA(cm); 588 } 589 if (ifindex == 0) { 590 syslog(LOG_ERR, 591 "<%s> failed to get receiving interface", 592 __func__); 593 return; 594 } 595 if (hlimp == NULL) { 596 syslog(LOG_ERR, 597 "<%s> failed to get receiving hop limit", 598 __func__); 599 return; 600 } 601 602 /* 603 * If we happen to receive data on an interface which is now down, 604 * just discard the data. 605 */ 606 if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) { 607 syslog(LOG_INFO, 608 "<%s> received data on a disabled interface (%s)", 609 __func__, 610 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 611 return; 612 } 613 614 #ifdef OLDRAWSOCKET 615 if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) { 616 syslog(LOG_ERR, 617 "<%s> packet size(%d) is too short", 618 __func__, i); 619 return; 620 } 621 622 ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base; 623 icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */ 624 #else 625 if (i < sizeof(struct icmp6_hdr)) { 626 syslog(LOG_ERR, 627 "<%s> packet size(%d) is too short", 628 __func__, i); 629 return; 630 } 631 632 icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; 633 #endif 634 635 switch (icp->icmp6_type) { 636 case ND_ROUTER_SOLICIT: 637 /* 638 * Message verification - RFC-2461 6.1.1 639 * XXX: these checks must be done in the kernel as well, 640 * but we can't completely rely on them. 641 */ 642 if (*hlimp != 255) { 643 syslog(LOG_NOTICE, 644 "<%s> RS with invalid hop limit(%d) " 645 "received from %s on %s", 646 __func__, *hlimp, 647 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 648 INET6_ADDRSTRLEN), 649 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 650 return; 651 } 652 if (icp->icmp6_code) { 653 syslog(LOG_NOTICE, 654 "<%s> RS with invalid ICMP6 code(%d) " 655 "received from %s on %s", 656 __func__, icp->icmp6_code, 657 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 658 INET6_ADDRSTRLEN), 659 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 660 return; 661 } 662 if (i < sizeof(struct nd_router_solicit)) { 663 syslog(LOG_NOTICE, 664 "<%s> RS from %s on %s does not have enough " 665 "length (len = %d)", 666 __func__, 667 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 668 INET6_ADDRSTRLEN), 669 if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); 670 return; 671 } 672 rs_input(i, (struct nd_router_solicit *)icp, pi, &from); 673 break; 674 case ND_ROUTER_ADVERT: 675 /* 676 * Message verification - RFC-2461 6.1.2 677 * XXX: there's a same dilemma as above... 678 */ 679 if (*hlimp != 255) { 680 syslog(LOG_NOTICE, 681 "<%s> RA with invalid hop limit(%d) " 682 "received from %s on %s", 683 __func__, *hlimp, 684 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 685 INET6_ADDRSTRLEN), 686 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 687 return; 688 } 689 if (icp->icmp6_code) { 690 syslog(LOG_NOTICE, 691 "<%s> RA with invalid ICMP6 code(%d) " 692 "received from %s on %s", 693 __func__, icp->icmp6_code, 694 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 695 INET6_ADDRSTRLEN), 696 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 697 return; 698 } 699 if (i < sizeof(struct nd_router_advert)) { 700 syslog(LOG_NOTICE, 701 "<%s> RA from %s on %s does not have enough " 702 "length (len = %d)", 703 __func__, 704 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 705 INET6_ADDRSTRLEN), 706 if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); 707 return; 708 } 709 ra_input(i, (struct nd_router_advert *)icp, pi, &from); 710 break; 711 case ICMP6_ROUTER_RENUMBERING: 712 if (accept_rr == 0) { 713 syslog(LOG_ERR, "<%s> received a router renumbering " 714 "message, but not allowed to be accepted", 715 __func__); 716 break; 717 } 718 rr_input(i, (struct icmp6_router_renum *)icp, pi, &from, 719 &dst); 720 break; 721 default: 722 /* 723 * Note that this case is POSSIBLE, especially just 724 * after invocation of the daemon. This is because we 725 * could receive message after opening the socket and 726 * before setting ICMP6 type filter(see sock_open()). 727 */ 728 syslog(LOG_ERR, "<%s> invalid icmp type(%d)", 729 __func__, icp->icmp6_type); 730 return; 731 } 732 733 return; 734 } 735 736 static void 737 rs_input(int len, struct nd_router_solicit *rs, 738 struct in6_pktinfo *pi, struct sockaddr_in6 *from) 739 { 740 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 741 union nd_opts ndopts; 742 struct rainfo *ra; 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_DEBUG, 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_ERR, 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 long delay; /* must not be greater than 1000000 */ 802 struct timeval interval, now, min_delay, tm_tmp, *rest; 803 struct soliciter *sol; 804 805 /* 806 * record sockaddr waiting for RA, if possible 807 */ 808 sol = (struct soliciter *)malloc(sizeof(*sol)); 809 if (sol) { 810 sol->addr = *from; 811 /*XXX RFC2553 need clarification on flowinfo */ 812 sol->addr.sin6_flowinfo = 0; 813 sol->next = ra->soliciter; 814 ra->soliciter = sol->next; 815 } 816 817 /* 818 * If there is already a waiting RS packet, don't 819 * update the timer. 820 */ 821 if (ra->waiting++) 822 goto done; 823 824 /* 825 * Compute a random delay. If the computed value 826 * corresponds to a time later than the time the next 827 * multicast RA is scheduled to be sent, ignore the random 828 * delay and send the advertisement at the 829 * already-scheduled time. RFC-2461 6.2.6 830 */ 831 delay = random() % MAX_RA_DELAY_TIME; 832 interval.tv_sec = 0; 833 interval.tv_usec = delay; 834 rest = rtadvd_timer_rest(ra->timer); 835 if (TIMEVAL_LT(*rest, interval)) { 836 syslog(LOG_DEBUG, 837 "<%s> random delay is larger than " 838 "the rest of normal timer", 839 __func__); 840 interval = *rest; 841 } 842 843 /* 844 * If we sent a multicast Router Advertisement within 845 * the last MIN_DELAY_BETWEEN_RAS seconds, schedule 846 * the advertisement to be sent at a time corresponding to 847 * MIN_DELAY_BETWEEN_RAS plus the random value after the 848 * previous advertisement was sent. 849 */ 850 gettimeofday(&now, NULL); 851 TIMEVAL_SUB(&now, &ra->lastsent, &tm_tmp); 852 min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; 853 min_delay.tv_usec = 0; 854 if (TIMEVAL_LT(tm_tmp, min_delay)) { 855 TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); 856 TIMEVAL_ADD(&min_delay, &interval, &interval); 857 } 858 rtadvd_set_timer(&interval, ra->timer); 859 goto done; 860 } 861 862 done: 863 free_ndopts(&ndopts); 864 return; 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 u_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_ERR, 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)) == NULL) { 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 u_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 (rai->clockskew && 1085 abs(preferred_time - pp->pltimeexpire) > rai->clockskew) { 1086 syslog(LOG_INFO, 1087 "<%s> prefeerred 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 (preferred_time != pp->preflifetime) { 1101 syslog(LOG_INFO, 1102 "<%s> prefeerred 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 (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 (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 1161 for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) { 1162 if (plen != pp->prefixlen) 1163 continue; 1164 bytelen = plen / 8; 1165 bitlen = plen % 8; 1166 if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen)) 1167 continue; 1168 if (prefix->s6_addr[bytelen] >> (8 - bitlen) == 1169 pp->prefix.s6_addr[bytelen] >> (8 - bitlen)) 1170 return(pp); 1171 } 1172 1173 return(NULL); 1174 } 1175 1176 /* check if p0/plen0 matches p1/plen1; return 1 if matches, otherwise 0. */ 1177 int 1178 prefix_match(struct in6_addr *p0, int plen0, 1179 struct in6_addr *p1, int plen1) 1180 { 1181 int bytelen, bitlen; 1182 1183 if (plen0 < plen1) 1184 return(0); 1185 bytelen = plen1 / 8; 1186 bitlen = plen1 % 8; 1187 if (memcmp((void *)p0, (void *)p1, bytelen)) 1188 return(0); 1189 if (p0->s6_addr[bytelen] >> (8 - bitlen) == 1190 p1->s6_addr[bytelen] >> (8 - bitlen)) 1191 return(1); 1192 1193 return(0); 1194 } 1195 1196 static int 1197 nd6_options(struct nd_opt_hdr *hdr, int limit, 1198 union nd_opts *ndopts, u_int32_t optflags) 1199 { 1200 int optlen = 0; 1201 1202 for (; limit > 0; limit -= optlen) { 1203 if (limit < sizeof(struct nd_opt_hdr)) { 1204 syslog(LOG_INFO, "<%s> short option header", __func__); 1205 goto bad; 1206 } 1207 1208 hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen); 1209 if (hdr->nd_opt_len == 0) { 1210 syslog(LOG_INFO, 1211 "<%s> bad ND option length(0) (type = %d)", 1212 __func__, hdr->nd_opt_type); 1213 goto bad; 1214 } 1215 optlen = hdr->nd_opt_len << 3; 1216 if (optlen > limit) { 1217 syslog(LOG_INFO, "<%s> short option", __func__); 1218 goto bad; 1219 } 1220 1221 if (hdr->nd_opt_type > ND_OPT_MTU) { 1222 syslog(LOG_INFO, 1223 "<%s> unknown ND option(type %d)", 1224 __func__, hdr->nd_opt_type); 1225 continue; 1226 } 1227 1228 if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) { 1229 syslog(LOG_INFO, 1230 "<%s> unexpected ND option(type %d)", 1231 __func__, hdr->nd_opt_type); 1232 continue; 1233 } 1234 1235 /* 1236 * Option length check. Do it here for all fixed-length 1237 * options. 1238 */ 1239 if ((hdr->nd_opt_type == ND_OPT_MTU && 1240 (optlen != sizeof(struct nd_opt_mtu))) || 1241 ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION && 1242 optlen != sizeof(struct nd_opt_prefix_info)))) { 1243 syslog(LOG_INFO, "<%s> invalid option length", 1244 __func__); 1245 continue; 1246 } 1247 1248 switch (hdr->nd_opt_type) { 1249 case ND_OPT_SOURCE_LINKADDR: 1250 case ND_OPT_TARGET_LINKADDR: 1251 case ND_OPT_REDIRECTED_HEADER: 1252 break; /* we don't care about these options */ 1253 case ND_OPT_MTU: 1254 if (ndopts->nd_opt_array[hdr->nd_opt_type]) { 1255 syslog(LOG_INFO, 1256 "<%s> duplicated ND option (type = %d)", 1257 __func__, hdr->nd_opt_type); 1258 } 1259 ndopts->nd_opt_array[hdr->nd_opt_type] = hdr; 1260 break; 1261 case ND_OPT_PREFIX_INFORMATION: 1262 { 1263 struct nd_optlist *pfxlist; 1264 1265 if (ndopts->nd_opts_pi == 0) { 1266 ndopts->nd_opts_pi = 1267 (struct nd_opt_prefix_info *)hdr; 1268 continue; 1269 } 1270 if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) { 1271 syslog(LOG_ERR, "<%s> can't allocate memory", 1272 __func__); 1273 goto bad; 1274 } 1275 pfxlist->next = ndopts->nd_opts_list; 1276 pfxlist->opt = hdr; 1277 ndopts->nd_opts_list = pfxlist; 1278 1279 break; 1280 } 1281 default: /* impossible */ 1282 break; 1283 } 1284 } 1285 1286 return(0); 1287 1288 bad: 1289 free_ndopts(ndopts); 1290 1291 return(-1); 1292 } 1293 1294 static void 1295 free_ndopts(union nd_opts *ndopts) 1296 { 1297 struct nd_optlist *opt = ndopts->nd_opts_list, *next; 1298 1299 while (opt) { 1300 next = opt->next; 1301 free(opt); 1302 opt = next; 1303 } 1304 } 1305 1306 void 1307 sock_open(void) 1308 { 1309 struct icmp6_filter filt; 1310 struct ipv6_mreq mreq; 1311 struct rainfo *ra = ralist; 1312 int on; 1313 /* XXX: should be max MTU attached to the node */ 1314 static u_char answer[1500]; 1315 1316 rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 1317 CMSG_SPACE(sizeof(int)); 1318 rcvcmsgbuf = (u_char *)malloc(rcvcmsgbuflen); 1319 if (rcvcmsgbuf == NULL) { 1320 syslog(LOG_ERR, "<%s> not enough core", __func__); 1321 exit(1); 1322 } 1323 1324 sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 1325 CMSG_SPACE(sizeof(int)); 1326 sndcmsgbuf = (u_char *)malloc(sndcmsgbuflen); 1327 if (sndcmsgbuf == NULL) { 1328 syslog(LOG_ERR, "<%s> not enough core", __func__); 1329 exit(1); 1330 } 1331 1332 if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 1333 syslog(LOG_ERR, "<%s> socket: %s", __func__, 1334 strerror(errno)); 1335 exit(1); 1336 } 1337 1338 /* specify to tell receiving interface */ 1339 on = 1; 1340 #ifdef IPV6_RECVPKTINFO 1341 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 1342 sizeof(on)) < 0) { 1343 syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s", 1344 __func__, strerror(errno)); 1345 exit(1); 1346 } 1347 #else /* old adv. API */ 1348 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 1349 sizeof(on)) < 0) { 1350 syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s", 1351 __func__, strerror(errno)); 1352 exit(1); 1353 } 1354 #endif 1355 1356 on = 1; 1357 /* specify to tell value of hoplimit field of received IP6 hdr */ 1358 #ifdef IPV6_RECVHOPLIMIT 1359 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 1360 sizeof(on)) < 0) { 1361 syslog(LOG_ERR, "<%s> IPV6_RECVHOPLIMIT: %s", 1362 __func__, strerror(errno)); 1363 exit(1); 1364 } 1365 #else /* old adv. API */ 1366 if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 1367 sizeof(on)) < 0) { 1368 syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s", 1369 __func__, strerror(errno)); 1370 exit(1); 1371 } 1372 #endif 1373 1374 ICMP6_FILTER_SETBLOCKALL(&filt); 1375 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt); 1376 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); 1377 if (accept_rr) 1378 ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); 1379 if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 1380 sizeof(filt)) < 0) { 1381 syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", 1382 __func__, strerror(errno)); 1383 exit(1); 1384 } 1385 1386 /* 1387 * join all routers multicast address on each advertising interface. 1388 */ 1389 if (inet_pton(AF_INET6, ALLROUTERS_LINK, 1390 &mreq.ipv6mr_multiaddr.s6_addr) 1391 != 1) { 1392 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", 1393 __func__); 1394 exit(1); 1395 } 1396 while (ra) { 1397 mreq.ipv6mr_interface = ra->ifindex; 1398 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, 1399 sizeof(mreq)) < 0) { 1400 syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP(link) on %s: %s", 1401 __func__, ra->ifname, strerror(errno)); 1402 exit(1); 1403 } 1404 ra = ra->next; 1405 } 1406 1407 /* 1408 * When attending router renumbering, join all-routers site-local 1409 * multicast group. 1410 */ 1411 if (accept_rr) { 1412 if (inet_pton(AF_INET6, ALLROUTERS_SITE, 1413 &in6a_site_allrouters) != 1) { 1414 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", 1415 __func__); 1416 exit(1); 1417 } 1418 mreq.ipv6mr_multiaddr = in6a_site_allrouters; 1419 if (mcastif) { 1420 if ((mreq.ipv6mr_interface = if_nametoindex(mcastif)) 1421 == 0) { 1422 syslog(LOG_ERR, 1423 "<%s> invalid interface: %s", 1424 __func__, mcastif); 1425 exit(1); 1426 } 1427 } else 1428 mreq.ipv6mr_interface = ralist->ifindex; 1429 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 1430 &mreq, sizeof(mreq)) < 0) { 1431 syslog(LOG_ERR, 1432 "<%s> IPV6_JOIN_GROUP(site) on %s: %s", 1433 __func__, 1434 mcastif ? mcastif : ralist->ifname, 1435 strerror(errno)); 1436 exit(1); 1437 } 1438 } 1439 1440 /* initialize msghdr for receiving packets */ 1441 rcviov[0].iov_base = (caddr_t)answer; 1442 rcviov[0].iov_len = sizeof(answer); 1443 rcvmhdr.msg_name = (caddr_t)&from; 1444 rcvmhdr.msg_namelen = sizeof(from); 1445 rcvmhdr.msg_iov = rcviov; 1446 rcvmhdr.msg_iovlen = 1; 1447 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 1448 rcvmhdr.msg_controllen = rcvcmsgbuflen; 1449 1450 /* initialize msghdr for sending packets */ 1451 sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 1452 sndmhdr.msg_iov = sndiov; 1453 sndmhdr.msg_iovlen = 1; 1454 sndmhdr.msg_control = (caddr_t)sndcmsgbuf; 1455 sndmhdr.msg_controllen = sndcmsgbuflen; 1456 1457 return; 1458 } 1459 1460 /* open a routing socket to watch the routing table */ 1461 static void 1462 rtsock_open(void) 1463 { 1464 if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 1465 syslog(LOG_ERR, 1466 "<%s> socket: %s", __func__, strerror(errno)); 1467 exit(1); 1468 } 1469 } 1470 1471 struct rainfo * 1472 if_indextorainfo(int index) 1473 { 1474 struct rainfo *rai = ralist; 1475 1476 for (rai = ralist; rai; rai = rai->next) { 1477 if (rai->ifindex == index) 1478 return(rai); 1479 } 1480 1481 return(NULL); /* search failed */ 1482 } 1483 1484 static void 1485 ra_output(struct rainfo *rainfo) 1486 { 1487 int i; 1488 struct cmsghdr *cm; 1489 struct in6_pktinfo *pi; 1490 struct soliciter *sol, *nextsol; 1491 1492 if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) { 1493 syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA", 1494 __func__, rainfo->ifname); 1495 return; 1496 } 1497 1498 make_packet(rainfo); /* XXX: inefficient */ 1499 1500 sndmhdr.msg_name = (caddr_t)&sin6_allnodes; 1501 sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data; 1502 sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen; 1503 1504 cm = CMSG_FIRSTHDR(&sndmhdr); 1505 /* specify the outgoing interface */ 1506 cm->cmsg_level = IPPROTO_IPV6; 1507 cm->cmsg_type = IPV6_PKTINFO; 1508 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1509 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1510 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ 1511 pi->ipi6_ifindex = rainfo->ifindex; 1512 1513 /* specify the hop limit of the packet */ 1514 { 1515 int hoplimit = 255; 1516 1517 cm = CMSG_NXTHDR(&sndmhdr, cm); 1518 cm->cmsg_level = IPPROTO_IPV6; 1519 cm->cmsg_type = IPV6_HOPLIMIT; 1520 cm->cmsg_len = CMSG_LEN(sizeof(int)); 1521 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 1522 } 1523 1524 syslog(LOG_DEBUG, 1525 "<%s> send RA on %s, # of waitings = %d", 1526 __func__, rainfo->ifname, rainfo->waiting); 1527 1528 i = sendmsg(sock, &sndmhdr, 0); 1529 1530 if (i < 0 || i != rainfo->ra_datalen) { 1531 if (i < 0) { 1532 syslog(LOG_ERR, "<%s> sendmsg on %s: %s", 1533 __func__, rainfo->ifname, 1534 strerror(errno)); 1535 } 1536 } 1537 1538 /* 1539 * unicast advertisements 1540 * XXX commented out. reason: though spec does not forbit it, unicast 1541 * advert does not really help 1542 */ 1543 for (sol = rainfo->soliciter; sol; sol = nextsol) { 1544 nextsol = sol->next; 1545 1546 #if 0 1547 sndmhdr.msg_name = (caddr_t)&sol->addr; 1548 i = sendmsg(sock, &sndmhdr, 0); 1549 if (i < 0 || i != rainfo->ra_datalen) { 1550 if (i < 0) { 1551 syslog(LOG_ERR, 1552 "<%s> unicast sendmsg on %s: %s", 1553 __func__, rainfo->ifname, 1554 strerror(errno)); 1555 } 1556 } 1557 #endif 1558 1559 sol->next = NULL; 1560 free(sol); 1561 } 1562 rainfo->soliciter = NULL; 1563 1564 /* update counter */ 1565 if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) 1566 rainfo->initcounter++; 1567 rainfo->raoutput++; 1568 1569 /* update timestamp */ 1570 gettimeofday(&rainfo->lastsent, NULL); 1571 1572 /* reset waiting conter */ 1573 rainfo->waiting = 0; 1574 } 1575 1576 /* process RA timer */ 1577 struct rtadvd_timer * 1578 ra_timeout(void *data) 1579 { 1580 struct rainfo *rai = (struct rainfo *)data; 1581 1582 #ifdef notyet 1583 /* if necessary, reconstruct the packet. */ 1584 #endif 1585 1586 syslog(LOG_DEBUG, 1587 "<%s> RA timer on %s is expired", 1588 __func__, rai->ifname); 1589 1590 ra_output(rai); 1591 1592 return(rai->timer); 1593 } 1594 1595 /* update RA timer */ 1596 void 1597 ra_timer_update(void *data, struct timeval *tm) 1598 { 1599 struct rainfo *rai = (struct rainfo *)data; 1600 long interval; 1601 1602 /* 1603 * Whenever a multicast advertisement is sent from an interface, 1604 * the timer is reset to a uniformly-distributed random value 1605 * between the interface's configured MinRtrAdvInterval and 1606 * MaxRtrAdvInterval (RFC2461 6.2.4). 1607 */ 1608 interval = rai->mininterval; 1609 interval += random() % (rai->maxinterval - rai->mininterval); 1610 1611 /* 1612 * For the first few advertisements (up to 1613 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval 1614 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer 1615 * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead. 1616 * (RFC-2461 6.2.4) 1617 */ 1618 if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS && 1619 interval > MAX_INITIAL_RTR_ADVERT_INTERVAL) 1620 interval = MAX_INITIAL_RTR_ADVERT_INTERVAL; 1621 1622 tm->tv_sec = interval; 1623 tm->tv_usec = 0; 1624 1625 syslog(LOG_DEBUG, 1626 "<%s> RA timer on %s is set to %ld:%ld", 1627 __func__, rai->ifname, 1628 (long int)tm->tv_sec, (long int)tm->tv_usec); 1629 1630 return; 1631 } 1632