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