1 /* $NetBSD: rtadvd.c,v 1.4 1999/12/10 05:47:51 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 37 #include <net/if.h> 38 #include <net/route.h> 39 #include <net/if_dl.h> 40 #include <netinet/in.h> 41 #include <netinet/ip6.h> 42 #include <netinet6/ip6_var.h> 43 #include <netinet/icmp6.h> 44 45 #include <arpa/inet.h> 46 47 #include <time.h> 48 #include <unistd.h> 49 #include <stdio.h> 50 #include <err.h> 51 #include <errno.h> 52 #include <string.h> 53 #include <stdlib.h> 54 #include <syslog.h> 55 #include "rtadvd.h" 56 #include "rrenum.h" 57 #include "advcap.h" 58 #include "timer.h" 59 #include "if.h" 60 #include "config.h" 61 62 struct msghdr rcvmhdr; 63 static u_char rcvcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) + 64 CMSG_SPACE(sizeof(int))]; 65 struct msghdr sndmhdr; 66 struct iovec rcviov[2]; 67 struct iovec sndiov[2]; 68 struct sockaddr_in6 from; 69 struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6}; 70 int sock, rtsock; 71 int accept_rr = 1; 72 int dflag = 0, sflag = 0; 73 74 u_char *conffile = NULL; 75 76 struct rainfo *ralist = NULL; 77 struct nd_optlist { 78 struct nd_optlist *next; 79 struct nd_opt_hdr *opt; 80 }; 81 union nd_opts { 82 struct nd_opt_hdr *nd_opt_array[7]; 83 struct { 84 struct nd_opt_hdr *zero; 85 struct nd_opt_hdr *src_lladdr; 86 struct nd_opt_hdr *tgt_lladdr; 87 struct nd_opt_prefix_info *pi; 88 struct nd_opt_rd_hdr *rh; 89 struct nd_opt_mtu *mtu; 90 struct nd_optlist *list; 91 } nd_opt_each; 92 }; 93 #define nd_opts_src_lladdr nd_opt_each.src_lladdr 94 #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr 95 #define nd_opts_pi nd_opt_each.pi 96 #define nd_opts_rh nd_opt_each.rh 97 #define nd_opts_mtu nd_opt_each.mtu 98 #define nd_opts_list nd_opt_each.list 99 100 #define NDOPT_FLAG_SRCLINKADDR 0x1 101 #define NDOPT_FLAG_TGTLINKADDR 0x2 102 #define NDOPT_FLAG_PREFIXINFO 0x4 103 #define NDOPT_FLAG_RDHDR 0x8 104 #define NDOPT_FLAG_MTU 0x10 105 106 u_int32_t ndopt_flags[] = { 107 0, NDOPT_FLAG_SRCLINKADDR, NDOPT_FLAG_TGTLINKADDR, 108 NDOPT_FLAG_PREFIXINFO, NDOPT_FLAG_RDHDR, NDOPT_FLAG_MTU 109 }; 110 111 int main __P((int, char *[])); 112 static void sock_open __P((void)); 113 static void rtsock_open __P((void)); 114 static void rtadvd_input __P((void)); 115 static void rs_input __P((int, struct nd_router_solicit *, 116 struct in6_pktinfo *, struct sockaddr_in6 *)); 117 static void ra_input __P((int, struct nd_router_advert *, 118 struct in6_pktinfo *, struct sockaddr_in6 *)); 119 static void prefix_check __P((struct nd_opt_prefix_info *, struct rainfo *, 120 struct sockaddr_in6 *)); 121 static int nd6_options __P((struct nd_opt_hdr *, int, 122 union nd_opts *, u_int32_t)); 123 static void free_ndopts __P((union nd_opts *)); 124 static struct rainfo *if_indextorainfo __P((int)); 125 static void ra_output __P((struct rainfo *)); 126 static void rtmsg_input __P((void)); 127 struct prefix *find_prefix __P((struct rainfo *, struct in6_addr *, int)); 128 129 130 int 131 main(argc, argv) 132 int argc; 133 char *argv[]; 134 { 135 fd_set fdset; 136 int maxfd = 0; 137 struct timeval *timeout; 138 int i, ch; 139 int fflag = 0; 140 141 openlog(*argv, LOG_NDELAY|LOG_PID, LOG_DAEMON); 142 143 /* get command line options and arguments */ 144 while ((ch = getopt(argc, argv, "c:dDfs")) != -1) { 145 switch(ch) { 146 case 'c': 147 conffile = optarg; 148 break; 149 case 'd': 150 dflag = 1; 151 break; 152 case 'D': 153 dflag = 2; 154 break; 155 case 'f': 156 fflag = 1; 157 break; 158 case 's': 159 sflag = 1; 160 } 161 } 162 argc -= optind; 163 argv += optind; 164 if (argc == 0) { 165 fprintf(stderr, 166 "usage: rtadvd [-c conffile] [-d|D] [-f] [-s]" 167 "interfaces...\n"); 168 exit(1); 169 } 170 171 /* set log level */ 172 if (dflag == 0) 173 (void)setlogmask(LOG_UPTO(LOG_ERR)); 174 if (dflag == 1) 175 (void)setlogmask(LOG_UPTO(LOG_INFO)); 176 177 /* timer initialization */ 178 rtadvd_timer_init(); 179 180 /* random value initialization */ 181 srandom((u_long)time(NULL)); 182 183 /* get iflist block from kernel */ 184 init_iflist(); 185 186 while (argc--) 187 getconfig(*argv++); 188 189 if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1) { 190 fprintf(stderr, "fatal: inet_pton failed\n"); 191 exit(1); 192 } 193 sock_open(); 194 195 if (!fflag) 196 daemon(1, 0); 197 198 FD_ZERO(&fdset); 199 FD_SET(sock, &fdset); 200 maxfd = sock; 201 if (sflag == 0) { 202 rtsock_open(); 203 FD_SET(rtsock, &fdset); 204 if (rtsock > sock) 205 maxfd = rtsock; 206 } 207 208 while (1) { 209 struct fd_set select_fd = fdset; /* reinitialize */ 210 211 /* timer expiration check and reset the timer */ 212 timeout = rtadvd_check_timer(); 213 214 syslog(LOG_DEBUG, 215 "<%s> set timer to %ld:%ld. waiting for inputs " 216 "or timeout", 217 __FUNCTION__, 218 timeout->tv_sec, timeout->tv_usec); 219 220 if ((i = select(maxfd + 1, &select_fd, 221 NULL, NULL, timeout)) < 0){ 222 syslog(LOG_ERR, "<%s> select: %s", 223 __FUNCTION__, strerror(errno)); 224 continue; 225 } 226 if (i == 0) /* timeout */ 227 continue; 228 if (sflag == 0 && FD_ISSET(rtsock, &select_fd)) 229 rtmsg_input(); 230 if (FD_ISSET(sock, &select_fd)) 231 rtadvd_input(); 232 } 233 exit(0); /* NOTREACHED */ 234 } 235 236 static void 237 rtmsg_input() 238 { 239 int n, type, ifindex, plen; 240 size_t len; 241 char msg[2048], *next, *lim; 242 u_char ifname[16]; 243 struct prefix *prefix; 244 struct rainfo *rai; 245 struct in6_addr *addr; 246 char addrbuf[INET6_ADDRSTRLEN]; 247 248 n = read(rtsock, msg, 2048); 249 if (dflag > 1) { 250 syslog(LOG_DEBUG, 251 "<%s> received a routing message " 252 "(type = %d, len = %d)", 253 __FUNCTION__, 254 rtmsg_type(msg), n); 255 } 256 if (n > rtmsg_len(msg)) { 257 /* 258 * This usually won't happen for messages received on 259 * an routing socket. 260 */ 261 if (dflag > 1) 262 syslog(LOG_DEBUG, 263 "<%s> received data length is larger than" 264 "1st routing message len. multiple messages?" 265 " read %d bytes, but 1st msg len = %d", 266 __FUNCTION__, n, rtmsg_len(msg)); 267 #if 0 268 /* adjust length */ 269 n = rtmsg_len(msg); 270 #endif 271 } 272 273 lim = msg + n; 274 for (next = msg; next < lim; next += len) { 275 next = get_next_msg(next, lim, 0, &len, 276 RTADV_TYPE2BITMASK(RTM_ADD) | 277 RTADV_TYPE2BITMASK(RTM_DELETE) | 278 RTADV_TYPE2BITMASK(RTM_NEWADDR) | 279 RTADV_TYPE2BITMASK(RTM_DELADDR) | 280 RTADV_TYPE2BITMASK(RTM_IFINFO)); 281 if (len == 0) 282 break; 283 type = rtmsg_type(next); 284 switch (type) { 285 case RTM_ADD: 286 case RTM_DELETE: 287 ifindex = get_rtm_ifindex(next); 288 break; 289 case RTM_NEWADDR: 290 case RTM_DELADDR: 291 ifindex = get_ifam_ifindex(next); 292 break; 293 case RTM_IFINFO: 294 ifindex = get_ifm_ifindex(next); 295 break; 296 default: 297 /* should not reach here */ 298 if (dflag > 1) { 299 syslog(LOG_DEBUG, 300 "<%s:%d> unknown rtmsg %d on %s", 301 __FUNCTION__, __LINE__, type, 302 if_indextoname(ifindex, ifname)); 303 } 304 return; 305 } 306 307 if ((rai = if_indextorainfo(ifindex)) == NULL) { 308 if (dflag > 1) { 309 syslog(LOG_DEBUG, 310 "<%s> route changed on " 311 "non advertising interface(%s)", 312 __FUNCTION__, 313 if_indextoname(ifindex, ifname)); 314 } 315 return; 316 } 317 318 switch(type) { 319 case RTM_ADD: 320 /* init iffalgs because it may have changed */ 321 iflist[ifindex]->ifm_flags = 322 if_getflags(ifindex, 323 iflist[ifindex]->ifm_flags); 324 325 addr = get_addr(msg); 326 plen = get_prefixlen(msg); 327 /* sanity check for plen */ 328 if (plen < 4 /* as RFC2373, prefixlen is at least 4 */ 329 || plen > 127) { 330 syslog(LOG_INFO, "<%s> new interface route's" 331 "plen %d is invalid for a prefix", 332 __FUNCTION__, plen); 333 return; 334 } 335 prefix = find_prefix(rai, addr, plen); 336 if (prefix) { 337 if (dflag > 1) { 338 syslog(LOG_DEBUG, 339 "<%s> new prefix(%s/%d) " 340 "added on %s, " 341 "but it was already in list", 342 __FUNCTION__, 343 inet_ntop(AF_INET6, 344 addr, (char *)addrbuf, 345 INET6_ADDRSTRLEN), 346 plen, 347 rai->ifname); 348 } 349 return; 350 } 351 make_prefix(rai, ifindex, addr, plen); 352 break; 353 case RTM_DELETE: 354 /* init ifflags because it may have changed */ 355 iflist[ifindex]->ifm_flags = 356 if_getflags(ifindex, 357 iflist[ifindex]->ifm_flags); 358 359 addr = get_addr(msg); 360 plen = get_prefixlen(msg); 361 /* sanity check for plen */ 362 if (plen < 4 /* as RFC2373, prefixlen is at least 4 */ 363 || plen > 127) { 364 syslog(LOG_INFO, "<%s> deleted interface" 365 "route's" 366 "plen %d is invalid for a prefix", 367 __FUNCTION__, plen); 368 return; 369 } 370 prefix = find_prefix(rai, addr, plen); 371 if (prefix == NULL) { 372 if (dflag > 1) { 373 syslog(LOG_DEBUG, 374 "<%s> prefix(%s/%d) was " 375 "deleted on %s, " 376 "but it was not in list", 377 __FUNCTION__, 378 inet_ntop(AF_INET6, 379 addr, (char *)addrbuf, 380 INET6_ADDRSTRLEN), 381 plen, 382 rai->ifname); 383 } 384 return; 385 } 386 delete_prefix(rai, prefix); 387 break; 388 case RTM_NEWADDR: 389 case RTM_DELADDR: 390 /* init ifflags because it may have changed */ 391 iflist[ifindex]->ifm_flags = 392 if_getflags(ifindex, 393 iflist[ifindex]->ifm_flags); 394 break; 395 case RTM_IFINFO: 396 iflist[ifindex]->ifm_flags = get_ifm_flags(next); 397 break; 398 default: 399 /* should not reach here */ 400 if (dflag > 1) { 401 syslog(LOG_DEBUG, 402 "<%s:%d> unknown rtmsg %d on %s", 403 __FUNCTION__, __LINE__, type, 404 if_indextoname(ifindex, ifname)); 405 } 406 return; 407 } 408 } 409 410 return; 411 } 412 413 void 414 rtadvd_input() 415 { 416 int i; 417 int *hlimp = NULL; 418 #ifdef OLDRAWSOCKET 419 struct ip6_hdr *ip; 420 #endif 421 struct icmp6_hdr *icp; 422 int ifindex = 0; 423 struct cmsghdr *cm; 424 struct in6_pktinfo *pi = NULL; 425 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 426 struct in6_addr dst = in6addr_any; 427 428 /* 429 * Get message. We reset msg_controllen since the field could 430 * be modified if we had received a message before setting 431 * receive options. 432 */ 433 rcvmhdr.msg_controllen = sizeof(rcvcmsgbuf); 434 if ((i = recvmsg(sock, &rcvmhdr, 0)) < 0) 435 return; 436 437 /* extract optional information via Advanced API */ 438 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); 439 cm; 440 cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) { 441 if (cm->cmsg_level == IPPROTO_IPV6 && 442 cm->cmsg_type == IPV6_PKTINFO && 443 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 444 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 445 ifindex = pi->ipi6_ifindex; 446 dst = pi->ipi6_addr; 447 } 448 if (cm->cmsg_level == IPPROTO_IPV6 && 449 cm->cmsg_type == IPV6_HOPLIMIT && 450 cm->cmsg_len == CMSG_LEN(sizeof(int))) 451 hlimp = (int *)CMSG_DATA(cm); 452 } 453 if (ifindex == 0) { 454 syslog(LOG_ERR, 455 "<%s> failed to get receiving interface", 456 __FUNCTION__); 457 return; 458 } 459 if (hlimp == NULL) { 460 syslog(LOG_ERR, 461 "<%s> failed to get receiving hop limit", 462 __FUNCTION__); 463 return; 464 } 465 466 #ifdef OLDRAWSOCKET 467 if (i < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) { 468 syslog(LOG_ERR, 469 "<%s> packet size(%d) is too short", 470 __FUNCTION__, i); 471 return; 472 } 473 474 ip = (struct ip6_hdr *)rcvmhdr.msg_iov[0].iov_base; 475 icp = (struct icmp6_hdr *)(ip + 1); /* XXX: ext. hdr? */ 476 #else 477 if (i < sizeof(struct icmp6_hdr)) { 478 syslog(LOG_ERR, 479 "<%s> packet size(%d) is too short", 480 __FUNCTION__, i); 481 return; 482 } 483 484 icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; 485 #endif 486 487 switch(icp->icmp6_type) { 488 case ND_ROUTER_SOLICIT: 489 /* 490 * Message verification - RFC-2461 6.1.1 491 * XXX: these checks must be done in the kernel as well, 492 * but we can't completely rely on them. 493 */ 494 if (*hlimp != 255) { 495 syslog(LOG_NOTICE, 496 "<%s> RS with invalid hop limit(%d) " 497 "received from %s on %s", 498 __FUNCTION__, *hlimp, 499 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 500 INET6_ADDRSTRLEN), 501 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 502 return; 503 } 504 if (icp->icmp6_code) { 505 syslog(LOG_NOTICE, 506 "<%s> RS with invalid ICMP6 code(%d) " 507 "received from %s on %s", 508 __FUNCTION__, icp->icmp6_code, 509 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 510 INET6_ADDRSTRLEN), 511 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 512 return; 513 } 514 if (i < sizeof(struct nd_router_solicit)) { 515 syslog(LOG_NOTICE, 516 "<%s> RS from %s on %s does not have enough " 517 "length (len = %d)", 518 __FUNCTION__, 519 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 520 INET6_ADDRSTRLEN), 521 if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); 522 return; 523 } 524 rs_input(i, (struct nd_router_solicit *)icp, pi, &from); 525 break; 526 case ND_ROUTER_ADVERT: 527 /* 528 * Message verification - RFC-2461 6.1.2 529 * XXX: there's a same dilemma as above... 530 */ 531 if (*hlimp != 255) { 532 syslog(LOG_NOTICE, 533 "<%s> RA with invalid hop limit(%d) " 534 "received from %s on %s", 535 __FUNCTION__, *hlimp, 536 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 537 INET6_ADDRSTRLEN), 538 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 539 return; 540 } 541 if (icp->icmp6_code) { 542 syslog(LOG_NOTICE, 543 "<%s> RA with invalid ICMP6 code(%d) " 544 "received from %s on %s", 545 __FUNCTION__, icp->icmp6_code, 546 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 547 INET6_ADDRSTRLEN), 548 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 549 return; 550 } 551 if (i < sizeof(struct nd_router_advert)) { 552 syslog(LOG_NOTICE, 553 "<%s> RA from %s on %s does not have enough " 554 "length (len = %d)", 555 __FUNCTION__, 556 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 557 INET6_ADDRSTRLEN), 558 if_indextoname(pi->ipi6_ifindex, ifnamebuf), i); 559 return; 560 } 561 ra_input(i, (struct nd_router_advert *)icp, pi, &from); 562 break; 563 case ICMP6_ROUTER_RENUMBERING: 564 if (accept_rr == 0) { 565 syslog(LOG_ERR, 566 "<%s> received a router renumbering " 567 "message, but not allowed to be accepted", 568 __FUNCTION__); 569 break; 570 } 571 rr_input(i, (struct icmp6_router_renum *)icp, pi, &from, 572 &dst); 573 break; 574 default: 575 /* 576 * Note that this case is POSSIBLE, especially just 577 * after invocation of the daemon. This is because we 578 * could receive message after opening the socket and 579 * before setting ICMP6 type filter(see sock_open()). 580 */ 581 syslog(LOG_ERR, 582 "<%s> invalid icmp type(%d)", 583 __FUNCTION__, icp->icmp6_type); 584 return; 585 } 586 587 return; 588 } 589 590 static void 591 rs_input(int len, struct nd_router_solicit *rs, 592 struct in6_pktinfo *pi, struct sockaddr_in6 *from) 593 { 594 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 595 union nd_opts ndopts; 596 struct rainfo *ra; 597 598 syslog(LOG_DEBUG, 599 "<%s> RS received from %s on %s", 600 __FUNCTION__, 601 inet_ntop(AF_INET6, &from->sin6_addr, 602 ntopbuf, INET6_ADDRSTRLEN), 603 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 604 605 /* ND option check */ 606 memset(&ndopts, 0, sizeof(ndopts)); 607 if (nd6_options((struct nd_opt_hdr *)(rs + 1), 608 len - sizeof(struct nd_router_solicit), 609 &ndopts, NDOPT_FLAG_SRCLINKADDR)) { 610 syslog(LOG_DEBUG, 611 "<%s> ND option check failed for an RS from %s on %s", 612 __FUNCTION__, 613 inet_ntop(AF_INET6, &from->sin6_addr, 614 ntopbuf, INET6_ADDRSTRLEN), 615 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 616 return; 617 } 618 619 /* 620 * If the IP source address is the unspecified address, there 621 * must be no source link-layer address option in the message. 622 * (RFC-2461 6.1.1) 623 */ 624 if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) && 625 ndopts.nd_opts_src_lladdr) { 626 syslog(LOG_ERR, 627 "<%s> RS from unspecified src on %s has a link-layer" 628 " address option", 629 __FUNCTION__, 630 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 631 goto done; 632 } 633 634 ra = ralist; 635 while (ra != NULL) { 636 if (pi->ipi6_ifindex == ra->ifindex) 637 break; 638 ra = ra->next; 639 } 640 if (ra == NULL) { 641 syslog(LOG_INFO, 642 "<%s> RS received on non advertising interface(%s)", 643 __FUNCTION__, 644 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 645 goto done; 646 } 647 648 /* 649 * Decide whether to send RA according to the rate-limit 650 * consideration. 651 */ 652 { 653 long delay; /* must not be greater than 1000000 */ 654 struct timeval interval, now, min_delay, tm_tmp, *rest; 655 656 /* 657 * If there is already a waiting RS packet, don't 658 * update the timer. 659 */ 660 if (ra->waiting++) 661 goto done; 662 663 /* 664 * Compute a random delay. If the computed value 665 * corresponds to a time later than the time the next 666 * multicast RA is scheduled to be sent, ignore the random 667 * delay and send the advertisement at the 668 * already-scheduled time. RFC-2461 6.2.6 669 */ 670 delay = random() % MAX_RA_DELAY_TIME; 671 interval.tv_sec = 0; 672 interval.tv_usec = delay; 673 rest = rtadvd_timer_rest(ra->timer); 674 if (TIMEVAL_LT(*rest, interval)) { 675 syslog(LOG_DEBUG, 676 "<%s> random delay is larger than " 677 "the rest of normal timer", 678 __FUNCTION__); 679 interval = *rest; 680 } 681 682 /* 683 * If we sent a multicast Router Advertisement within 684 * the last MIN_DELAY_BETWEEN_RAS seconds, schedule 685 * the advertisement to be sent at a time corresponding to 686 * MIN_DELAY_BETWEEN_RAS plus the random value after the 687 * previous advertisement was sent. 688 */ 689 gettimeofday(&now, NULL); 690 TIMEVAL_SUB(&now, &ra->lastsent, &tm_tmp); 691 min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; 692 min_delay.tv_usec = 0; 693 if (TIMEVAL_LT(tm_tmp, min_delay)) { 694 TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); 695 TIMEVAL_ADD(&min_delay, &interval, &interval); 696 } 697 rtadvd_set_timer(&interval, ra->timer); 698 goto done; 699 } 700 701 done: 702 free_ndopts(&ndopts); 703 return; 704 } 705 706 static void 707 ra_input(int len, struct nd_router_advert *ra, 708 struct in6_pktinfo *pi, struct sockaddr_in6 *from) 709 { 710 struct rainfo *rai; 711 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 712 union nd_opts ndopts; 713 char *on_off[] = {"OFF", "ON"}; 714 u_int32_t reachabletime, retranstimer, mtu; 715 716 syslog(LOG_DEBUG, 717 "<%s> RA received from %s on %s", 718 __FUNCTION__, 719 inet_ntop(AF_INET6, &from->sin6_addr, 720 ntopbuf, INET6_ADDRSTRLEN), 721 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 722 723 /* ND option check */ 724 memset(&ndopts, 0, sizeof(ndopts)); 725 if (nd6_options((struct nd_opt_hdr *)(ra + 1), 726 len - sizeof(struct nd_router_advert), 727 &ndopts, 728 NDOPT_FLAG_PREFIXINFO | NDOPT_FLAG_MTU)) { 729 syslog(LOG_ERR, 730 "<%s> ND option check failed for an RA from %s on %s", 731 __FUNCTION__, 732 inet_ntop(AF_INET6, &from->sin6_addr, 733 ntopbuf, INET6_ADDRSTRLEN), 734 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 735 return; 736 } 737 738 /* 739 * RA consistency check according to RFC-2461 6.2.7 740 */ 741 if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == 0) { 742 syslog(LOG_INFO, 743 "<%s> received RA from %s on non-advertising" 744 " interface(%s)", 745 __FUNCTION__, 746 inet_ntop(AF_INET6, &from->sin6_addr, 747 ntopbuf, INET6_ADDRSTRLEN), 748 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 749 goto done; 750 } 751 /* Cur Hop Limit value */ 752 if (ra->nd_ra_curhoplimit && rai->hoplimit && 753 ra->nd_ra_curhoplimit != rai->hoplimit) { 754 syslog(LOG_WARNING, 755 "<%s> CurHopLimit inconsistent on %s:" 756 " %d from %s, %d from us", 757 __FUNCTION__, 758 rai->ifname, 759 ra->nd_ra_curhoplimit, 760 inet_ntop(AF_INET6, &from->sin6_addr, 761 ntopbuf, INET6_ADDRSTRLEN), 762 rai->hoplimit); 763 } 764 /* M flag */ 765 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) != 766 rai->managedflg) { 767 syslog(LOG_WARNING, 768 "<%s> M flag inconsistent on %s:" 769 " %s from %s, %s from us", 770 __FUNCTION__, 771 rai->ifname, 772 on_off[!rai->managedflg], 773 inet_ntop(AF_INET6, &from->sin6_addr, 774 ntopbuf, INET6_ADDRSTRLEN), 775 on_off[rai->managedflg]); 776 } 777 /* O flag */ 778 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) != 779 rai->otherflg) { 780 syslog(LOG_WARNING, 781 "<%s> O flag inconsistent on %s:" 782 " %s from %s, %s from us", 783 __FUNCTION__, 784 rai->ifname, 785 on_off[!rai->otherflg], 786 inet_ntop(AF_INET6, &from->sin6_addr, 787 ntopbuf, INET6_ADDRSTRLEN), 788 on_off[rai->otherflg]); 789 } 790 /* Reachable Time */ 791 reachabletime = ntohl(ra->nd_ra_reachable); 792 if (reachabletime && rai->reachabletime && 793 reachabletime != rai->reachabletime) { 794 syslog(LOG_WARNING, 795 "<%s> ReachableTime inconsistent on %s:" 796 " %d from %s, %d from us", 797 __FUNCTION__, 798 rai->ifname, 799 reachabletime, 800 inet_ntop(AF_INET6, &from->sin6_addr, 801 ntopbuf, INET6_ADDRSTRLEN), 802 rai->reachabletime); 803 } 804 /* Retrans Timer */ 805 retranstimer = ntohl(ra->nd_ra_retransmit); 806 if (retranstimer && rai->retranstimer && 807 retranstimer != rai->retranstimer) { 808 syslog(LOG_WARNING, 809 "<%s> RetranceTimer inconsistent on %s:" 810 " %d from %s, %d from us", 811 __FUNCTION__, 812 rai->ifname, 813 retranstimer, 814 inet_ntop(AF_INET6, &from->sin6_addr, 815 ntopbuf, INET6_ADDRSTRLEN), 816 rai->retranstimer); 817 } 818 /* Values in the MTU options */ 819 if (ndopts.nd_opts_mtu) { 820 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu); 821 if (mtu && rai->linkmtu && mtu != rai->linkmtu) { 822 syslog(LOG_WARNING, 823 "<%s> MTU option value inconsistent on %s:" 824 " %d from %s, %d from us", 825 __FUNCTION__, 826 rai->ifname, mtu, 827 inet_ntop(AF_INET6, &from->sin6_addr, 828 ntopbuf, INET6_ADDRSTRLEN), 829 rai->linkmtu); 830 } 831 } 832 /* Preferred and Valid Lifetimes for prefixes */ 833 { 834 struct nd_optlist *optp = ndopts.nd_opts_list; 835 836 if (ndopts.nd_opts_pi) 837 prefix_check(ndopts.nd_opts_pi, rai, from); 838 while (optp) { 839 prefix_check((struct nd_opt_prefix_info *)optp->opt, 840 rai, from); 841 optp = optp->next; 842 } 843 } 844 845 done: 846 free_ndopts(&ndopts); 847 return; 848 } 849 850 static void 851 prefix_check(struct nd_opt_prefix_info *pinfo, 852 struct rainfo *rai, struct sockaddr_in6 *from) 853 { 854 u_int32_t preferred_time, valid_time; 855 struct prefix *pp; 856 u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN]; 857 858 #if 0 /* impossible */ 859 if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION) 860 return; 861 #endif 862 863 /* 864 * log if the adveritsed prefix has link-local scope(sanity check?) 865 */ 866 if (IN6_IS_ADDR_LINKLOCAL(&pinfo->nd_opt_pi_prefix)) { 867 syslog(LOG_INFO, 868 "<%s> link-local prefix %s/%d is advertised " 869 "from %s on %s", 870 __FUNCTION__, 871 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, 872 prefixbuf, INET6_ADDRSTRLEN), 873 pinfo->nd_opt_pi_prefix_len, 874 inet_ntop(AF_INET6, &from->sin6_addr, 875 ntopbuf, INET6_ADDRSTRLEN), 876 rai->ifname); 877 } 878 879 if ((pp = find_prefix(rai, &pinfo->nd_opt_pi_prefix, 880 pinfo->nd_opt_pi_prefix_len)) == NULL) { 881 syslog(LOG_INFO, 882 "<%s> prefix %s/%d from %s on %s is not in our list", 883 __FUNCTION__, 884 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, 885 prefixbuf, INET6_ADDRSTRLEN), 886 pinfo->nd_opt_pi_prefix_len, 887 inet_ntop(AF_INET6, &from->sin6_addr, 888 ntopbuf, INET6_ADDRSTRLEN), 889 rai->ifname); 890 return; 891 } 892 893 preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time); 894 if (preferred_time != pp->preflifetime) 895 syslog(LOG_WARNING, 896 "<%s> prefeerred lifetime for %s/%d" 897 " inconsistent on %s:" 898 " %d from %s, %d from us", 899 __FUNCTION__, 900 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, 901 prefixbuf, INET6_ADDRSTRLEN), 902 pinfo->nd_opt_pi_prefix_len, 903 rai->ifname, preferred_time, 904 inet_ntop(AF_INET6, &from->sin6_addr, 905 ntopbuf, INET6_ADDRSTRLEN), 906 pp->preflifetime); 907 908 valid_time = ntohl(pinfo->nd_opt_pi_valid_time); 909 if (valid_time != pp->validlifetime) 910 syslog(LOG_WARNING, 911 "<%s> valid lifetime for %s/%d" 912 " inconsistent on %s:" 913 " %d from %s, %d from us", 914 __FUNCTION__, 915 inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, 916 prefixbuf, INET6_ADDRSTRLEN), 917 pinfo->nd_opt_pi_prefix_len, 918 rai->ifname, valid_time, 919 inet_ntop(AF_INET6, &from->sin6_addr, 920 ntopbuf, INET6_ADDRSTRLEN), 921 pp->validlifetime); 922 } 923 924 struct prefix * 925 find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen) 926 { 927 struct prefix *pp; 928 int bytelen, bitlen; 929 930 for (pp = rai->prefix.next; pp != &rai->prefix; pp = pp->next) { 931 if (plen != pp->prefixlen) 932 continue; 933 bytelen = plen / 8; 934 bitlen = plen % 8; 935 if (memcmp((void *)prefix, (void *)&pp->prefix, bytelen)) 936 continue; 937 if (prefix->s6_addr[bytelen] >> (8 - bitlen) == 938 pp->prefix.s6_addr[bytelen] >> (8 - bitlen)) 939 return(pp); 940 } 941 942 return(NULL); 943 } 944 945 static int 946 nd6_options(struct nd_opt_hdr *hdr, int limit, 947 union nd_opts *ndopts, u_int32_t optflags) 948 { 949 int optlen = 0; 950 951 for (; limit > 0; limit -= optlen) { 952 hdr = (struct nd_opt_hdr *)((caddr_t)hdr + optlen); 953 optlen = hdr->nd_opt_len << 3; 954 if (hdr->nd_opt_len == 0) { 955 syslog(LOG_ERR, 956 "<%s> bad ND option length(0) (type = %d)", 957 __FUNCTION__, hdr->nd_opt_type); 958 goto bad; 959 } 960 961 if (hdr->nd_opt_type > ND_OPT_MTU) { 962 syslog(LOG_INFO, 963 "<%s> unknown ND option(type %d)", 964 __FUNCTION__, 965 hdr->nd_opt_type); 966 continue; 967 } 968 969 if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) { 970 syslog(LOG_INFO, 971 "<%s> unexpected ND option(type %d)", 972 __FUNCTION__, 973 hdr->nd_opt_type); 974 continue; 975 } 976 977 switch(hdr->nd_opt_type) { 978 case ND_OPT_SOURCE_LINKADDR: 979 case ND_OPT_TARGET_LINKADDR: 980 case ND_OPT_REDIRECTED_HEADER: 981 case ND_OPT_MTU: 982 if (ndopts->nd_opt_array[hdr->nd_opt_type]) { 983 syslog(LOG_INFO, 984 "<%s> duplicated ND option" 985 " (type = %d)", 986 __FUNCTION__, 987 hdr->nd_opt_type); 988 } 989 ndopts->nd_opt_array[hdr->nd_opt_type] = hdr; 990 break; 991 case ND_OPT_PREFIX_INFORMATION: 992 { 993 struct nd_optlist *pfxlist; 994 995 if (ndopts->nd_opts_pi == 0) { 996 ndopts->nd_opts_pi = 997 (struct nd_opt_prefix_info *)hdr; 998 continue; 999 } 1000 if ((pfxlist = malloc(sizeof(*pfxlist))) == NULL) { 1001 syslog(LOG_ERR, 1002 "<%s> can't allocate memory", 1003 __FUNCTION__); 1004 goto bad; 1005 } 1006 pfxlist->next = ndopts->nd_opts_list; 1007 pfxlist->opt = hdr; 1008 ndopts->nd_opts_list = pfxlist; 1009 1010 break; 1011 } 1012 default: /* impossible */ 1013 break; 1014 } 1015 } 1016 1017 return(0); 1018 1019 bad: 1020 free_ndopts(ndopts); 1021 1022 return(-1); 1023 } 1024 1025 static void 1026 free_ndopts(union nd_opts *ndopts) 1027 { 1028 struct nd_optlist *opt = ndopts->nd_opts_list, *next; 1029 1030 while(opt) { 1031 next = opt->next; 1032 free(opt); 1033 opt = next; 1034 } 1035 } 1036 1037 void 1038 sock_open() 1039 { 1040 struct icmp6_filter filt; 1041 struct ipv6_mreq mreq; 1042 struct rainfo *ra = ralist; 1043 int on; 1044 /* XXX: should be max MTU attached to the node */ 1045 static u_char answer[1500]; 1046 static u_char sndcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) + 1047 CMSG_SPACE(sizeof(int))]; 1048 1049 if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 1050 syslog(LOG_ERR, "<%s> socket: %s", __FUNCTION__, 1051 strerror(errno)); 1052 exit(1); 1053 } 1054 1055 /* specify to tell receiving interface */ 1056 on = 1; 1057 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 1058 sizeof(on)) < 0) { 1059 syslog(LOG_ERR, "<%s> IPV6_PKTINFO: %s", 1060 __FUNCTION__, strerror(errno)); 1061 exit(1); 1062 } 1063 1064 on = 1; 1065 /* specify to tell value of hoplimit field of received IP6 hdr */ 1066 if (setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 1067 sizeof(on)) < 0) { 1068 syslog(LOG_ERR, "<%s> IPV6_HOPLIMIT: %s", 1069 __FUNCTION__, strerror(errno)); 1070 exit(1); 1071 } 1072 1073 ICMP6_FILTER_SETBLOCKALL(&filt); 1074 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt); 1075 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); 1076 if (accept_rr) 1077 ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); 1078 if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 1079 sizeof(filt)) < 0) { 1080 syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", 1081 __FUNCTION__, strerror(errno)); 1082 exit(1); 1083 } 1084 1085 /* 1086 * join all routers multicast address on each advertising interface. 1087 */ 1088 if (inet_pton(AF_INET6, ALLROUTERS, &mreq.ipv6mr_multiaddr.s6_addr) 1089 != 1) { 1090 syslog(LOG_ERR, "<%s> inet_pton failed(library bug?)", 1091 __FUNCTION__); 1092 exit(1); 1093 } 1094 while(ra) { 1095 mreq.ipv6mr_interface = ra->ifindex; 1096 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 1097 &mreq, 1098 sizeof(mreq)) < 0) { 1099 syslog(LOG_ERR, "<%s> IPV6_JOIN_GROUP on %s: %s", 1100 __FUNCTION__, ra->ifname, strerror(errno)); 1101 exit(1); 1102 } 1103 ra = ra->next; 1104 } 1105 1106 /* initialize msghdr for receiving packets */ 1107 rcviov[0].iov_base = (caddr_t)answer; 1108 rcviov[0].iov_len = sizeof(answer); 1109 rcvmhdr.msg_name = (caddr_t)&from; 1110 rcvmhdr.msg_namelen = sizeof(from); 1111 rcvmhdr.msg_iov = rcviov; 1112 rcvmhdr.msg_iovlen = 1; 1113 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 1114 rcvmhdr.msg_controllen = sizeof(rcvcmsgbuf); 1115 1116 /* initialize msghdr for sending packets */ 1117 sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 1118 sndmhdr.msg_iov = sndiov; 1119 sndmhdr.msg_iovlen = 1; 1120 sndmhdr.msg_control = (caddr_t)sndcmsgbuf; 1121 sndmhdr.msg_controllen = sizeof(sndcmsgbuf); 1122 1123 return; 1124 } 1125 1126 /* open a routing socket to watch the routing table */ 1127 static void 1128 rtsock_open() 1129 { 1130 if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 1131 syslog(LOG_ERR, 1132 "<%s> socket: %s", __FUNCTION__, strerror(errno)); 1133 exit(1); 1134 } 1135 } 1136 1137 static struct rainfo * 1138 if_indextorainfo(int index) 1139 { 1140 struct rainfo *rai = ralist; 1141 1142 for (rai = ralist; rai; rai = rai->next) { 1143 if (rai->ifindex == index) 1144 return(rai); 1145 } 1146 1147 return(NULL); /* search failed */ 1148 } 1149 1150 static void 1151 ra_output(rainfo) 1152 struct rainfo *rainfo; 1153 { 1154 int i; 1155 1156 struct cmsghdr *cm; 1157 struct in6_pktinfo *pi; 1158 1159 sndmhdr.msg_name = (caddr_t)&sin6_allnodes; 1160 sndmhdr.msg_iov[0].iov_base = (caddr_t)rainfo->ra_data; 1161 sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen; 1162 1163 cm = CMSG_FIRSTHDR(&sndmhdr); 1164 /* specify the outgoing interface */ 1165 cm->cmsg_level = IPPROTO_IPV6; 1166 cm->cmsg_type = IPV6_PKTINFO; 1167 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1168 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1169 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ 1170 pi->ipi6_ifindex = rainfo->ifindex; 1171 1172 /* specify the hop limit of the packet */ 1173 { 1174 int hoplimit = 255; 1175 1176 cm = CMSG_NXTHDR(&sndmhdr, cm); 1177 cm->cmsg_level = IPPROTO_IPV6; 1178 cm->cmsg_type = IPV6_HOPLIMIT; 1179 cm->cmsg_len = CMSG_LEN(sizeof(int)); 1180 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 1181 } 1182 1183 syslog(LOG_DEBUG, 1184 "<%s> send RA on %s, # of waitings = %d", 1185 __FUNCTION__, rainfo->ifname, rainfo->waiting); 1186 1187 i = sendmsg(sock, &sndmhdr, 0); 1188 1189 if (i < 0 || i != rainfo->ra_datalen) { 1190 if (i < 0) { 1191 syslog(LOG_ERR, "<%s> sendmsg on %s: %s", 1192 __FUNCTION__, rainfo->ifname, 1193 strerror(errno)); 1194 } 1195 } 1196 1197 /* update counter */ 1198 if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS) 1199 rainfo->initcounter++; 1200 1201 /* update timestamp */ 1202 gettimeofday(&rainfo->lastsent, NULL); 1203 1204 /* reset waiting conter */ 1205 rainfo->waiting = 0; 1206 } 1207 1208 /* process RA timer */ 1209 void 1210 ra_timeout(void *data) 1211 { 1212 struct rainfo *rai = (struct rainfo *)data; 1213 1214 #ifdef notyet 1215 /* if necessary, reconstruct the packet. */ 1216 #endif 1217 1218 syslog(LOG_DEBUG, 1219 "<%s> RA timer on %s is expired", 1220 __FUNCTION__, rai->ifname); 1221 1222 if (iflist[rai->ifindex]->ifm_flags & IFF_UP) 1223 ra_output(rai); 1224 else 1225 syslog(LOG_DEBUG, "<%s> %s is not up, skip sending RA", 1226 __FUNCTION__, rai->ifname); 1227 } 1228 1229 /* update RA timer */ 1230 void 1231 ra_timer_update(void *data, struct timeval *tm) 1232 { 1233 struct rainfo *rai = (struct rainfo *)data; 1234 long interval; 1235 1236 /* 1237 * Whenever a multicast advertisement is sent from an interface, 1238 * the timer is reset to a uniformly-distributed random value 1239 * between the interface's configured MinRtrAdvInterval and 1240 * MaxRtrAdvInterval(discovery-v2-02 6.2.4). 1241 */ 1242 interval = rai->mininterval; 1243 interval += random() % (rai->maxinterval - rai->mininterval); 1244 1245 /* 1246 * For the first few advertisements (up to 1247 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval 1248 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer 1249 * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead. 1250 * (RFC-2461 6.2.4) 1251 */ 1252 if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS && 1253 interval > MAX_INITIAL_RTR_ADVERT_INTERVAL) 1254 interval = MAX_INITIAL_RTR_ADVERT_INTERVAL; 1255 1256 tm->tv_sec = interval; 1257 tm->tv_usec = 0; 1258 1259 syslog(LOG_DEBUG, 1260 "<%s> RA timer on %s is set to %ld:%ld", 1261 __FUNCTION__, rai->ifname, tm->tv_sec, tm->tv_usec); 1262 1263 return; 1264 } 1265