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