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