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