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