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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 syslog(LOG_ERR, "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 /* 346 * rfc4861#section-6.2.1 : AdvDefaultLifetime Default: 3 * MaxRtrAdvInterval 347 * therefore max interval shall be no greater than 1/3 of the lowest valid 348 * lease time of all known prefixes. 349 */ 350 if (*maxival > lowest_found_lifetime/3) 351 *maxival = lowest_found_lifetime/3; 352 353 if (*maxival > MaxRtrAdvInterval) 354 *maxival = MaxRtrAdvInterval; 355 else if (*maxival < 4) 356 *maxival = 4; 357 358 if (minival < MinRtrAdvInterval) 359 minival = MinRtrAdvInterval; 360 else if (minival > (*maxival * 3)/4) 361 minival = (*maxival >= 9 ? *maxival/3 : *maxival); 362 363 odhcpd_urandom(&msecs, sizeof(msecs)); 364 msecs = (labs(msecs) % ((*maxival != minival) ? (*maxival - minival)*1000 : 500)) + 365 minival*1000; 366 367 /* RFC 2461 6.2.4 For the first MAX_INITIAL_RTR_ADVERTISEMENTS advertisements */ 368 /* if the timer is bigger than MAX_INITIAL_RTR_ADVERT_INTERVAL it should be */ 369 /* set to MAX_INITIAL_RTR_ADVERT_INTERVAL */ 370 /* Off by one as an initial interval timer has already expired */ 371 if ((iface->ra_sent + 1) < MaxInitialRtAdvs && msecs > MaxInitialRtrAdvInterval*1000) 372 msecs = MaxInitialRtrAdvInterval*1000; 373 374 return msecs; 375 } 376 377 static uint32_t calc_ra_lifetime(struct interface *iface, uint32_t maxival) 378 { 379 uint32_t lifetime = 3*maxival; 380 381 if (iface->ra_lifetime >= 0) { 382 lifetime = iface->ra_lifetime; 383 if (lifetime > 0 && lifetime < maxival) 384 lifetime = maxival; 385 else if (lifetime > 9000) 386 lifetime = 9000; 387 } 388 389 return lifetime; 390 } 391 392 enum { 393 IOV_RA_ADV=0, 394 IOV_RA_PFXS, 395 IOV_RA_ROUTES, 396 IOV_RA_DNS, 397 IOV_RA_SEARCH, 398 IOV_RA_PREF64, 399 IOV_RA_ADV_INTERVAL, 400 IOV_RA_TOTAL, 401 }; 402 403 struct adv_msg { 404 struct nd_router_advert h; 405 struct icmpv6_opt lladdr; 406 struct nd_opt_mtu mtu; 407 }; 408 409 struct nd_opt_dns_server { 410 uint8_t type; 411 uint8_t len; 412 uint8_t pad; 413 uint8_t pad2; 414 uint32_t lifetime; 415 struct in6_addr addr[]; 416 }; 417 418 struct nd_opt_search_list { 419 uint8_t type; 420 uint8_t len; 421 uint8_t pad; 422 uint8_t pad2; 423 uint32_t lifetime; 424 uint8_t name[]; 425 }; 426 427 struct nd_opt_route_info { 428 uint8_t type; 429 uint8_t len; 430 uint8_t prefix; 431 uint8_t flags; 432 uint32_t lifetime; 433 uint32_t addr[4]; 434 }; 435 436 struct nd_opt_pref64_info { 437 uint8_t type; 438 uint8_t len; 439 uint16_t lifetime_plc; 440 uint32_t addr[3]; 441 }; 442 443 /* Router Advert server mode */ 444 static int send_router_advert(struct interface *iface, const struct in6_addr *from) 445 { 446 time_t now = odhcpd_time(); 447 struct odhcpd_ipaddr *addrs = NULL; 448 struct adv_msg adv; 449 struct nd_opt_prefix_info *pfxs = NULL; 450 struct nd_opt_dns_server *dns = NULL; 451 struct nd_opt_search_list *search = NULL; 452 struct nd_opt_route_info *routes = NULL; 453 struct nd_opt_pref64_info *pref64 = NULL; 454 struct nd_opt_adv_interval adv_interval; 455 struct iovec iov[IOV_RA_TOTAL]; 456 struct sockaddr_in6 dest; 457 size_t dns_sz = 0, search_sz = 0, pref64_sz = 0; 458 size_t pfxs_cnt = 0, routes_cnt = 0; 459 ssize_t valid_addr_cnt = 0, invalid_addr_cnt = 0; 460 /* 461 * lowest_found_lifetime stores the lowest lifetime of all prefixes; 462 * necessary to find shortest adv interval necessary 463 * for shortest lived prefix 464 */ 465 uint32_t lowest_found_lifetime = UINT32_MAX, maxival, lifetime; 466 int msecs, mtu = iface->ra_mtu, hlim = iface->ra_hoplimit; 467 bool default_route = false; 468 bool valid_prefix = false; 469 char buf[INET6_ADDRSTRLEN]; 470 471 memset(&adv, 0, sizeof(adv)); 472 adv.h.nd_ra_type = ND_ROUTER_ADVERT; 473 474 if (hlim == 0) 475 hlim = odhcpd_get_interface_config(iface->ifname, "hop_limit"); 476 477 if (hlim > 0) 478 adv.h.nd_ra_curhoplimit = hlim; 479 480 adv.h.nd_ra_flags_reserved = iface->ra_flags; 481 482 if (iface->route_preference < 0) 483 adv.h.nd_ra_flags_reserved |= ND_RA_PREF_LOW; 484 else if (iface->route_preference > 0) 485 adv.h.nd_ra_flags_reserved |= ND_RA_PREF_HIGH; 486 487 adv.h.nd_ra_reachable = htonl(iface->ra_reachabletime); 488 adv.h.nd_ra_retransmit = htonl(iface->ra_retranstime); 489 490 adv.lladdr.type = ND_OPT_SOURCE_LINKADDR; 491 adv.lladdr.len = 1; 492 odhcpd_get_mac(iface, adv.lladdr.data); 493 494 adv.mtu.nd_opt_mtu_type = ND_OPT_MTU; 495 adv.mtu.nd_opt_mtu_len = 1; 496 497 if (mtu == 0) 498 mtu = odhcpd_get_interface_config(iface->ifname, "mtu"); 499 500 if (mtu < 1280) 501 mtu = 1280; 502 503 adv.mtu.nd_opt_mtu_mtu = htonl(mtu); 504 505 iov[IOV_RA_ADV].iov_base = (char *)&adv; 506 iov[IOV_RA_ADV].iov_len = sizeof(adv); 507 508 valid_addr_cnt = (iface->timer_rs.cb /* if not shutdown */ ? iface->addr6_len : 0); 509 invalid_addr_cnt = iface->invalid_addr6_len; 510 511 // check ra_default 512 if (iface->default_router) { 513 default_route = true; 514 515 if (iface->default_router > 1) 516 valid_prefix = true; 517 } 518 519 if (valid_addr_cnt + invalid_addr_cnt) { 520 addrs = alloca(sizeof(*addrs) * (valid_addr_cnt + invalid_addr_cnt)); 521 522 if (valid_addr_cnt) { 523 memcpy(addrs, iface->addr6, sizeof(*addrs) * valid_addr_cnt); 524 525 /* Check default route */ 526 if (!default_route && parse_routes(addrs, valid_addr_cnt)) 527 default_route = true; 528 } 529 530 if (invalid_addr_cnt) { 531 size_t i = 0; 532 533 memcpy(&addrs[valid_addr_cnt], iface->invalid_addr6, sizeof(*addrs) * invalid_addr_cnt); 534 535 /* Remove invalid prefixes that were advertised 3 times */ 536 while (i < iface->invalid_addr6_len) { 537 if (++iface->invalid_addr6[i].invalid_advertisements >= 3) { 538 if (i + 1 < iface->invalid_addr6_len) 539 memmove(&iface->invalid_addr6[i], &iface->invalid_addr6[i + 1], sizeof(*addrs) * (iface->invalid_addr6_len - i - 1)); 540 541 iface->invalid_addr6_len--; 542 543 if (iface->invalid_addr6_len) { 544 struct odhcpd_ipaddr *new_invalid_addr6 = realloc(iface->invalid_addr6, sizeof(*addrs) * iface->invalid_addr6_len); 545 546 if (new_invalid_addr6) 547 iface->invalid_addr6 = new_invalid_addr6; 548 } else { 549 free(iface->invalid_addr6); 550 iface->invalid_addr6 = NULL; 551 } 552 } else 553 ++i; 554 } 555 } 556 } 557 558 /* Construct Prefix Information options */ 559 for (ssize_t i = 0; i < valid_addr_cnt + invalid_addr_cnt; ++i) { 560 struct odhcpd_ipaddr *addr = &addrs[i]; 561 struct nd_opt_prefix_info *p = NULL; 562 uint32_t preferred_lt = 0; 563 uint32_t valid_lt = 0; 564 565 if (addr->prefix > 96 || (i < valid_addr_cnt && addr->valid_lt <= (uint32_t)now)) { 566 syslog(LOG_INFO, "Address %s (prefix %d, valid-lifetime %u) not suitable as RA prefix on %s", 567 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), addr->prefix, 568 addr->valid_lt, iface->name); 569 continue; 570 } 571 572 if (ADDR_MATCH_PIO_FILTER(addr, iface)) { 573 syslog(LOG_INFO, "Address %s filtered out as RA prefix on %s", 574 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 575 iface->name); 576 continue; /* PIO filtered out of this RA */ 577 } 578 579 for (size_t i = 0; i < pfxs_cnt; ++i) { 580 if (addr->prefix == pfxs[i].nd_opt_pi_prefix_len && 581 !odhcpd_bmemcmp(&pfxs[i].nd_opt_pi_prefix, 582 &addr->addr.in6, addr->prefix)) 583 p = &pfxs[i]; 584 } 585 586 if (!p) { 587 struct nd_opt_prefix_info *tmp; 588 589 tmp = realloc(pfxs, sizeof(*pfxs) * (pfxs_cnt + 1)); 590 if (!tmp) { 591 syslog(LOG_ERR, "Realloc failed for RA prefix option on %s", iface->name); 592 continue; 593 } 594 595 pfxs = tmp; 596 p = &pfxs[pfxs_cnt++]; 597 memset(p, 0, sizeof(*p)); 598 } 599 600 if (addr->preferred_lt > (uint32_t)now) { 601 preferred_lt = TIME_LEFT(addr->preferred_lt, now); 602 603 if (preferred_lt > iface->preferred_lifetime) { 604 /* set to possibly user mandated preferred_lt */ 605 preferred_lt = iface->preferred_lifetime; 606 } 607 } 608 609 if (addr->valid_lt > (uint32_t)now) { 610 valid_lt = TIME_LEFT(addr->valid_lt, now); 611 612 if (iface->ra_useleasetime && valid_lt > iface->dhcp_leasetime) 613 valid_lt = iface->dhcp_leasetime; 614 } 615 616 if (preferred_lt > valid_lt) { 617 /* 618 * RFC4861 § 6.2.1 619 * This value [AdvPreferredLifetime] MUST NOT be larger than 620 * AdvValidLifetime. 621 */ 622 preferred_lt = valid_lt; 623 } 624 625 if (lowest_found_lifetime > valid_lt) 626 lowest_found_lifetime = valid_lt; 627 628 if ((!IN6_IS_ADDR_ULA(&addr->addr.in6) || iface->default_router) && valid_lt) 629 valid_prefix = true; 630 631 odhcpd_bmemcpy(&p->nd_opt_pi_prefix, &addr->addr.in6, 632 (iface->ra_advrouter) ? 128 : addr->prefix); 633 p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 634 p->nd_opt_pi_len = 4; 635 p->nd_opt_pi_prefix_len = (addr->prefix < 64) ? 64 : addr->prefix; 636 p->nd_opt_pi_flags_reserved = 0; 637 if (!iface->ra_not_onlink) 638 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; 639 if (iface->ra_slaac && addr->prefix <= 64) 640 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; 641 if (iface->ra_advrouter) 642 p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; 643 p->nd_opt_pi_preferred_time = htonl(preferred_lt); 644 p->nd_opt_pi_valid_time = htonl(valid_lt); 645 } 646 647 iov[IOV_RA_PFXS].iov_base = (char *)pfxs; 648 iov[IOV_RA_PFXS].iov_len = pfxs_cnt * sizeof(*pfxs); 649 650 /* Calculate periodic transmit */ 651 msecs = calc_adv_interval(iface, lowest_found_lifetime, &maxival); 652 lifetime = calc_ra_lifetime(iface, maxival); 653 654 if (!iface->have_link_local) { 655 syslog(LOG_NOTICE, "Skip sending a RA on %s as no link local address is available", iface->name); 656 goto out; 657 } 658 659 if (default_route && valid_prefix) { 660 adv.h.nd_ra_router_lifetime = htons(lifetime < UINT16_MAX ? lifetime : UINT16_MAX); 661 } else { 662 adv.h.nd_ra_router_lifetime = 0; 663 664 if (default_route) { 665 syslog(LOG_WARNING, "A default route is present but there is no public prefix " 666 "on %s thus we announce no default route by overriding ra_lifetime to 0!", iface->name); 667 } else { 668 syslog(LOG_WARNING, "No default route present, overriding ra_lifetime to 0!"); 669 } 670 } 671 672 syslog(LOG_DEBUG, "Using a RA lifetime of %d seconds on %s", ntohs(adv.h.nd_ra_router_lifetime), iface->name); 673 674 /* DNS options */ 675 if (iface->ra_dns) { 676 struct in6_addr dns_pref, *dns_addr = NULL; 677 size_t dns_cnt = 0, search_len = iface->search_len; 678 uint8_t *search_domain = iface->search; 679 uint8_t search_buf[256]; 680 681 /* DNS Recursive DNS aka RDNSS Type 25; RFC8106 */ 682 if (iface->dns_cnt > 0) { 683 dns_addr = iface->dns; 684 dns_cnt = iface->dns_cnt; 685 } else if (!odhcpd_get_interface_dns_addr(iface, &dns_pref)) { 686 dns_addr = &dns_pref; 687 dns_cnt = 1; 688 } 689 690 if (dns_cnt) { 691 dns_sz = sizeof(*dns) + sizeof(struct in6_addr)*dns_cnt; 692 693 dns = alloca(dns_sz); 694 memset(dns, 0, dns_sz); 695 dns->type = ND_OPT_RECURSIVE_DNS; 696 dns->len = 1 + (2 * dns_cnt); 697 dns->lifetime = htonl(lifetime); 698 memcpy(dns->addr, dns_addr, sizeof(struct in6_addr)*dns_cnt); 699 } 700 701 /* DNS Search options aka DNSSL Type 31; RFC8106 */ 702 if (!search_domain && !res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) { 703 int len = dn_comp(_res.dnsrch[0], search_buf, 704 sizeof(search_buf), NULL, NULL); 705 if (len > 0) { 706 search_domain = search_buf; 707 search_len = len; 708 } 709 } 710 711 if (search_len > 0) { 712 size_t search_padded = ((search_len + 7) & (~7)) + 8; 713 714 search_sz = sizeof(*search) + search_padded; 715 716 search = alloca(search_sz); 717 memset(search, 0, search_sz); 718 search->type = ND_OPT_DNS_SEARCH; 719 search->len = search_len ? ((sizeof(*search) + search_padded) / 8) : 0; 720 search->lifetime = htonl(lifetime); 721 memcpy(search->name, search_domain, search_len); 722 memset(&search->name[search_len], 0, search_padded - search_len); 723 } 724 } 725 726 iov[IOV_RA_DNS].iov_base = (char *)dns; 727 iov[IOV_RA_DNS].iov_len = dns_sz; 728 iov[IOV_RA_SEARCH].iov_base = (char *)search; 729 iov[IOV_RA_SEARCH].iov_len = search_sz; 730 731 if (iface->pref64_length) { 732 /* RFC 8781 § 4.1 rounding up lifetime to multiple of 8 */ 733 uint16_t pref64_lifetime = lifetime < (UINT16_MAX - 7) ? lifetime + 7 : UINT16_MAX; 734 uint8_t prefix_length_code; 735 uint32_t mask_a1, mask_a2; 736 737 switch (iface->pref64_length) { 738 case 96: 739 prefix_length_code = 0; 740 mask_a1 = 0xffffffff; 741 mask_a2 = 0xffffffff; 742 break; 743 case 64: 744 prefix_length_code = 1; 745 mask_a1 = 0xffffffff; 746 mask_a2 = 0x00000000; 747 break; 748 case 56: 749 prefix_length_code = 2; 750 mask_a1 = 0xffffff00; 751 mask_a2 = 0x00000000; 752 break; 753 case 48: 754 prefix_length_code = 3; 755 mask_a1 = 0xffff0000; 756 mask_a2 = 0x00000000; 757 break; 758 case 40: 759 prefix_length_code = 4; 760 mask_a1 = 0xff000000; 761 mask_a2 = 0x00000000; 762 break; 763 case 32: 764 prefix_length_code = 5; 765 mask_a1 = 0x00000000; 766 mask_a2 = 0x00000000; 767 break; 768 default: 769 syslog(LOG_WARNING, "Invalid PREF64 prefix size (%d), " 770 "ignoring ra_pref64 option!", iface->pref64_length); 771 goto pref64_out; 772 break; 773 } 774 775 pref64_sz = sizeof(*pref64); 776 pref64 = alloca(pref64_sz); 777 memset(pref64, 0, pref64_sz); 778 pref64->type = ND_OPT_PREF64; 779 pref64->len = 2; 780 pref64->lifetime_plc = htons((0xfff8 & pref64_lifetime) | 781 (0x7 & prefix_length_code)); 782 pref64->addr[0] = iface->pref64_addr.s6_addr32[0]; 783 pref64->addr[1] = iface->pref64_addr.s6_addr32[1] & htonl(mask_a1); 784 pref64->addr[2] = iface->pref64_addr.s6_addr32[2] & htonl(mask_a2); 785 } 786 pref64_out: 787 iov[IOV_RA_PREF64].iov_base = (char *)pref64; 788 iov[IOV_RA_PREF64].iov_len = pref64_sz; 789 790 /* 791 * RFC7084 § 4.3 : 792 * L-3: An IPv6 CE router MUST advertise itself as a router for the 793 * delegated prefix(es) (and ULA prefix if configured to provide 794 * ULA addressing) using the "Route Information Option" specified 795 * in Section 2.3 of [RFC4191]. This advertisement is 796 * independent of having or not having IPv6 connectivity on the 797 * WAN interface. 798 */ 799 800 for (ssize_t i = 0; i < valid_addr_cnt; ++i) { 801 struct odhcpd_ipaddr *addr = &addrs[i]; 802 struct nd_opt_route_info *tmp; 803 uint32_t valid_lt; 804 805 if (addr->dprefix >= 64 || addr->dprefix == 0 || addr->valid_lt <= (uint32_t)now) { 806 syslog(LOG_INFO, "Address %s (dprefix %d, valid-lifetime %u) not suitable as RA route on %s", 807 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 808 addr->dprefix, addr->valid_lt, iface->name); 809 810 continue; /* Address not suitable */ 811 } 812 813 if (ADDR_MATCH_PIO_FILTER(addr, iface)) { 814 syslog(LOG_INFO, "Address %s filtered out as RA route on %s", 815 inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), 816 iface->name); 817 continue; /* PIO filtered out of this RA */ 818 } 819 820 if (addr->dprefix > 32) { 821 addr->addr.in6.s6_addr32[1] &= htonl(~((1U << (64 - addr->dprefix)) - 1)); 822 } else if (addr->dprefix <= 32) { 823 addr->addr.in6.s6_addr32[0] &= htonl(~((1U << (32 - addr->dprefix)) - 1)); 824 addr->addr.in6.s6_addr32[1] = 0; 825 } 826 827 tmp = realloc(routes, sizeof(*routes) * (routes_cnt + 1)); 828 if (!tmp) { 829 syslog(LOG_ERR, "Realloc failed for RA route option on %s", iface->name); 830 continue; 831 } 832 833 routes = tmp; 834 835 memset(&routes[routes_cnt], 0, sizeof(*routes)); 836 routes[routes_cnt].type = ND_OPT_ROUTE_INFO; 837 routes[routes_cnt].len = sizeof(*routes) / 8; 838 routes[routes_cnt].prefix = addr->dprefix; 839 routes[routes_cnt].flags = 0; 840 if (iface->route_preference < 0) 841 routes[routes_cnt].flags |= ND_RA_PREF_LOW; 842 else if (iface->route_preference > 0) 843 routes[routes_cnt].flags |= ND_RA_PREF_HIGH; 844 845 valid_lt = TIME_LEFT(addr->valid_lt, now); 846 routes[routes_cnt].lifetime = htonl(valid_lt < lifetime ? valid_lt : lifetime); 847 routes[routes_cnt].addr[0] = addr->addr.in6.s6_addr32[0]; 848 routes[routes_cnt].addr[1] = addr->addr.in6.s6_addr32[1]; 849 routes[routes_cnt].addr[2] = 0; 850 routes[routes_cnt].addr[3] = 0; 851 852 ++routes_cnt; 853 } 854 855 iov[IOV_RA_ROUTES].iov_base = (char *)routes; 856 iov[IOV_RA_ROUTES].iov_len = routes_cnt * sizeof(*routes); 857 858 memset(&adv_interval, 0, sizeof(adv_interval)); 859 adv_interval.nd_opt_adv_interval_type = ND_OPT_RTR_ADV_INTERVAL; 860 adv_interval.nd_opt_adv_interval_len = 1; 861 adv_interval.nd_opt_adv_interval_ival = htonl(maxival*1000); 862 863 iov[IOV_RA_ADV_INTERVAL].iov_base = (char *)&adv_interval; 864 iov[IOV_RA_ADV_INTERVAL].iov_len = adv_interval.nd_opt_adv_interval_len * 8; 865 866 memset(&dest, 0, sizeof(dest)); 867 dest.sin6_family = AF_INET6; 868 869 if (from && !IN6_IS_ADDR_UNSPECIFIED(from)) 870 dest.sin6_addr = *from; 871 else 872 inet_pton(AF_INET6, ALL_IPV6_NODES, &dest.sin6_addr); 873 874 syslog(LOG_NOTICE, "Sending a RA on %s", iface->name); 875 876 if (odhcpd_send(iface->router_event.uloop.fd, &dest, iov, ARRAY_SIZE(iov), iface) > 0) 877 iface->ra_sent++; 878 879 out: 880 free(pfxs); 881 free(routes); 882 883 return msecs; 884 } 885 886 887 static void trigger_router_advert(struct uloop_timeout *event) 888 { 889 struct interface *iface = container_of(event, struct interface, timer_rs); 890 int msecs = send_router_advert(iface, NULL); 891 892 /* Rearm timer if not shut down */ 893 if (event->cb) 894 uloop_timeout_set(event, msecs); 895 } 896 897 898 /* Event handler for incoming ICMPv6 packets */ 899 static void handle_icmpv6(void *addr, void *data, size_t len, 900 struct interface *iface, _unused void *dest) 901 { 902 struct icmp6_hdr *hdr = data; 903 struct sockaddr_in6 *from = addr; 904 905 if (!router_icmpv6_valid(addr, data, len)) 906 return; 907 908 if ((iface->ra == MODE_SERVER && !iface->master)) { /* Server mode */ 909 if (hdr->icmp6_type == ND_ROUTER_SOLICIT) 910 send_router_advert(iface, &from->sin6_addr); 911 } else if (iface->ra == MODE_RELAY) { /* Relay mode */ 912 if (hdr->icmp6_type == ND_ROUTER_SOLICIT && !iface->master) { 913 struct interface *c; 914 915 avl_for_each_element(&interfaces, c, avl) { 916 if (!c->master || c->ra != MODE_RELAY) 917 continue; 918 919 forward_router_solicitation(c); 920 } 921 } else if (hdr->icmp6_type == ND_ROUTER_ADVERT && iface->master) 922 forward_router_advertisement(iface, data, len); 923 } 924 } 925 926 927 /* Forward router solicitation */ 928 static void forward_router_solicitation(const struct interface *iface) 929 { 930 struct icmp6_hdr rs = {ND_ROUTER_SOLICIT, 0, 0, {{0}}}; 931 struct iovec iov = {&rs, sizeof(rs)}; 932 struct sockaddr_in6 all_routers; 933 934 if (!iface) 935 return; 936 937 memset(&all_routers, 0, sizeof(all_routers)); 938 all_routers.sin6_family = AF_INET6; 939 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &all_routers.sin6_addr); 940 all_routers.sin6_scope_id = iface->ifindex; 941 942 syslog(LOG_NOTICE, "Sending RS to %s", iface->name); 943 odhcpd_send(iface->router_event.uloop.fd, &all_routers, &iov, 1, iface); 944 } 945 946 947 /* Handler for incoming router solicitations on slave interfaces */ 948 static void forward_router_advertisement(const struct interface *iface, uint8_t *data, size_t len) 949 { 950 struct nd_router_advert *adv = (struct nd_router_advert *)data; 951 struct sockaddr_in6 all_nodes; 952 struct icmpv6_opt *opt; 953 struct interface *c; 954 struct iovec iov = { .iov_base = data, .iov_len = len }; 955 /* Rewrite options */ 956 uint8_t *end = data + len; 957 uint8_t *mac_ptr = NULL; 958 struct in6_addr *dns_ptr = NULL; 959 size_t dns_count = 0; 960 961 icmpv6_for_each_option(opt, &adv[1], end) { 962 if (opt->type == ND_OPT_SOURCE_LINKADDR) { 963 /* Store address of source MAC-address */ 964 mac_ptr = opt->data; 965 } else if (opt->type == ND_OPT_RECURSIVE_DNS && opt->len > 1) { 966 /* Check if we have to rewrite DNS */ 967 dns_ptr = (struct in6_addr*)&opt->data[6]; 968 dns_count = (opt->len - 1) / 2; 969 } 970 } 971 972 syslog(LOG_NOTICE, "Got a RA on %s", iface->name); 973 974 /* Indicate a proxy, however we don't follow the rest of RFC 4389 yet */ 975 adv->nd_ra_flags_reserved |= ND_RA_FLAG_PROXY; 976 977 /* Forward advertisement to all slave interfaces */ 978 memset(&all_nodes, 0, sizeof(all_nodes)); 979 all_nodes.sin6_family = AF_INET6; 980 inet_pton(AF_INET6, ALL_IPV6_NODES, &all_nodes.sin6_addr); 981 982 avl_for_each_element(&interfaces, c, avl) { 983 if (c->ra != MODE_RELAY || c->master) 984 continue; 985 986 /* Fixup source hardware address option */ 987 if (mac_ptr) 988 odhcpd_get_mac(c, mac_ptr); 989 990 /* If we have to rewrite DNS entries */ 991 if (c->always_rewrite_dns && dns_ptr && dns_count > 0) { 992 const struct in6_addr *rewrite = c->dns; 993 struct in6_addr addr; 994 size_t rewrite_cnt = c->dns_cnt; 995 996 if (rewrite_cnt == 0) { 997 if (odhcpd_get_interface_dns_addr(c, &addr)) 998 continue; /* Unable to comply */ 999 1000 rewrite = &addr; 1001 rewrite_cnt = 1; 1002 } 1003 1004 /* Copy over any other addresses */ 1005 for (size_t i = 0; i < dns_count; ++i) { 1006 size_t j = (i < rewrite_cnt) ? i : rewrite_cnt - 1; 1007 dns_ptr[i] = rewrite[j]; 1008 } 1009 } 1010 1011 syslog(LOG_NOTICE, "Forward a RA on %s", c->name); 1012 1013 odhcpd_send(c->router_event.uloop.fd, &all_nodes, &iov, 1, c); 1014 } 1015 } 1016
This page was automatically generated by LXR 0.3.1. • OpenWrt