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