1/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 dated June, 1991, or 6 (at your option) version 3 dated 29 June, 2007. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15*/ 16 17 18/* NB. This code may be called during a DHCPv4 or transaction which is in ping-wait 19 It therefore cannot use any DHCP buffer resources except outpacket, which is 20 not used by DHCPv4 code. This code may also be called when DHCP 4 or 6 isn't 21 active, so we ensure that outpacket is allocated here too */ 22 23#include "dnsmasq.h" 24 25#ifdef HAVE_DHCP6 26 27#include <netinet/icmp6.h> 28 29struct ra_param { 30 time_t now; 31 int ind, managed, other, found_context, first, adv_router; 32 char *if_name; 33 struct dhcp_netid *tags; 34 struct in6_addr link_local, link_global, ula; 35 unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval, prio; 36}; 37 38struct search_param { 39 time_t now; int iface; 40 char name[IF_NAMESIZE+1]; 41}; 42 43struct alias_param { 44 int iface; 45 struct dhcp_bridge *bridge; 46 int num_alias_ifs; 47 int max_alias_ifs; 48 int *alias_ifs; 49}; 50 51static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest); 52static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, 53 int send_iface); 54static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm); 55static int add_prefixes(struct in6_addr *local, int prefix, 56 int scope, int if_index, int flags, 57 unsigned int preferred, unsigned int valid, void *vparam); 58static int iface_search(struct in6_addr *local, int prefix, 59 int scope, int if_index, int flags, 60 int prefered, int valid, void *vparam); 61static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm); 62static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now); 63static unsigned int calc_lifetime(struct ra_interface *ra); 64static unsigned int calc_interval(struct ra_interface *ra); 65static unsigned int calc_prio(struct ra_interface *ra); 66static struct ra_interface *find_iface_param(char *iface); 67 68static int hop_limit; 69 70void ra_init(time_t now) 71{ 72 struct icmp6_filter filter; 73 int fd; 74#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6) 75 int class = IPTOS_CLASS_CS6; 76#endif 77 int val = 255; /* radvd uses this value */ 78 socklen_t len = sizeof(int); 79 struct dhcp_context *context; 80 81 /* ensure this is around even if we're not doing DHCPv6 */ 82 expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet)); 83 84 /* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */ 85 for (context = daemon->dhcp6; context; context = context->next) 86 if ((context->flags & CONTEXT_RA_NAME)) 87 break; 88 89 /* Need ICMP6 socket for transmission for DHCPv6 even when not doing RA. */ 90 91 ICMP6_FILTER_SETBLOCKALL(&filter); 92 if (daemon->doing_ra) 93 { 94 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); 95 if (context) 96 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter); 97 } 98 99 if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1 || 100 getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, &len) || 101#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6) 102 setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 || 103#endif 104 !fix_fd(fd) || 105 !set_ipv6pktinfo(fd) || 106 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)) || 107 setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)) || 108 setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == -1) 109 die (_("cannot create ICMPv6 socket: %s"), NULL, EC_BADNET); 110 111 daemon->icmp6fd = fd; 112 113 if (daemon->doing_ra) 114 ra_start_unsolicted(now, NULL); 115} 116 117void ra_start_unsolicted(time_t now, struct dhcp_context *context) 118{ 119 /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed 120 if it's not appropriate to advertise those contexts. 121 This gets re-called on a netlink route-change to re-do the advertisement 122 and pick up new interfaces */ 123 124 if (context) 125 context->ra_short_period_start = context->ra_time = now; 126 else 127 for (context = daemon->dhcp6; context; context = context->next) 128 if (!(context->flags & CONTEXT_TEMPLATE)) 129 { 130 context->ra_time = now + (rand16()/13000); /* range 0 - 5 */ 131 /* re-do frequently for a minute or so, in case the first gets lost. */ 132 context->ra_short_period_start = now; 133 } 134} 135 136void icmp6_packet(time_t now) 137{ 138 char interface[IF_NAMESIZE+1]; 139 ssize_t sz; 140 int if_index = 0; 141 struct cmsghdr *cmptr; 142 struct msghdr msg; 143 union { 144 struct cmsghdr align; /* this ensures alignment */ 145 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 146 } control_u; 147 struct sockaddr_in6 from; 148 unsigned char *packet; 149 struct iname *tmp; 150 151 /* Note: use outpacket for input buffer */ 152 msg.msg_control = control_u.control6; 153 msg.msg_controllen = sizeof(control_u); 154 msg.msg_flags = 0; 155 msg.msg_name = &from; 156 msg.msg_namelen = sizeof(from); 157 msg.msg_iov = &daemon->outpacket; 158 msg.msg_iovlen = 1; 159 160 if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8) 161 return; 162 163 packet = (unsigned char *)daemon->outpacket.iov_base; 164 165 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 166 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) 167 { 168 union { 169 unsigned char *c; 170 struct in6_pktinfo *p; 171 } p; 172 p.c = CMSG_DATA(cmptr); 173 174 if_index = p.p->ipi6_ifindex; 175 } 176 177 if (!indextoname(daemon->icmp6fd, if_index, interface)) 178 return; 179 180 if (!iface_check(AF_LOCAL, NULL, interface, NULL)) 181 return; 182 183 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) 184 if (tmp->name && wildcard_match(tmp->name, interface)) 185 return; 186 187 if (packet[1] != 0) 188 return; 189 190 if (packet[0] == ICMP6_ECHO_REPLY) 191 lease_ping_reply(&from.sin6_addr, packet, interface); 192 else if (packet[0] == ND_ROUTER_SOLICIT) 193 { 194 char *mac = ""; 195 struct dhcp_bridge *bridge, *alias; 196 197 /* look for link-layer address option for logging */ 198 if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) 199 { 200 print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); 201 mac = daemon->namebuff; 202 } 203 204 if (!option_bool(OPT_QUIET_RA)) 205 my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac); 206 207 /* If the incoming interface is an alias of some other one (as 208 specified by the --bridge-interface option), send an RA using 209 the context of the aliased interface. */ 210 for (bridge = daemon->bridges; bridge; bridge = bridge->next) 211 { 212 int bridge_index = if_nametoindex(bridge->iface); 213 if (bridge_index) 214 { 215 for (alias = bridge->alias; alias; alias = alias->next) 216 if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE)) 217 { 218 /* Send an RA on if_index with information from 219 bridge_index. */ 220 send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index); 221 break; 222 } 223 if (alias) 224 break; 225 } 226 } 227 228 /* If the incoming interface wasn't an alias, send an RA using 229 the context of the incoming interface. */ 230 if (!bridge) 231 /* source address may not be valid in solicit request. */ 232 send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL); 233 } 234} 235 236static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface) 237{ 238 struct ra_packet *ra; 239 struct ra_param parm; 240 struct sockaddr_in6 addr; 241 struct dhcp_context *context, *tmp, **up; 242 struct dhcp_netid iface_id; 243 struct dhcp_opt *opt_cfg; 244 struct ra_interface *ra_param = find_iface_param(iface_name); 245 int done_dns = 0, old_prefix = 0; 246 unsigned int min_pref_time; 247#ifdef HAVE_LINUX_NETWORK 248 FILE *f; 249#endif 250 251 parm.ind = iface; 252 parm.managed = 0; 253 parm.other = 0; 254 parm.found_context = 0; 255 parm.adv_router = 0; 256 parm.if_name = iface_name; 257 parm.first = 1; 258 parm.now = now; 259 parm.glob_pref_time = parm.link_pref_time = parm.ula_pref_time = 0; 260 parm.adv_interval = calc_interval(ra_param); 261 parm.prio = calc_prio(ra_param); 262 263 save_counter(0); 264 ra = expand(sizeof(struct ra_packet)); 265 266 ra->type = ND_ROUTER_ADVERT; 267 ra->code = 0; 268 ra->hop_limit = hop_limit; 269 ra->flags = parm.prio; 270 ra->lifetime = htons(calc_lifetime(ra_param)); 271 ra->reachable_time = 0; 272 ra->retrans_time = 0; 273 274 /* set tag with name == interface */ 275 iface_id.net = iface_name; 276 iface_id.next = NULL; 277 parm.tags = &iface_id; 278 279 for (context = daemon->dhcp6; context; context = context->next) 280 { 281 context->flags &= ~CONTEXT_RA_DONE; 282 context->netid.next = &context->netid; 283 } 284 285 if (!iface_enumerate(AF_INET6, &parm, add_prefixes)) 286 return; 287 288 /* Find smallest preferred time within address classes, 289 to use as lifetime for options. This is a rather arbitrary choice. */ 290 min_pref_time = 0xffffffff; 291 if (parm.glob_pref_time != 0 && parm.glob_pref_time < min_pref_time) 292 min_pref_time = parm.glob_pref_time; 293 294 if (parm.ula_pref_time != 0 && parm.ula_pref_time < min_pref_time) 295 min_pref_time = parm.ula_pref_time; 296 297 if (parm.link_pref_time != 0 && parm.link_pref_time < min_pref_time) 298 min_pref_time = parm.link_pref_time; 299 300 /* Look for constructed contexts associated with addresses which have gone, 301 and advertise them with preferred_time == 0 RFC 6204 4.3 L-13 */ 302 for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp) 303 { 304 tmp = context->next; 305 306 if (context->if_index == iface && (context->flags & CONTEXT_OLD)) 307 { 308 unsigned int old = difftime(now, context->address_lost_time); 309 310 if (old > context->saved_valid) 311 { 312 /* We've advertised this enough, time to go */ 313 *up = context->next; 314 free(context); 315 } 316 else 317 { 318 struct prefix_opt *opt; 319 struct in6_addr local = context->start6; 320 int do_slaac = 0; 321 322 old_prefix = 1; 323 324 /* zero net part of address */ 325 setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU)); 326 327 328 if (context->flags & CONTEXT_RA) 329 { 330 do_slaac = 1; 331 if (context->flags & CONTEXT_DHCP) 332 { 333 parm.other = 1; 334 if (!(context->flags & CONTEXT_RA_STATELESS)) 335 parm.managed = 1; 336 } 337 } 338 else 339 { 340 /* don't do RA for non-ra-only unless --enable-ra is set */ 341 if (option_bool(OPT_RA)) 342 { 343 parm.managed = 1; 344 parm.other = 1; 345 } 346 } 347 348 if ((opt = expand(sizeof(struct prefix_opt)))) 349 { 350 opt->type = ICMP6_OPT_PREFIX; 351 opt->len = 4; 352 opt->prefix_len = context->prefix; 353 /* autonomous only if we're not doing dhcp, set 354 "on-link" unless "off-link" was specified */ 355 opt->flags = (do_slaac ? 0x40 : 0) | 356 ((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80); 357 opt->valid_lifetime = htonl(context->saved_valid - old); 358 opt->preferred_lifetime = htonl(0); 359 opt->reserved = 0; 360 opt->prefix = local; 361 362 inet_ntop(AF_INET6, &local, daemon->addrbuff, ADDRSTRLEN); 363 if (!option_bool(OPT_QUIET_RA)) 364 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s old prefix", iface_name, daemon->addrbuff); 365 } 366 367 up = &context->next; 368 } 369 } 370 else 371 up = &context->next; 372 } 373 374 /* If we're advertising only old prefixes, set router lifetime to zero. */ 375 if (old_prefix && !parm.found_context) 376 ra->lifetime = htons(0); 377 378 /* No prefixes to advertise. */ 379 if (!old_prefix && !parm.found_context) 380 return; 381 382 /* If we're sending router address instead of prefix in at least on prefix, 383 include the advertisement interval option. */ 384 if (parm.adv_router) 385 { 386 put_opt6_char(ICMP6_OPT_ADV_INTERVAL); 387 put_opt6_char(1); 388 put_opt6_short(0); 389 /* interval value is in milliseconds */ 390 put_opt6_long(1000 * calc_interval(find_iface_param(iface_name))); 391 } 392 393#ifdef HAVE_LINUX_NETWORK 394 /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU 395 available from SIOCGIFMTU */ 396 sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name); 397 if ((f = fopen(daemon->namebuff, "r"))) 398 { 399 if (fgets(daemon->namebuff, MAXDNAME, f)) 400 { 401 put_opt6_char(ICMP6_OPT_MTU); 402 put_opt6_char(1); 403 put_opt6_short(0); 404 put_opt6_long(atoi(daemon->namebuff)); 405 } 406 fclose(f); 407 } 408#endif 409 410 iface_enumerate(AF_LOCAL, &send_iface, add_lla); 411 412 /* RDNSS, RFC 6106, use relevant DHCP6 options */ 413 (void)option_filter(parm.tags, NULL, daemon->dhcp_opts6); 414 415 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next) 416 { 417 int i; 418 419 /* netids match and not encapsulated? */ 420 if (!(opt_cfg->flags & DHOPT_TAGOK)) 421 continue; 422 423 if (opt_cfg->opt == OPTION6_DNS_SERVER) 424 { 425 struct in6_addr *a; 426 int len; 427 428 done_dns = 1; 429 430 if (opt_cfg->len == 0) 431 continue; 432 433 /* reduce len for any addresses we can't substitute */ 434 for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, i = 0; 435 i < opt_cfg->len; i += IN6ADDRSZ, a++) 436 if ((IN6_IS_ADDR_UNSPECIFIED(a) && parm.glob_pref_time == 0) || 437 (IN6_IS_ADDR_ULA_ZERO(a) && parm.ula_pref_time == 0) || 438 (IN6_IS_ADDR_LINK_LOCAL_ZERO(a) && parm.link_pref_time == 0)) 439 len -= IN6ADDRSZ; 440 441 if (len != 0) 442 { 443 put_opt6_char(ICMP6_OPT_RDNSS); 444 put_opt6_char((len/8) + 1); 445 put_opt6_short(0); 446 put_opt6_long(min_pref_time); 447 448 for (a = (struct in6_addr *)opt_cfg->val, i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++) 449 if (IN6_IS_ADDR_UNSPECIFIED(a)) 450 { 451 if (parm.glob_pref_time != 0) 452 put_opt6(&parm.link_global, IN6ADDRSZ); 453 } 454 else if (IN6_IS_ADDR_ULA_ZERO(a)) 455 { 456 if (parm.ula_pref_time != 0) 457 put_opt6(&parm.ula, IN6ADDRSZ); 458 } 459 else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a)) 460 { 461 if (parm.link_pref_time != 0) 462 put_opt6(&parm.link_local, IN6ADDRSZ); 463 } 464 else 465 put_opt6(a, IN6ADDRSZ); 466 } 467 } 468 469 if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0) 470 { 471 int len = ((opt_cfg->len+7)/8); 472 473 put_opt6_char(ICMP6_OPT_DNSSL); 474 put_opt6_char(len + 1); 475 put_opt6_short(0); 476 put_opt6_long(min_pref_time); 477 put_opt6(opt_cfg->val, opt_cfg->len); 478 479 /* pad */ 480 for (i = opt_cfg->len; i < len * 8; i++) 481 put_opt6_char(0); 482 } 483 } 484 485 if (daemon->port == NAMESERVER_PORT && !done_dns && parm.link_pref_time != 0) 486 { 487 /* default == us, as long as we are supplying DNS service. */ 488 put_opt6_char(ICMP6_OPT_RDNSS); 489 put_opt6_char(3); 490 put_opt6_short(0); 491 put_opt6_long(min_pref_time); 492 put_opt6(&parm.link_local, IN6ADDRSZ); 493 } 494 495 /* set managed bits unless we're providing only RA on this link */ 496 if (parm.managed) 497 ra->flags |= 0x80; /* M flag, managed, */ 498 if (parm.other) 499 ra->flags |= 0x40; /* O flag, other */ 500 501 /* decide where we're sending */ 502 memset(&addr, 0, sizeof(addr)); 503#ifdef HAVE_SOCKADDR_SA_LEN 504 addr.sin6_len = sizeof(struct sockaddr_in6); 505#endif 506 addr.sin6_family = AF_INET6; 507 addr.sin6_port = htons(IPPROTO_ICMPV6); 508 if (dest) 509 { 510 addr.sin6_addr = *dest; 511 if (IN6_IS_ADDR_LINKLOCAL(dest) || 512 IN6_IS_ADDR_MC_LINKLOCAL(dest)) 513 addr.sin6_scope_id = iface; 514 } 515 else 516 { 517 inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr); 518 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface)); 519 } 520 521 while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, 522 save_counter(0), 0, (struct sockaddr *)&addr, 523 sizeof(addr)))); 524 525} 526 527static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest) 528{ 529 /* Send an RA on the same interface that the RA content is based 530 on. */ 531 send_ra_alias(now, iface, iface_name, dest, iface); 532} 533 534static int add_prefixes(struct in6_addr *local, int prefix, 535 int scope, int if_index, int flags, 536 unsigned int preferred, unsigned int valid, void *vparam) 537{ 538 struct ra_param *param = vparam; 539 540 (void)scope; /* warning */ 541 542 if (if_index == param->ind) 543 { 544 if (IN6_IS_ADDR_LINKLOCAL(local)) 545 { 546 /* Can there be more than one LL address? 547 Select the one with the longest preferred time 548 if there is. */ 549 if (preferred > param->link_pref_time) 550 { 551 param->link_pref_time = preferred; 552 param->link_local = *local; 553 } 554 } 555 else if (!IN6_IS_ADDR_LOOPBACK(local) && 556 !IN6_IS_ADDR_MULTICAST(local)) 557 { 558 int real_prefix = 0; 559 int do_slaac = 0; 560 int deprecate = 0; 561 int constructed = 0; 562 int adv_router = 0; 563 int off_link = 0; 564 unsigned int time = 0xffffffff; 565 struct dhcp_context *context; 566 567 for (context = daemon->dhcp6; context; context = context->next) 568 if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && 569 prefix <= context->prefix && 570 is_same_net6(local, &context->start6, context->prefix) && 571 is_same_net6(local, &context->end6, context->prefix)) 572 { 573 context->saved_valid = valid; 574 575 if (context->flags & CONTEXT_RA) 576 { 577 do_slaac = 1; 578 if (context->flags & CONTEXT_DHCP) 579 { 580 param->other = 1; 581 if (!(context->flags & CONTEXT_RA_STATELESS)) 582 param->managed = 1; 583 } 584 } 585 else 586 { 587 /* don't do RA for non-ra-only unless --enable-ra is set */ 588 if (!option_bool(OPT_RA)) 589 continue; 590 param->managed = 1; 591 param->other = 1; 592 } 593 594 /* Configured to advertise router address, not prefix. See RFC 3775 7.2 595 In this case we do all addresses associated with a context, 596 hence the real_prefix setting here. */ 597 if (context->flags & CONTEXT_RA_ROUTER) 598 { 599 adv_router = 1; 600 param->adv_router = 1; 601 real_prefix = context->prefix; 602 } 603 604 /* find floor time, don't reduce below 3 * RA interval. */ 605 if (time > context->lease_time) 606 { 607 time = context->lease_time; 608 if (time < ((unsigned int)(3 * param->adv_interval))) 609 time = 3 * param->adv_interval; 610 } 611 612 if (context->flags & CONTEXT_DEPRECATE) 613 deprecate = 1; 614 615 if (context->flags & CONTEXT_CONSTRUCTED) 616 constructed = 1; 617 618 619 /* collect dhcp-range tags */ 620 if (context->netid.next == &context->netid && context->netid.net) 621 { 622 context->netid.next = param->tags; 623 param->tags = &context->netid; 624 } 625 626 /* subsequent prefixes on the same interface 627 and subsequent instances of this prefix don't need timers. 628 Be careful not to find the same prefix twice with different 629 addresses unless we're advertising the actual addresses. */ 630 if (!(context->flags & CONTEXT_RA_DONE)) 631 { 632 if (!param->first) 633 context->ra_time = 0; 634 context->flags |= CONTEXT_RA_DONE; 635 real_prefix = context->prefix; 636 off_link = (context->flags & CONTEXT_RA_OFF_LINK); 637 } 638 639 param->first = 0; 640 param->found_context = 1; 641 } 642 643 /* configured time is ceiling */ 644 if (!constructed || valid > time) 645 valid = time; 646 647 if (flags & IFACE_DEPRECATED) 648 preferred = 0; 649 650 if (deprecate) 651 time = 0; 652 653 /* configured time is ceiling */ 654 if (!constructed || preferred > time) 655 preferred = time; 656 657 if (IN6_IS_ADDR_ULA(local)) 658 { 659 if (preferred > param->ula_pref_time) 660 { 661 param->ula_pref_time = preferred; 662 param->ula = *local; 663 } 664 } 665 else 666 { 667 if (preferred > param->glob_pref_time) 668 { 669 param->glob_pref_time = preferred; 670 param->link_global = *local; 671 } 672 } 673 674 if (real_prefix != 0) 675 { 676 struct prefix_opt *opt; 677 678 if ((opt = expand(sizeof(struct prefix_opt)))) 679 { 680 /* zero net part of address */ 681 if (!adv_router) 682 setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU)); 683 684 opt->type = ICMP6_OPT_PREFIX; 685 opt->len = 4; 686 opt->prefix_len = real_prefix; 687 /* autonomous only if we're not doing dhcp, set 688 "on-link" unless "off-link" was specified */ 689 opt->flags = (off_link ? 0 : 0x80); 690 if (do_slaac) 691 opt->flags |= 0x40; 692 if (adv_router) 693 opt->flags |= 0x20; 694 opt->valid_lifetime = htonl(valid); 695 opt->preferred_lifetime = htonl(preferred); 696 opt->reserved = 0; 697 opt->prefix = *local; 698 699 inet_ntop(AF_INET6, local, daemon->addrbuff, ADDRSTRLEN); 700 if (!option_bool(OPT_QUIET_RA)) 701 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff); 702 } 703 } 704 } 705 } 706 return 1; 707} 708 709static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm) 710{ 711 (void)type; 712 713 if (index == *((int *)parm)) 714 { 715 /* size is in units of 8 octets and includes type and length (2 bytes) 716 add 7 to round up */ 717 int len = (maclen + 9) >> 3; 718 unsigned char *p = expand(len << 3); 719 memset(p, 0, len << 3); 720 *p++ = ICMP6_OPT_SOURCE_MAC; 721 *p++ = len; 722 memcpy(p, mac, maclen); 723 724 return 0; 725 } 726 727 return 1; 728} 729 730time_t periodic_ra(time_t now) 731{ 732 struct search_param param; 733 struct dhcp_context *context; 734 time_t next_event; 735 struct alias_param aparam; 736 737 param.now = now; 738 param.iface = 0; 739 740 while (1) 741 { 742 /* find overdue events, and time of first future event */ 743 for (next_event = 0, context = daemon->dhcp6; context; context = context->next) 744 if (context->ra_time != 0) 745 { 746 if (difftime(context->ra_time, now) <= 0.0) 747 break; /* overdue */ 748 749 if (next_event == 0 || difftime(next_event, context->ra_time) > 0.0) 750 next_event = context->ra_time; 751 } 752 753 /* none overdue */ 754 if (!context) 755 break; 756 757 if ((context->flags & CONTEXT_OLD) && 758 context->if_index != 0 && 759 indextoname(daemon->icmp6fd, context->if_index, param.name)) 760 { 761 /* A context for an old address. We'll not find the interface by 762 looking for addresses, but we know it anyway, since the context is 763 constructed */ 764 param.iface = context->if_index; 765 new_timeout(context, param.name, now); 766 } 767 else if (iface_enumerate(AF_INET6, ¶m, iface_search)) 768 /* There's a context overdue, but we can't find an interface 769 associated with it, because it's for a subnet we dont 770 have an interface on. Probably we're doing DHCP on 771 a remote subnet via a relay. Zero the timer, since we won't 772 ever be able to send ra's and satistfy it. */ 773 context->ra_time = 0; 774 775 if (param.iface != 0 && 776 iface_check(AF_LOCAL, NULL, param.name, NULL)) 777 { 778 struct iname *tmp; 779 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) 780 if (tmp->name && wildcard_match(tmp->name, param.name)) 781 break; 782 if (!tmp) 783 { 784 send_ra(now, param.iface, param.name, NULL); 785 786 /* Also send on all interfaces that are aliases of this 787 one. */ 788 for (aparam.bridge = daemon->bridges; 789 aparam.bridge; 790 aparam.bridge = aparam.bridge->next) 791 if ((int)if_nametoindex(aparam.bridge->iface) == param.iface) 792 { 793 /* Count the number of alias interfaces for this 794 'bridge', by calling iface_enumerate with 795 send_ra_to_aliases and NULL alias_ifs. */ 796 aparam.iface = param.iface; 797 aparam.alias_ifs = NULL; 798 aparam.num_alias_ifs = 0; 799 iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases); 800 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)", 801 param.name, daemon->addrbuff, aparam.num_alias_ifs); 802 803 /* Allocate memory to store the alias interface 804 indices. */ 805 aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs * 806 sizeof(int)); 807 if (aparam.alias_ifs) 808 { 809 /* Use iface_enumerate again to get the alias 810 interface indices, then send on each of 811 those. */ 812 aparam.max_alias_ifs = aparam.num_alias_ifs; 813 aparam.num_alias_ifs = 0; 814 iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases); 815 for (; aparam.num_alias_ifs; aparam.num_alias_ifs--) 816 { 817 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d", 818 param.name, daemon->addrbuff, 819 aparam.alias_ifs[aparam.num_alias_ifs - 1]); 820 send_ra_alias(now, 821 param.iface, 822 param.name, 823 NULL, 824 aparam.alias_ifs[aparam.num_alias_ifs - 1]); 825 } 826 free(aparam.alias_ifs); 827 } 828 829 /* The source interface can only appear in at most 830 one --bridge-interface. */ 831 break; 832 } 833 } 834 } 835 } 836 return next_event; 837} 838 839static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm) 840{ 841 struct alias_param *aparam = (struct alias_param *)parm; 842 char ifrn_name[IFNAMSIZ]; 843 struct dhcp_bridge *alias; 844 845 (void)type; 846 (void)mac; 847 (void)maclen; 848 849 if (if_indextoname(index, ifrn_name)) 850 for (alias = aparam->bridge->alias; alias; alias = alias->next) 851 if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ)) 852 { 853 if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs)) 854 aparam->alias_ifs[aparam->num_alias_ifs] = index; 855 aparam->num_alias_ifs++; 856 } 857 858 return 1; 859} 860 861static int iface_search(struct in6_addr *local, int prefix, 862 int scope, int if_index, int flags, 863 int preferred, int valid, void *vparam) 864{ 865 struct search_param *param = vparam; 866 struct dhcp_context *context; 867 868 (void)scope; 869 (void)preferred; 870 (void)valid; 871 872 for (context = daemon->dhcp6; context; context = context->next) 873 if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && 874 prefix <= context->prefix && 875 is_same_net6(local, &context->start6, context->prefix) && 876 is_same_net6(local, &context->end6, context->prefix) && 877 context->ra_time != 0 && 878 difftime(context->ra_time, param->now) <= 0.0) 879 { 880 /* found an interface that's overdue for RA determine new 881 timeout value and arrange for RA to be sent unless interface is 882 still doing DAD.*/ 883 884 if (!(flags & IFACE_TENTATIVE)) 885 param->iface = if_index; 886 887 /* should never fail */ 888 if (!indextoname(daemon->icmp6fd, if_index, param->name)) 889 { 890 param->iface = 0; 891 return 0; 892 } 893 894 new_timeout(context, param->name, param->now); 895 896 /* zero timers for other contexts on the same subnet, so they don't timeout 897 independently */ 898 for (context = context->next; context; context = context->next) 899 if (prefix <= context->prefix && 900 is_same_net6(local, &context->start6, context->prefix) && 901 is_same_net6(local, &context->end6, context->prefix)) 902 context->ra_time = 0; 903 904 return 0; /* found, abort */ 905 } 906 907 return 1; /* keep searching */ 908} 909 910static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now) 911{ 912 if (difftime(now, context->ra_short_period_start) < 60.0) 913 /* range 5 - 20 */ 914 context->ra_time = now + 5 + (rand16()/4400); 915 else 916 { 917 /* range 3/4 - 1 times MaxRtrAdvInterval */ 918 unsigned int adv_interval = calc_interval(find_iface_param(iface_name)); 919 context->ra_time = now + (3 * adv_interval)/4 + ((adv_interval * (unsigned int)rand16()) >> 18); 920 } 921} 922 923static struct ra_interface *find_iface_param(char *iface) 924{ 925 struct ra_interface *ra; 926 927 for (ra = daemon->ra_interfaces; ra; ra = ra->next) 928 if (wildcard_match(ra->name, iface)) 929 return ra; 930 931 return NULL; 932} 933 934static unsigned int calc_interval(struct ra_interface *ra) 935{ 936 int interval = 600; 937 938 if (ra && ra->interval != 0) 939 { 940 interval = ra->interval; 941 if (interval > 1800) 942 interval = 1800; 943 else if (interval < 4) 944 interval = 4; 945 } 946 947 return (unsigned int)interval; 948} 949 950static unsigned int calc_lifetime(struct ra_interface *ra) 951{ 952 int lifetime, interval = (int)calc_interval(ra); 953 954 if (!ra || ra->lifetime == -1) /* not specified */ 955 lifetime = 3 * interval; 956 else 957 { 958 lifetime = ra->lifetime; 959 if (lifetime < interval && lifetime != 0) 960 lifetime = interval; 961 else if (lifetime > 9000) 962 lifetime = 9000; 963 } 964 965 return (unsigned int)lifetime; 966} 967 968static unsigned int calc_prio(struct ra_interface *ra) 969{ 970 if (ra) 971 return ra->prio; 972 973 return 0; 974} 975 976#endif 977