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