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