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