1 /** 2 * Copyright (C) 2012-2013 Steven Barth <steven@midlink.org> 3 * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License v2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <signal.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <stdbool.h> 23 #include <arpa/inet.h> 24 #include <net/route.h> 25 26 #include <libubox/utils.h> 27 28 #include "router.h" 29 #include "odhcpd.h" 30 #include "statefiles.h" 31 32 33 static void forward_router_solicitation(const struct interface *iface); 34 static void forward_router_advertisement(const struct interface *iface, uint8_t *data, size_t len); 35 36 static void handle_icmpv6(void *addr, void *data, size_t len, 37 struct interface *iface, void *dest); 38 static void trigger_router_advert(struct uloop_timeout *event); 39 static void router_netevent_cb(unsigned long event, struct netevent_handler_info *info); 40 41 static struct netevent_handler router_netevent_handler = { .cb = router_netevent_cb, }; 42 43 static FILE *fp_route = NULL; 44 45 46 #define TIME_LEFT(t1, now) ((t1) != UINT32_MAX ? (t1) - (now) : UINT32_MAX) 47 48 /* Shutdown helper: close fp_route if open. Safe to call multiple times. */ 49 static void router_shutdown(void) 50 { 51 if (fp_route) { 52 fclose(fp_route); 53 fp_route = NULL; 54 } 55 } 56 57 int router_init(void) 58 { 59 int ret = 0; 60 61 if (!(fp_route = fopen("/proc/net/ipv6_route", "r"))) { 62 error("fopen(/proc/net/ipv6_route): %m"); 63 ret = -1; 64 goto out; 65 } 66 67 if (netlink_add_netevent_handler(&router_netevent_handler) < 0) { 68 error("Failed to add netevent handler"); 69 ret = -1; 70 } 71 72 atexit(router_shutdown); 73 74 out: 75 if (ret < 0) 76 router_shutdown(); 77 78 return ret; 79 } 80 81 82 int router_setup_interface(struct interface *iface, bool enable) 83 { 84 int ret = 0; 85 86 enable = enable && (iface->ra != MODE_DISABLED); 87 88 if (!fp_route) { 89 ret = -1; 90 goto out; 91 } 92 93 94 if (!enable && iface->router_event.uloop.fd >= 0) { 95 if (!iface->master) { 96 uloop_timeout_cancel(&iface->timer_rs); 97 iface->timer_rs.cb = NULL; 98 99 trigger_router_advert(&iface->timer_rs); 100 } 101 102 uloop_fd_delete(&iface->router_event.uloop); 103 close(iface->router_event.uloop.fd); 104 iface->router_event.uloop.fd = -1; 105 } else if (enable) { 106 struct icmp6_filter filt; 107 struct ipv6_mreq mreq; 108 int val = 2; 109 110 if (iface->router_event.uloop.fd < 0) { 111 /* Open ICMPv6 socket */ 112 iface->router_event.uloop.fd = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, 113 IPPROTO_ICMPV6); 114 if (iface->router_event.uloop.fd < 0) { 115 error("socket(AF_INET6): %m"); 116 ret = -1; 117 goto out; 118 } 119 120 if (setsockopt(iface->router_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE, 121 iface->ifname, strlen(iface->ifname)) < 0) { 122 error("setsockopt(SO_BINDTODEVICE): %m"); 123 ret = -1; 124 goto out; 125 } 126 127 /* Let the kernel compute our checksums */ 128 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_RAW, IPV6_CHECKSUM, 129 &val, sizeof(val)) < 0) { 130 error("setsockopt(IPV6_CHECKSUM): %m"); 131 ret = -1; 132 goto out; 133 } 134 135 /* This is required by RFC 4861 */ 136 val = 255; 137 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 138 &val, sizeof(val)) < 0) { 139 error("setsockopt(IPV6_MULTICAST_HOPS): %m"); 140 ret = -1; 141 goto out; 142 } 143 144 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 145 &val, sizeof(val)) < 0) { 146 error("setsockopt(IPV6_UNICAST_HOPS): %m"); 147 ret = -1; 148 goto out; 149 } 150 151 /* We need to know the source interface */ 152 val = 1; 153 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, 154 &val, sizeof(val)) < 0) { 155 error("setsockopt(IPV6_RECVPKTINFO): %m"); 156 ret = -1; 157 goto out; 158 } 159 160 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 161 &val, sizeof(val)) < 0) { 162 error("setsockopt(IPV6_RECVHOPLIMIT): %m"); 163 ret = -1; 164 goto out; 165 } 166 167 /* Don't loop back */ 168 val = 0; 169 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 170 &val, sizeof(val)) < 0) { 171 error("setsockopt(IPV6_MULTICAST_LOOP): %m"); 172 ret = -1; 173 goto out; 174 } 175 176 /* Filter ICMPv6 package types */ 177 ICMP6_FILTER_SETBLOCKALL(&filt); 178 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); 179 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt); 180 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_ICMPV6, ICMP6_FILTER, 181 &filt, sizeof(filt)) < 0) { 182 error("setsockopt(ICMP6_FILTER): %m"); 183 ret = -1; 184 goto out; 185 } 186 187 iface->router_event.handle_dgram = handle_icmpv6; 188 iface->ra_sent = 0; 189 odhcpd_register(&iface->router_event); 190 } else { 191 uloop_timeout_cancel(&iface->timer_rs); 192 iface->timer_rs.cb = NULL; 193 194 memset(&mreq, 0, sizeof(mreq)); 195 mreq.ipv6mr_interface = iface->ifindex; 196 inet_pton(AF_INET6, ALL_IPV6_NODES, &mreq.ipv6mr_multiaddr); 197 setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, 198 &mreq, sizeof(mreq)); 199 200 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &mreq.ipv6mr_multiaddr); 201 setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, 202 &mreq, sizeof(mreq)); 203 } 204 205 memset(&mreq, 0, sizeof(mreq)); 206 mreq.ipv6mr_interface = iface->ifindex; 207 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &mreq.ipv6mr_multiaddr); 208 209 if (iface->ra == MODE_RELAY && iface->master) { 210 inet_pton(AF_INET6, ALL_IPV6_NODES, &mreq.ipv6mr_multiaddr); 211 forward_router_solicitation(iface); 212 } else if (iface->ra == MODE_SERVER) { 213 iface->timer_rs.cb = trigger_router_advert; 214 uloop_timeout_set(&iface->timer_rs, 1000); 215 } 216 217 if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, 218 IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { 219 ret = -1; 220 error("setsockopt(IPV6_ADD_MEMBERSHIP): %m"); 221 goto out; 222 } 223 } 224 out: 225 if (ret < 0 && iface->router_event.uloop.fd >= 0) { 226 if (iface->router_event.uloop.registered) 227 uloop_fd_delete(&iface->router_event.uloop); 228 229 close(iface->router_event.uloop.fd); 230 iface->router_event.uloop.fd = -1; 231 } 232 233 return ret; 234 } 235 236 237 static void router_netevent_cb(unsigned long event, struct netevent_handler_info *info) 238 { 239 struct interface *iface; 240 241 switch (event) { 242 case NETEV_IFINDEX_CHANGE: 243 iface = info->iface; 244 if (iface && iface->router_event.uloop.fd >= 0) { 245 if (iface->router_event.uloop.registered) 246 uloop_fd_delete(&iface->router_event.uloop); 247 248 close(iface->router_event.uloop.fd); 249 iface->router_event.uloop.fd = -1; 250 } 251 break; 252 case NETEV_ROUTE6_ADD: 253 case NETEV_ROUTE6_DEL: 254 if (info->rt.dst_len) 255 break; 256 257 avl_for_each_element(&interfaces, iface, avl) { 258 if (iface->ra == MODE_SERVER && !iface->master) 259 uloop_timeout_set(&iface->timer_rs, 1000); 260 } 261 break; 262 case NETEV_ADDR6LIST_CHANGE: 263 iface = info->iface; 264 if (iface && iface->ra == MODE_SERVER && !iface->master) 265 uloop_timeout_set(&iface->timer_rs, 1000); 266 break; 267 default: 268 break; 269 } 270 } 271 272 273 static bool router_icmpv6_valid(struct sockaddr_in6 *source, uint8_t *data, size_t len) 274 { 275 struct icmp6_hdr *hdr = (struct icmp6_hdr *)data; 276 struct icmpv6_opt *opt, *end = (struct icmpv6_opt*)&data[len]; 277 278 /* Hoplimit is already checked in odhcpd_receive_packets */ 279 if (len < sizeof(*hdr) || hdr->icmp6_code) 280 return false; 281 282 switch (hdr->icmp6_type) { 283 case ND_ROUTER_ADVERT: 284 if (!IN6_IS_ADDR_LINKLOCAL(&source->sin6_addr)) 285 return false; 286 287 opt = (struct icmpv6_opt *)((struct nd_router_advert *)data + 1); 288 break; 289 290 case ND_ROUTER_SOLICIT: 291 opt = (struct icmpv6_opt *)((struct nd_router_solicit *)data + 1); 292 break; 293 294 default: 295 return false; 296 } 297 298 icmpv6_for_each_option(opt, opt, end) 299 if (opt->type == ND_OPT_SOURCE_LINKADDR && 300 IN6_IS_ADDR_UNSPECIFIED(&source->sin6_addr) && 301 hdr->icmp6_type == ND_ROUTER_SOLICIT) 302 return false; 303 304 /* Check all options parsed successfully */ 305 return opt == end; 306 } 307 308 309 /* Detect whether a default route exists, also find the source prefixes */ 310 static bool parse_routes(struct odhcpd_ipaddr *n, ssize_t len) 311 { 312 struct odhcpd_ipaddr p = { 313 .addr.in6 = IN6ADDR_ANY_INIT, 314 .prefix_len = 0, 315 .dprefix_len = 0, 316 .preferred_lt = 0, 317 .valid_lt = 0 318 }; 319 bool found_default = false; 320 char line[512], ifname[16]; 321 322 rewind(fp_route); 323 324 while (fgets(line, sizeof(line), fp_route)) { 325 uint32_t rflags; 326 if (sscanf(line, "00000000000000000000000000000000 00 " 327 "%*s %*s %*s %*s %*s %*s %*s %15s", ifname) && 328 strcmp(ifname, "lo")) { 329 found_default = true; 330 } else if (sscanf(line, "%8" SCNx32 "%8" SCNx32 "%*8" SCNx32 "%*8" SCNx32 " %hhx %*s " 331 "%*s 00000000000000000000000000000000 %*s %*s %*s %" SCNx32 " lo", 332 &p.addr.in6.s6_addr32[0], &p.addr.in6.s6_addr32[1], &p.prefix_len, &rflags) && 333 p.prefix_len > 0 && (rflags & RTF_NONEXTHOP) && (rflags & RTF_REJECT)) { 334 // Find source prefixes by scanning through unreachable-routes 335 p.addr.in6.s6_addr32[0] = htonl(p.addr.in6.s6_addr32[0]); 336 p.addr.in6.s6_addr32[1] = htonl(p.addr.in6.s6_addr32[1]); 337 338 for (ssize_t i = 0; i < len; ++i) { 339 if (n[i].prefix_len <= 64 && n[i].prefix_len >= p.prefix_len && 340 !odhcpd_bmemcmp(&p.addr.in6, &n[i].addr.in6, p.prefix_len)) { 341 n[i].dprefix_len = p.prefix_len; 342 break; 343 } 344 } 345 } 346 } 347 348 return found_default; 349 } 350 351 static int calc_adv_interval(struct interface *iface, uint32_t lowest_found_lifetime, 352 uint32_t *maxival) 353 { 354 uint32_t minival = iface->ra_mininterval; 355 int msecs; 356 357 *maxival = iface->ra_maxinterval; 358 359 if (*maxival > lowest_found_lifetime) 360 *maxival = lowest_found_lifetime; 361 362 odhcpd_urandom(&msecs, sizeof(msecs)); 363 msecs = (labs(msecs) % ((*maxival != minival) ? (*maxival - minival)*1000 : 500)) + 364 minival*1000; 365 366 /* RFC 2461 6.2.4 For the first MAX_INITIAL_RTR_ADVERTISEMENTS advertisements 367 * if the timer is bigger than MAX_INITIAL_RTR_ADVERT_INTERVAL it should be 368 * set to MAX_INITIAL_RTR_ADVERT_INTERVAL 369 * Off by one as an initial interval timer has already expired 370 */ 371 if ((iface->ra_sent + 1) < MaxInitialRtAdvs && msecs > MaxInitialRtrAdvInterval*1000) 372 msecs = MaxInitialRtrAdvInterval*1000; 373 374 return msecs; 375 } 376 377 static uint32_t calc_ra_lifetime(struct interface *iface, uint32_t maxival) 378 { 379 uint32_t lifetime = iface->max_preferred_lifetime; 380 381 if (iface->ra_lifetime > 0) { 382 lifetime = iface->ra_lifetime; 383 } 384 385 if (lifetime > 0 && lifetime < maxival) 386 lifetime = maxival; 387 else if (lifetime > RouterLifetime) 388 lifetime = RouterLifetime; 389 390 return lifetime; 391 } 392 393 enum { 394 IOV_RA_ADV=0, 395 IOV_RA_PFXS, 396 IOV_RA_ROUTES, 397 IOV_RA_DNS, 398 IOV_RA_SEARCH, 399 IOV_RA_PREF64, 400 IOV_RA_DNR, 401 IOV_RA_ADV_INTERVAL, 402 IOV_RA_CAPT_PORTAL, 403 IOV_RA_TOTAL, 404 }; 405 406 struct adv_msg { 407 struct nd_router_advert h; 408 struct icmpv6_opt lladdr; 409 struct nd_opt_mtu mtu; 410 }; 411 412 struct nd_opt_dns_server { 413 uint8_t type; 414 uint8_t len; 415 uint8_t pad; 416 uint8_t pad2; 417 uint32_t lifetime; 418 struct in6_addr addr[]; 419 }; 420 421 struct nd_opt_search_list { 422 uint8_t type; 423 uint8_t len; 424 uint16_t reserved; 425 uint32_t lifetime; 426 uint8_t name[]; 427 } _o_packed; 428 429 struct nd_opt_route_info { 430 uint8_t type; 431 uint8_t len; 432 uint8_t prefix_len; 433 uint8_t flags; 434 uint32_t lifetime; 435 uint32_t addr[4]; 436 }; 437 438 struct nd_opt_pref64_info { 439 uint8_t type; 440 uint8_t len; 441 uint16_t lifetime_plc; 442 uint32_t prefix[3]; 443 }; 444 445 struct nd_opt_dnr_info { 446 uint8_t type; 447 uint8_t len; 448 uint16_t priority; 449 uint32_t lifetime; 450 uint16_t adn_len; 451 uint8_t body[]; 452 }; 453 454 struct nd_opt_capt_portal { 455 uint8_t type; 456 uint8_t len; 457 uint8_t data[]; 458 }; 459 460 /* IPv6 RA PIOs */ 461 inline static int router_compare_pio_addr(const struct ra_pio *pio, const struct odhcpd_ipaddr *addr) 462 { 463 uint8_t cmp_len = max(64, max(pio->length, addr->prefix_len)); 464 465 return odhcpd_bmemcmp(&pio->prefix, &addr->addr.in6, cmp_len); 466 } 467 468 static struct ra_pio *router_find_ra_pio(struct interface *iface, 469 struct odhcpd_ipaddr *addr) 470 { 471 for (size_t i = 0; i < iface->pio_cnt; i++) { 472 struct ra_pio *cur_pio = &iface->pios[i]; 473 474 if (!router_compare_pio_addr(cur_pio, addr)) 475 return cur_pio; 476 } 477 478 return NULL; 479 } 480 481 static void router_add_ra_pio(struct interface *iface, 482 struct odhcpd_ipaddr *addr) 483 { 484 char ipv6_str[INET6_ADDRSTRLEN]; 485 struct ra_pio *new_pios, *pio; 486 487 pio = router_find_ra_pio(iface, addr); 488 if (pio) { 489 if (memcmp(&pio->prefix, &addr->addr.in6, sizeof(struct in6_addr)) != 0 || 490 pio->length != addr->prefix_len) 491 { 492 char new_ipv6_str[INET6_ADDRSTRLEN]; 493 494 iface->pio_update = true; 495 warn("rfc9096: %s: changed %s/%u -> %s/%u", 496 iface->ifname, 497 inet_ntop(AF_INET6, &pio->prefix, ipv6_str, sizeof(ipv6_str)), 498 pio->length, 499 inet_ntop(AF_INET6, &addr->addr.in6, new_ipv6_str, sizeof(new_ipv6_str)), 500 addr->prefix_len); 501 502 memcpy(&pio->prefix, &addr->addr.in6, sizeof(struct in6_addr)); 503 pio->length = addr->prefix_len; 504 } 505 506 if (pio->lifetime) { 507 pio->lifetime = 0; 508 509 iface->pio_update = true; 510 warn("rfc9096: %s: renew %s/%u", 511 iface->ifname, 512 inet_ntop(AF_INET6, &pio->prefix, ipv6_str, sizeof(ipv6_str)), 513 pio->length); 514 } 515 516 return; 517 } 518 519 new_pios = realloc(iface->pios, sizeof(struct ra_pio) * (iface->pio_cnt + 1)); 520 if (!new_pios) 521 return; 522 523 iface->pios = new_pios; 524 pio = &iface->pios[iface->pio_cnt]; 525 iface->pio_cnt++; 526 527 memcpy(&pio->prefix, &addr->addr.in6, sizeof(struct in6_addr)); 528 pio->length = addr->prefix_len; 529 pio->lifetime = 0; 530 531 iface->pio_update = true; 532 info("rfc9096: %s: add %s/%u", 533 iface->ifname, 534 inet_ntop(AF_INET6, &pio->prefix, ipv6_str, sizeof(ipv6_str)), 535 pio->length); 536 } 537 538 static void router_clear_duplicated_ra_pio(struct interface *iface) 539 { 540 size_t pio_cnt = iface->pio_cnt; 541 char ipv6_str[INET6_ADDRSTRLEN]; 542 543 for (size_t i = 0; i < iface->pio_cnt; i++) { 544 struct ra_pio *pio_a = &iface->pios[i]; 545 size_t j = i + 1; 546 547 while (j < iface->pio_cnt) { 548 struct ra_pio *pio_b = &iface->pios[j]; 549 550 if (pio_a->length == pio_b->length && 551 !memcmp(&pio_a->prefix, &pio_b->prefix, sizeof(struct in6_addr))) { 552 warn("rfc9096: %s: clear duplicated %s/%u", 553 iface->ifname, 554 inet_ntop(AF_INET6, &pio_a->prefix, ipv6_str, sizeof(ipv6_str)), 555 pio_a->length); 556 557 iface->pios[j] = iface->pios[iface->pio_cnt - 1]; 558 iface->pio_cnt--; 559 } else { 560 j++; 561 } 562 } 563 } 564 565 if (iface->pio_cnt != pio_cnt) { 566 struct ra_pio *new_pios = realloc(iface->pios, sizeof(struct ra_pio) * iface->pio_cnt); 567 568 if (new_pios) 569 iface->pios = new_pios; 570 } 571 } 572 573 static void router_clear_expired_ra_pio(time_t now, 574 struct interface *iface) 575 { 576 size_t i = 0, pio_cnt = iface->pio_cnt; 577 char ipv6_str[INET6_ADDRSTRLEN]; 578 579 while (i < iface->pio_cnt) { 580 struct ra_pio *cur_pio = &iface->pios[i]; 581 582 if (ra_pio_expired(cur_pio, now)) { 583 info("rfc9096: %s: clear expired %s/%u", 584 iface->ifname, 585 inet_ntop(AF_INET6, &cur_pio->prefix, ipv6_str, sizeof(ipv6_str)), 586 cur_pio->length); 587 588 iface->pios[i] = iface->pios[iface->pio_cnt - 1]; 589 iface->pio_cnt--; 590 } else { 591 i++; 592 } 593 } 594 595 if (!iface->pio_cnt) { 596 free(iface->pios); 597 iface->pios = NULL; 598 } else if (iface->pio_cnt != pio_cnt) { 599 struct ra_pio *new_pios = realloc(iface->pios, sizeof(struct ra_pio) * iface->pio_cnt); 600 601 if (new_pios) 602 iface->pios = new_pios; 603 } 604 } 605 606 static void router_stale_ra_pio(struct interface *iface, 607 struct odhcpd_ipaddr *addr, 608 time_t now) 609 { 610 struct ra_pio *pio = router_find_ra_pio(iface, addr); 611 char ipv6_str[INET6_ADDRSTRLEN]; 612 613 if (!pio || pio->lifetime) 614 return; 615 616 pio->lifetime = now + iface->max_valid_lifetime; 617 618 iface->pio_update = true; 619 warn("rfc9096: %s: stale %s/%u", 620 iface->ifname, 621 inet_ntop(AF_INET6, &pio->prefix, ipv6_str, sizeof(ipv6_str)), 622 pio->length); 623 } 624 625 /* Router Advert server mode */ 626 static int send_router_advert(struct interface *iface, const struct in6_addr *from) 627 { 628 time_t now = odhcpd_time(); 629 struct odhcpd_ipaddr *addrs = NULL; 630 struct adv_msg adv; 631 struct nd_opt_prefix_info *pfxs = NULL; 632 struct nd_opt_dns_server *dns = NULL; 633 struct nd_opt_search_list *search = NULL; 634 struct nd_opt_route_info *routes = NULL; 635 struct nd_opt_pref64_info *pref64 = NULL; 636 struct nd_opt_dnr_info *dnrs = NULL; 637 struct nd_opt_adv_interval adv_interval; 638 struct nd_opt_capt_portal *capt_portal = NULL; 639 struct iovec iov[IOV_RA_TOTAL]; 640 struct sockaddr_in6 dest; 641 size_t dns_sz = 0, search_sz = 0, pref64_sz = 0, dnrs_sz = 0; 642 size_t pfxs_cnt = 0, routes_cnt = 0; 643 size_t total_addr_cnt = 0, valid_addr_cnt = 0; 644 size_t capt_portal_sz = 0; 645 /* 646 * lowest_found_lifetime stores the lowest lifetime of all prefixes; 647 * necessary to find longest adv interval necessary 648 * for shortest lived prefix 649 */ 650 uint32_t lowest_found_lifetime = UINT32_MAX, highest_found_lifetime = 0, maxival, ra_lifetime; 651 int msecs, hlim = iface->ra_hoplimit; 652 bool default_route = false; 653 bool valid_prefix = false; 654 char buf[INET6_ADDRSTRLEN]; 655 656 router_clear_expired_ra_pio(now, iface); 657 658 memset(&adv, 0, sizeof(adv)); 659 adv.h.nd_ra_type = ND_ROUTER_ADVERT; 660 661 if (hlim == 0) 662 hlim = odhcpd_get_interface_config(iface->ifname, "hop_limit"); 663 664 if (hlim > 0) 665 adv.h.nd_ra_curhoplimit = hlim; 666 667 adv.h.nd_ra_flags_reserved = iface->ra_flags; 668 669 if (iface->route_preference < 0) 670 adv.h.nd_ra_flags_reserved |= ND_RA_PREF_LOW; 671 else if (iface->route_preference > 0) 672 adv.h.nd_ra_flags_reserved |= ND_RA_PREF_HIGH; 673 674 if (iface->dhcpv6 != MODE_DISABLED && iface->dhcpv6_pd && iface->dhcpv6_pd_preferred) { 675 /* RFC9762 § 5 676 * If the network desires to delegate prefixes to devices that support 677 * DHCPv6 prefix delegation but do not support the P flag, it SHOULD 678 * also set the M or O bits in the RA to 1 679 */ 680 adv.h.nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; 681 } 682 683 adv.h.nd_ra_reachable = htonl(iface->ra_reachabletime); 684 adv.h.nd_ra_retransmit = htonl(iface->ra_retranstime); 685 686 adv.lladdr.type = ND_OPT_SOURCE_LINKADDR; 687 adv.lladdr.len = 1; 688 odhcpd_get_mac(iface, adv.lladdr.data); 689 690 adv.mtu.nd_opt_mtu_type = ND_OPT_MTU; 691 adv.mtu.nd_opt_mtu_len = 1; 692 693 adv.mtu.nd_opt_mtu_mtu = htonl(iface->ra_mtu); 694 695 iov[IOV_RA_ADV].iov_base = &adv; 696 iov[IOV_RA_ADV].iov_len = sizeof(adv); 697 698 valid_addr_cnt = (iface->timer_rs.cb /* if not shutdown */ ? iface->addr6_len : 0); 699 700 // check ra_default 701 if (iface->default_router) { 702 default_route = true; 703 704 if (iface->default_router > 1) 705 valid_prefix = true; 706 } 707 708 if (valid_addr_cnt + iface->pio_cnt) { 709 addrs = alloca(sizeof(*addrs) * (valid_addr_cnt + iface->pio_cnt)); 710 711 if (valid_addr_cnt) { 712 memcpy(addrs, iface->addr6, sizeof(*addrs) * valid_addr_cnt); 713 total_addr_cnt = valid_addr_cnt; 714 715 /* Check default route */ 716 if (!default_route && parse_routes(addrs, valid_addr_cnt)) 717 default_route = true; 718 } 719 720 for (size_t i = 0; i < iface->pio_cnt; i++) { 721 struct ra_pio *cur_pio = &iface->pios[i]; 722 bool pio_found = false; 723 724 for (size_t j = 0; j < valid_addr_cnt; j++) { 725 struct odhcpd_ipaddr *cur_addr = &addrs[j]; 726 727 if (!router_compare_pio_addr(cur_pio, cur_addr)) { 728 pio_found = true; 729 break; 730 } 731 } 732 733 if (!pio_found) { 734 struct odhcpd_ipaddr *addr = &addrs[total_addr_cnt]; 735 736 memcpy(&addr->addr.in6, &cur_pio->prefix, sizeof(addr->addr.in6)); 737 addr->prefix_len = cur_pio->length; 738 addr->preferred_lt = 0; 739 addr->valid_lt = (uint32_t) (now + ND_VALID_LIMIT); 740 total_addr_cnt++; 741 } 742 } 743 } 744 745 /* Construct Prefix Information options */ 746 if (total_addr_cnt > 0) { 747 pfxs = alloca(total_addr_cnt * sizeof(*pfxs)); 748 memset(pfxs, 0, total_addr_cnt * sizeof(*pfxs)); 749 } 750 for (size_t i = 0; i < total_addr_cnt; ++i) { 751 struct odhcpd_ipaddr *addr = &addrs[i]; 752 struct nd_opt_prefix_info *p = NULL; 753 uint32_t preferred_lt = 0; 754 uint32_t valid_lt = 0; 755 756 if (addr->prefix_len > 96 || (i < valid_addr_cnt && addr->valid_lt <= (uint32_t)now)) { 757 info("Address %s (prefix %d, valid-lifetime %u) not suitable as RA prefix on %s", 758 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), addr->prefix_len, 759 addr->valid_lt, iface->name); 760 continue; 761 } 762 763 if (ADDR_MATCH_PIO_FILTER(addr, iface)) { 764 info("Address %s filtered out as RA prefix on %s", 765 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 766 iface->name); 767 continue; /* PIO filtered out of this RA */ 768 } 769 770 for (size_t j = 0; j < pfxs_cnt; ++j) { 771 if (addr->prefix_len == pfxs[j].nd_opt_pi_prefix_len && 772 !odhcpd_bmemcmp(&pfxs[j].nd_opt_pi_prefix, 773 &addr->addr.in6, addr->prefix_len)) 774 p = &pfxs[j]; 775 } 776 777 if (!p) 778 p = &pfxs[pfxs_cnt++]; 779 780 if (addr->preferred_lt > (uint32_t)now) { 781 preferred_lt = TIME_LEFT(addr->preferred_lt, now); 782 783 if (iface->max_preferred_lifetime && preferred_lt > iface->max_preferred_lifetime) { 784 preferred_lt = iface->max_preferred_lifetime; 785 } 786 } 787 788 if (addr->valid_lt > (uint32_t)now) { 789 valid_lt = TIME_LEFT(addr->valid_lt, now); 790 791 if (iface->max_valid_lifetime && valid_lt > iface->max_valid_lifetime) 792 valid_lt = iface->max_valid_lifetime; 793 } 794 795 if (preferred_lt > valid_lt) { 796 /* 797 * RFC4861 § 6.2.1 798 * This value [AdvPreferredLifetime] MUST NOT be larger than 799 * AdvValidLifetime. 800 */ 801 preferred_lt = valid_lt; 802 } 803 804 if (lowest_found_lifetime > valid_lt) 805 lowest_found_lifetime = valid_lt; 806 807 if ((!IN6_IS_ADDR_ULA(&addr->addr.in6) || iface->default_router) && valid_lt) 808 valid_prefix = true; 809 810 if (!IN6_IS_ADDR_ULA(&addr->addr.in6) && valid_lt) { 811 if (highest_found_lifetime < valid_lt) 812 highest_found_lifetime = valid_lt; 813 } 814 815 odhcpd_bmemcpy(&p->nd_opt_pi_prefix, &addr->addr.in6, 816 (iface->ra_advrouter) ? 128 : addr->prefix_len); 817 p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 818 p->nd_opt_pi_len = 4; 819 p->nd_opt_pi_prefix_len = (addr->prefix_len < 64) ? 64 : addr->prefix_len; 820 /* RFC9762 DHCPv6-PD Preferred Flag § 6: 821 * Routers SHOULD set the P flag to zero by default... 822 */ 823 p->nd_opt_pi_flags_reserved = 0; 824 if (!iface->ra_not_onlink) 825 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; 826 if (iface->ra_slaac && addr->prefix_len <= 64) 827 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; 828 if (iface->dhcpv6 != MODE_DISABLED && iface->dhcpv6_pd && iface->dhcpv6_pd_preferred) 829 /* RFC9762 DHCPv6-PD Preferred Flag 830 * We can run both SLAAC and DHCPv6-PD. 831 * §6: 832 * "Routers MUST allow the P flag to be configured separately from the A flag. 833 * ...en/disabling the P flag MUST NOT trigger automatic changes in the A flag 834 * value set by the router." 835 */ 836 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_PD_PREFERRED; 837 if (iface->ra_advrouter) 838 // RFC6275, §7.2 839 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; 840 if (i >= valid_addr_cnt || !preferred_lt) { 841 /* 842 * RFC9096 § 3.5 843 * 844 * - Any prefixes that were previously advertised by the CE router 845 * via PIOs in RA messages, but that have now become stale, MUST 846 * be advertised with PIOs that have the "Valid Lifetime" and the 847 * "Preferred Lifetime" set to 0 and the "A" and "L" bits 848 * unchanged. 849 */ 850 p->nd_opt_pi_preferred_time = 0; 851 p->nd_opt_pi_valid_time = 0; 852 853 router_stale_ra_pio(iface, addr, now); 854 } else { 855 p->nd_opt_pi_preferred_time = htonl(preferred_lt); 856 p->nd_opt_pi_valid_time = htonl(valid_lt); 857 858 router_add_ra_pio(iface, addr); 859 } 860 } 861 862 router_clear_duplicated_ra_pio(iface); 863 864 iov[IOV_RA_PFXS].iov_base = pfxs; 865 iov[IOV_RA_PFXS].iov_len = pfxs_cnt * sizeof(*pfxs); 866 867 /* Calculate periodic transmit */ 868 msecs = calc_adv_interval(iface, lowest_found_lifetime, &maxival); 869 ra_lifetime = calc_ra_lifetime(iface, maxival); 870 if (!highest_found_lifetime) 871 highest_found_lifetime = ra_lifetime; 872 873 if (!iface->have_link_local) { 874 notice("Skip sending a RA on %s as no link local address is available", iface->name); 875 goto out; 876 } 877 878 if (default_route && valid_prefix) { 879 adv.h.nd_ra_router_lifetime = htons(ra_lifetime < UINT16_MAX ? ra_lifetime : UINT16_MAX); 880 } else { 881 adv.h.nd_ra_router_lifetime = 0; 882 883 if (default_route) 884 warn("A default route is present but there is no public prefix " 885 "on %s thus we announce no default route by setting ra_lifetime to 0!", iface->name); 886 else 887 warn("No default route present, setting ra_lifetime to 0!"); 888 } 889 890 debug("Using a RA lifetime of %d seconds on %s", ntohs(adv.h.nd_ra_router_lifetime), iface->name); 891 892 /* Recursive DNS Server aka RDNSS; RFC8106, §5.1 */ 893 if (iface->ra_dns) { 894 struct in6_addr *dns_addrs6 = NULL, dns_addr6; 895 size_t dns_addrs6_cnt = 0; 896 897 if (iface->dns_addrs6_cnt > 0) { 898 dns_addrs6 = iface->dns_addrs6; 899 dns_addrs6_cnt = iface->dns_addrs6_cnt; 900 } else if (!odhcpd_get_interface_dns_addr6(iface, &dns_addr6)) { 901 dns_addrs6 = &dns_addr6; 902 dns_addrs6_cnt = 1; 903 } 904 905 if (dns_addrs6_cnt) { 906 dns_sz = sizeof(*dns) + dns_addrs6_cnt * sizeof(*dns_addrs6); 907 908 dns = alloca(dns_sz); 909 memset(dns, 0, dns_sz); 910 dns->type = ND_OPT_RECURSIVE_DNS; 911 dns->len = 1 + (2 * dns_addrs6_cnt); 912 dns->lifetime = htonl(highest_found_lifetime); 913 memcpy(dns->addr, dns_addrs6, dns_addrs6_cnt * sizeof(*dns_addrs6)); 914 } 915 } 916 iov[IOV_RA_DNS].iov_base = dns; 917 iov[IOV_RA_DNS].iov_len = dns_sz; 918 919 /* DNS Search List aka DNSSL; RFC8106, §5.2 */ 920 if (iface->ra_dns && iface->dns_search_len > 0) { 921 search_sz = sizeof(*search) + ((iface->dns_search_len + 7) & ~7); 922 search = alloca(search_sz); 923 *search = (struct nd_opt_search_list) { 924 .type = ND_OPT_DNS_SEARCH, 925 .len = search_sz / 8, 926 .reserved = 0, 927 .lifetime = htonl(highest_found_lifetime), 928 }; 929 memcpy(search->name, iface->dns_search, iface->dns_search_len); 930 } 931 iov[IOV_RA_SEARCH].iov_base = search; 932 iov[IOV_RA_SEARCH].iov_len = search_sz; 933 934 if (iface->pref64_length) { 935 /* RFC 8781 § 4.1 rounding up lifetime to multiple of 8 */ 936 uint16_t pref64_lifetime = ra_lifetime < (UINT16_MAX - 7) ? ra_lifetime + 7 : (UINT16_MAX - 7); 937 938 pref64_sz = sizeof(*pref64); 939 pref64 = alloca(pref64_sz); 940 pref64->type = ND_OPT_PREF64; 941 pref64->len = 2; 942 pref64->lifetime_plc = htons((0xfff8 & pref64_lifetime) | 943 (0x7 & iface->pref64_plc)); 944 memcpy(pref64->prefix, iface->pref64_prefix, sizeof(pref64->prefix)); 945 } 946 iov[IOV_RA_PREF64].iov_base = pref64; 947 iov[IOV_RA_PREF64].iov_len = pref64_sz; 948 949 if (iface->dnr_cnt) { 950 size_t dnr_sz[iface->dnr_cnt]; 951 952 for (unsigned i = 0; i < iface->dnr_cnt; i++) { 953 dnr_sz[i] = sizeof(struct nd_opt_dnr_info) + iface->dnr[i].adn_len; 954 if (iface->dnr[i].addr6_cnt > 0 || iface->dnr[i].svc_len > 0) { 955 dnr_sz[i] += 2 + iface->dnr[i].addr6_cnt * sizeof(struct in6_addr); 956 dnr_sz[i] += 2 + iface->dnr[i].svc_len; 957 } 958 dnr_sz[i] = (dnr_sz[i] + 7) & ~7; 959 dnrs_sz += dnr_sz[i]; 960 } 961 962 /* dnrs are sized in multiples of 8, so each dnr should be aligned */ 963 dnrs = alloca(dnrs_sz); 964 memset(dnrs, 0, dnrs_sz); 965 966 uint8_t *pos = (uint8_t *)dnrs; 967 for (unsigned i = 0; i < iface->dnr_cnt; pos += dnr_sz[i], i++) { 968 struct nd_opt_dnr_info *dnr = (struct nd_opt_dnr_info *)pos; 969 size_t dnr_addr6_sz = iface->dnr[i].addr6_cnt * sizeof(struct in6_addr); 970 uint8_t *tmp = dnr->body; 971 972 dnr->type = ND_OPT_DNR; 973 dnr->len = dnr_sz[i] / 8; 974 dnr->priority = htons(iface->dnr[i].priority); 975 if (iface->dnr[i].lifetime_set) 976 dnr->lifetime = htonl(iface->dnr[i].lifetime); 977 else 978 dnr->lifetime = htonl(highest_found_lifetime); 979 980 dnr->adn_len = htons(iface->dnr[i].adn_len); 981 memcpy(tmp, iface->dnr[i].adn, iface->dnr[i].adn_len); 982 tmp += iface->dnr[i].adn_len; 983 984 *(tmp++) = dnr_addr6_sz >> 8; 985 *(tmp++) = dnr_addr6_sz & 0xff; 986 memcpy(tmp, iface->dnr[i].addr6, dnr_addr6_sz); 987 tmp += dnr_addr6_sz; 988 989 *(tmp++) = iface->dnr[i].svc_len >> 8; 990 *(tmp++) = iface->dnr[i].svc_len & 0xff; 991 memcpy(tmp, iface->dnr[i].svc, iface->dnr[i].svc_len); 992 } 993 } 994 iov[IOV_RA_DNR].iov_base = dnrs; 995 iov[IOV_RA_DNR].iov_len = dnrs_sz; 996 997 /* 998 * RFC7084 § 4.3 : 999 * L-3: An IPv6 CE router MUST advertise itself as a router for the 1000 * delegated prefix(es) (and ULA prefix if configured to provide 1001 * ULA addressing) using the "Route Information Option" specified 1002 * in Section 2.3 of [RFC4191]. This advertisement is 1003 * independent of having or not having IPv6 connectivity on the 1004 * WAN interface. 1005 */ 1006 if (valid_addr_cnt > 0) { 1007 routes = alloca(valid_addr_cnt * sizeof(*routes)); 1008 memset(routes, 0, valid_addr_cnt * sizeof(*routes)); 1009 } 1010 for (size_t i = 0; i < valid_addr_cnt; ++i) { 1011 struct odhcpd_ipaddr *addr = &addrs[i]; 1012 uint32_t valid_lt; 1013 1014 if (addr->dprefix_len >= 64 || addr->dprefix_len == 0 || addr->valid_lt <= (uint32_t)now) { 1015 debug("Address %s (dprefix %d, valid-lifetime %u) not suitable as RA route on %s", 1016 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 1017 addr->dprefix_len, addr->valid_lt, iface->name); 1018 continue; 1019 } 1020 1021 if (ADDR_MATCH_PIO_FILTER(addr, iface)) { 1022 debug("Address %s filtered out as RA route on %s", 1023 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 1024 iface->name); 1025 continue; 1026 } 1027 1028 if (addr->dprefix_len > 32) { 1029 addr->addr.in6.s6_addr32[1] &= htonl(~((1U << (64 - addr->dprefix_len)) - 1)); 1030 } else if (addr->dprefix_len <= 32) { 1031 addr->addr.in6.s6_addr32[0] &= htonl(~((1U << (32 - addr->dprefix_len)) - 1)); 1032 addr->addr.in6.s6_addr32[1] = 0; 1033 } 1034 1035 routes[routes_cnt].type = ND_OPT_ROUTE_INFO; 1036 routes[routes_cnt].len = sizeof(*routes) / 8; 1037 routes[routes_cnt].prefix_len = addr->dprefix_len; 1038 routes[routes_cnt].flags = 0; 1039 if (iface->route_preference < 0) 1040 routes[routes_cnt].flags |= ND_RA_PREF_LOW; 1041 else if (iface->route_preference > 0) 1042 routes[routes_cnt].flags |= ND_RA_PREF_HIGH; 1043 1044 valid_lt = TIME_LEFT(addr->valid_lt, now); 1045 if (iface->max_valid_lifetime && valid_lt > iface->max_valid_lifetime) 1046 valid_lt = iface->max_valid_lifetime; 1047 routes[routes_cnt].lifetime = htonl(valid_lt); 1048 routes[routes_cnt].addr[0] = addr->addr.in6.s6_addr32[0]; 1049 routes[routes_cnt].addr[1] = addr->addr.in6.s6_addr32[1]; 1050 routes[routes_cnt].addr[2] = 0; 1051 routes[routes_cnt].addr[3] = 0; 1052 1053 routes_cnt++; 1054 } 1055 iov[IOV_RA_ROUTES].iov_base = routes; 1056 iov[IOV_RA_ROUTES].iov_len = routes_cnt * sizeof(*routes); 1057 1058 memset(&adv_interval, 0, sizeof(adv_interval)); 1059 adv_interval.nd_opt_adv_interval_type = ND_OPT_RTR_ADV_INTERVAL; 1060 adv_interval.nd_opt_adv_interval_len = 1; 1061 adv_interval.nd_opt_adv_interval_ival = htonl(maxival*1000); 1062 1063 iov[IOV_RA_ADV_INTERVAL].iov_base = &adv_interval; 1064 iov[IOV_RA_ADV_INTERVAL].iov_len = adv_interval.nd_opt_adv_interval_len * 8; 1065 1066 /* RFC 8910 Captive Portal */ 1067 if (iface->captive_portal_uri_len > 0) { 1068 /* compute pad so that (header + data + pad) is a multiple of 8 */ 1069 capt_portal_sz = (sizeof(struct nd_opt_capt_portal) + iface->captive_portal_uri_len + 7) & ~7; 1070 1071 capt_portal = alloca(capt_portal_sz); 1072 memset(capt_portal, 0, capt_portal_sz); 1073 1074 capt_portal->type = ND_OPT_CAPTIVE_PORTAL; 1075 capt_portal->len = capt_portal_sz / 8; 1076 1077 memcpy(capt_portal->data, iface->captive_portal_uri, iface->captive_portal_uri_len); 1078 /* remaining padding bytes already set to 0x00 */ 1079 } 1080 1081 iov[IOV_RA_CAPT_PORTAL].iov_base = capt_portal; 1082 iov[IOV_RA_CAPT_PORTAL].iov_len = capt_portal_sz; 1083 1084 memset(&dest, 0, sizeof(dest)); 1085 dest.sin6_family = AF_INET6; 1086 1087 if (from && !IN6_IS_ADDR_UNSPECIFIED(from)) 1088 dest.sin6_addr = *from; 1089 else 1090 inet_pton(AF_INET6, ALL_IPV6_NODES, &dest.sin6_addr); 1091 1092 debug("Sending a RA on %s", iface->name); 1093 1094 if (odhcpd_try_send_with_src(iface->router_event.uloop.fd, &dest, iov, ARRAY_SIZE(iov), iface) > 0) { 1095 iface->ra_sent++; 1096 1097 statefiles_write_prefix_information(iface); 1098 } 1099 1100 out: 1101 return msecs; 1102 } 1103 1104 1105 static void trigger_router_advert(struct uloop_timeout *event) 1106 { 1107 struct interface *iface = container_of(event, struct interface, timer_rs); 1108 int msecs = send_router_advert(iface, NULL); 1109 1110 /* Rearm timer if not shut down */ 1111 if (event->cb) 1112 uloop_timeout_set(event, msecs); 1113 } 1114 1115 1116 /* Event handler for incoming ICMPv6 packets */ 1117 static void handle_icmpv6(void *addr, void *data, size_t len, 1118 struct interface *iface, _o_unused void *dest) 1119 { 1120 struct icmp6_hdr *hdr = data; 1121 struct sockaddr_in6 *from = addr; 1122 1123 if (!router_icmpv6_valid(addr, data, len)) 1124 return; 1125 1126 if ((iface->ra == MODE_SERVER && !iface->master)) { /* Server mode */ 1127 if (hdr->icmp6_type == ND_ROUTER_SOLICIT) 1128 send_router_advert(iface, &from->sin6_addr); 1129 } else if (iface->ra == MODE_RELAY) { /* Relay mode */ 1130 if (hdr->icmp6_type == ND_ROUTER_SOLICIT && !iface->master) { 1131 struct interface *c; 1132 1133 avl_for_each_element(&interfaces, c, avl) { 1134 if (!c->master || c->ra != MODE_RELAY) 1135 continue; 1136 1137 forward_router_solicitation(c); 1138 } 1139 } else if (hdr->icmp6_type == ND_ROUTER_ADVERT && iface->master) 1140 forward_router_advertisement(iface, data, len); 1141 } 1142 } 1143 1144 1145 /* Forward a router solicitation from slave to master interface */ 1146 static void forward_router_solicitation(const struct interface *iface) 1147 { 1148 struct icmp6_hdr rs = {ND_ROUTER_SOLICIT, 0, 0, {{0}}}; 1149 struct iovec iov = {&rs, sizeof(rs)}; 1150 struct sockaddr_in6 all_routers; 1151 1152 if (!iface) 1153 return; 1154 1155 memset(&all_routers, 0, sizeof(all_routers)); 1156 all_routers.sin6_family = AF_INET6; 1157 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &all_routers.sin6_addr); 1158 all_routers.sin6_scope_id = iface->ifindex; 1159 1160 notice("Sending RS to %s", iface->name); 1161 odhcpd_send(iface->router_event.uloop.fd, &all_routers, &iov, 1, iface); 1162 } 1163 1164 1165 /* Forward a router advertisement from master to slave interfaces */ 1166 static void forward_router_advertisement(const struct interface *iface, uint8_t *data, size_t len) 1167 { 1168 struct nd_router_advert *adv = (struct nd_router_advert *)data; 1169 struct sockaddr_in6 all_nodes; 1170 struct icmpv6_opt *opt; 1171 struct interface *c; 1172 struct iovec iov = { .iov_base = data, .iov_len = len }; 1173 /* Rewrite options */ 1174 uint8_t *end = data + len; 1175 uint8_t *mac_ptr = NULL; 1176 struct in6_addr *dns_addrs6 = NULL; 1177 size_t dns_addrs6_cnt = 0; 1178 // MTU option 1179 struct nd_opt_mtu *mtu_opt = NULL; 1180 uint32_t ingress_mtu_val = 0; 1181 /* PIO L/A/R/P flag and RA M/O Flags */ 1182 uint8_t ra_flags; 1183 size_t pio_count = 0; 1184 struct fwd_pio_flags { 1185 uint8_t *ptr; 1186 uint8_t flags; 1187 } *pio_flags = NULL; 1188 1189 icmpv6_for_each_option(opt, &adv[1], end) { 1190 /* check our packet content is not truncated */ 1191 if (opt->len == 0 || (uint8_t *)opt + opt->len * 8 > end) { 1192 error("Ingress RA packet option for relaying has incorrect length"); 1193 return; 1194 } 1195 1196 switch(opt->type) { 1197 case ND_OPT_PREFIX_INFORMATION: 1198 pio_count++; 1199 break; 1200 } 1201 } 1202 1203 if (pio_count > 0) { 1204 pio_flags = alloca(sizeof(*pio_flags) * pio_count); 1205 pio_count = 0; 1206 } 1207 1208 /* Parse existing options */ 1209 icmpv6_for_each_option(opt, &adv[1], end) { 1210 switch (opt->type) { 1211 case ND_OPT_SOURCE_LINKADDR: 1212 mac_ptr = opt->data; 1213 break; 1214 1215 case ND_OPT_RECURSIVE_DNS: 1216 if (opt->len > 1) { 1217 dns_addrs6 = (struct in6_addr *)&opt->data[6]; 1218 dns_addrs6_cnt = (opt->len - 1) / 2; 1219 } 1220 break; 1221 1222 case ND_OPT_MTU: 1223 if (opt->len == 1 && (uint8_t *)opt + sizeof(struct nd_opt_mtu) <= end) { 1224 mtu_opt = (struct nd_opt_mtu *)opt; 1225 ingress_mtu_val = ntohl(mtu_opt->nd_opt_mtu_mtu); 1226 } 1227 break; 1228 case ND_OPT_PREFIX_INFORMATION: 1229 /* Store options for each PIO */ 1230 pio_flags[pio_count].ptr = &opt->data[1]; 1231 pio_flags[pio_count].flags = opt->data[1]; 1232 pio_count++; 1233 break; 1234 } 1235 } 1236 1237 info("Got a RA on %s", iface->name); 1238 1239 /* Indicate a proxy, however we don't follow the rest of RFC 4389 yet 1240 * store original upstream RA state 1241 */ 1242 ra_flags = adv->nd_ra_flags_reserved | ND_RA_FLAG_PROXY; 1243 1244 /* Forward advertisement to all slave interfaces */ 1245 memset(&all_nodes, 0, sizeof(all_nodes)); 1246 all_nodes.sin6_family = AF_INET6; 1247 inet_pton(AF_INET6, ALL_IPV6_NODES, &all_nodes.sin6_addr); 1248 1249 avl_for_each_element(&interfaces, c, avl) { 1250 if (c->ra != MODE_RELAY || c->master) 1251 continue; 1252 1253 /* Fixup source hardware address option */ 1254 if (mac_ptr) 1255 odhcpd_get_mac(c, mac_ptr); 1256 1257 if (pio_count > 0) 1258 debug("RA forward: Rewriting RA PIO flags"); 1259 1260 for (size_t i = 0; i < pio_count; i++) { 1261 /* restore the flags byte to its upstream state before applying per-interface policy */ 1262 *pio_flags[i].ptr = pio_flags[i].flags; 1263 /* ensure L flag (on-link) cleared; relayed == not on-link */ 1264 *pio_flags[i].ptr &= ~ND_OPT_PI_FLAG_ONLINK; 1265 /* upstream no SLAAC, downstream no SLAAC: no change 1266 * upstream no SLAAC, downstream SLAAC: no change 1267 * upstream SLAAC, downstream SLAAC: no change 1268 * upstream SLAAC, downstream no SLAAC: clear flag 1269 * Why? We shall not SLAAC downstream if upstream disables it. Sometimes 1270 * we just inform about a prefix for DHCPv6 and routing info. 1271 */ 1272 if (!c->ra_slaac) 1273 *pio_flags[i].ptr &= ~ND_OPT_PI_FLAG_AUTO;/* ensure A flag cleared */ 1274 1275 /* we have no opinion on the R flag - it can be forwarded */ 1276 1277 if (c->dhcpv6 == MODE_DISABLED || !c->dhcpv6_pd || !c->dhcpv6_pd_preferred) 1278 *pio_flags[i].ptr &= ~ND_OPT_PI_FLAG_PD_PREFERRED;/* ensure P flag (DHCPv6-PD) cleared */ 1279 } 1280 1281 /* Apply per-interface modifications of upstream RA state */ 1282 adv->nd_ra_flags_reserved = ra_flags; 1283 /* Rewrite M/O flags unless we relay DHCPv6 */ 1284 if (c->dhcpv6 != MODE_RELAY) { 1285 /* Clear the relayed M/O bits */ 1286 adv->nd_ra_flags_reserved &= ~(ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER); 1287 /* Apply the locally configured ra_flags for M and O */ 1288 adv->nd_ra_flags_reserved |= c->ra_flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER); 1289 } 1290 1291 /* If we have to rewrite DNS entries */ 1292 if (c->always_rewrite_dns && dns_addrs6 && dns_addrs6_cnt > 0) { 1293 const struct in6_addr *rewrite = c->dns_addrs6; 1294 struct in6_addr addr; 1295 size_t rewrite_cnt = c->dns_addrs6_cnt; 1296 1297 if (rewrite_cnt == 0) { 1298 if (odhcpd_get_interface_dns_addr6(c, &addr)) 1299 continue; /* Unable to comply */ 1300 1301 rewrite = &addr; 1302 rewrite_cnt = 1; 1303 } 1304 1305 /* Copy over any other addresses */ 1306 for (size_t i = 0; i < dns_addrs6_cnt; ++i) { 1307 size_t j = (i < rewrite_cnt) ? i : rewrite_cnt - 1; 1308 dns_addrs6[i] = rewrite[j]; 1309 } 1310 } 1311 1312 /* Rewrite MTU option if local RA MTU is configured */ 1313 if (c->ra_mtu && mtu_opt) { 1314 if (ingress_mtu_val != c->ra_mtu) { 1315 debug("Rewriting RA MTU from %u to %u on %s", 1316 ingress_mtu_val, c->ra_mtu, c->name); 1317 mtu_opt->nd_opt_mtu_mtu = htonl(c->ra_mtu); 1318 } 1319 } 1320 1321 info("Forward a RA on %s", c->name); 1322 odhcpd_send(c->router_event.uloop.fd, &all_nodes, &iov, 1, c); 1323 } 1324 } 1325
This page was automatically generated by LXR 0.3.1. • OpenWrt