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