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