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