1 /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
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.
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.
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/>.
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 */
27 #include <netinet/icmp6.h>
31 int ind, managed, other, first, adv_router;
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 struct dhcp_context *found_context;
40 time_t now; int iface;
41 char name[IF_NAMESIZE+1];
46 struct dhcp_bridge *bridge;
52 static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
53 static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest,
55 static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm);
56 static int add_prefixes(struct in6_addr *local, int prefix,
57 int scope, int if_index, int flags,
58 unsigned int preferred, unsigned int valid, void *vparam);
59 static int iface_search(struct in6_addr *local, int prefix,
60 int scope, int if_index, int flags,
61 int prefered, int valid, void *vparam);
62 static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
63 static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now);
64 static unsigned int calc_lifetime(struct ra_interface *ra);
65 static unsigned int calc_interval(struct ra_interface *ra);
66 static unsigned int calc_prio(struct ra_interface *ra);
67 static struct ra_interface *find_iface_param(char *iface);
71 void ra_init(time_t now)
73 struct icmp6_filter filter;
75 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
76 int class = IPTOS_CLASS_CS6;
78 int val = 255; /* radvd uses this value */
79 socklen_t len = sizeof(int);
80 struct dhcp_context *context;
82 /* ensure this is around even if we're not doing DHCPv6 */
83 expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
85 /* See if we're guessing SLAAC addresses, if so we need to receive ping replies */
86 for (context = daemon->dhcp6; context; context = context->next)
87 if ((context->flags & CONTEXT_RA_NAME))
90 /* Need ICMP6 socket for transmission for DHCPv6 even when not doing RA. */
92 ICMP6_FILTER_SETBLOCKALL(&filter);
95 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
97 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter);
100 if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1 ||
101 getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, &len) ||
102 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
103 setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
106 !set_ipv6pktinfo(fd) ||
107 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)) ||
108 setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)) ||
109 setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == -1)
110 die (_("cannot create ICMPv6 socket: %s"), NULL, EC_BADNET);
112 daemon->icmp6fd = fd;
114 if (daemon->doing_ra)
115 ra_start_unsolicited(now, NULL);
118 void ra_start_unsolicited(time_t now, struct dhcp_context *context)
120 /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
121 if it's not appropriate to advertise those contexts.
122 This gets re-called on a netlink route-change to re-do the advertisement
123 and pick up new interfaces */
127 context->ra_short_period_start = now;
128 /* start after 1 second to get logging right at startup. */
129 context->ra_time = now + 1;
132 for (context = daemon->dhcp6; context; context = context->next)
133 if (!(context->flags & CONTEXT_TEMPLATE))
135 context->ra_time = now + (rand16()/13000); /* range 0 - 5 */
136 /* re-do frequently for a minute or so, in case the first gets lost. */
137 context->ra_short_period_start = now;
141 void icmp6_packet(time_t now)
143 char interface[IF_NAMESIZE+1];
146 struct cmsghdr *cmptr;
149 struct cmsghdr align; /* this ensures alignment */
150 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
152 struct sockaddr_in6 from;
153 unsigned char *packet;
156 /* Note: use outpacket for input buffer */
157 msg.msg_control = control_u.control6;
158 msg.msg_controllen = sizeof(control_u);
160 msg.msg_name = &from;
161 msg.msg_namelen = sizeof(from);
162 msg.msg_iov = &daemon->outpacket;
165 if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8)
168 packet = (unsigned char *)daemon->outpacket.iov_base;
170 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
171 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
175 struct in6_pktinfo *p;
177 p.c = CMSG_DATA(cmptr);
179 if_index = p.p->ipi6_ifindex;
182 if (!indextoname(daemon->icmp6fd, if_index, interface))
185 if (!iface_check(AF_LOCAL, NULL, interface, NULL))
188 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
189 if (tmp->name && wildcard_match(tmp->name, interface))
195 if (packet[0] == ICMP6_ECHO_REPLY)
196 lease_ping_reply(&from.sin6_addr, packet, interface);
197 else if (packet[0] == ND_ROUTER_SOLICIT)
200 struct dhcp_bridge *bridge, *alias;
206 dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
209 /* look for link-layer address option for logging */
210 for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz)
214 if (opt_sz == 0 || opt_sz > rem)
215 return; /* Bad packet */
217 if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME))
219 print_mac(daemon->namebuff, &p[2], opt_sz - 2);
220 mac = daemon->namebuff;
224 if (!option_bool(OPT_QUIET_RA))
225 my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
227 /* If the incoming interface is an alias of some other one (as
228 specified by the --bridge-interface option), send an RA using
229 the context of the aliased interface. */
230 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
232 int bridge_index = if_nametoindex(bridge->iface);
235 for (alias = bridge->alias; alias; alias = alias->next)
236 if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
238 /* Send an RA on if_index with information from
240 send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
248 /* If the incoming interface wasn't an alias, send an RA using
249 the context of the incoming interface. */
251 /* source address may not be valid in solicit request. */
252 send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
256 static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
258 struct ra_packet *ra;
259 struct ra_param parm;
260 struct sockaddr_in6 addr;
261 struct dhcp_context *context, *tmp, **up;
262 struct dhcp_netid iface_id;
263 struct dhcp_opt *opt_cfg;
264 struct ra_interface *ra_param = find_iface_param(iface_name);
265 int done_dns = 0, old_prefix = 0, mtu = 0;
266 unsigned int min_pref_time;
267 #ifdef HAVE_LINUX_NETWORK
274 parm.found_context = NULL;
276 parm.if_name = iface_name;
279 parm.glob_pref_time = parm.link_pref_time = parm.ula_pref_time = 0;
280 parm.adv_interval = calc_interval(ra_param);
281 parm.prio = calc_prio(ra_param);
285 if (!(ra = expand(sizeof(struct ra_packet))))
288 ra->type = ND_ROUTER_ADVERT;
290 ra->hop_limit = hop_limit;
291 ra->flags = parm.prio;
292 ra->lifetime = htons(calc_lifetime(ra_param));
293 ra->reachable_time = 0;
294 ra->retrans_time = 0;
296 /* set tag with name == interface */
297 iface_id.net = iface_name;
298 iface_id.next = NULL;
299 parm.tags = &iface_id;
301 for (context = daemon->dhcp6; context; context = context->next)
303 context->flags &= ~CONTEXT_RA_DONE;
304 context->netid.next = &context->netid;
307 /* If no link-local address then we can't advertise since source address of
308 advertisement must be link local address: RFC 4861 para 6.1.2. */
309 if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
310 parm.link_pref_time == 0)
313 /* Find smallest preferred time within address classes,
314 to use as lifetime for options. This is a rather arbitrary choice. */
315 min_pref_time = 0xffffffff;
316 if (parm.glob_pref_time != 0 && parm.glob_pref_time < min_pref_time)
317 min_pref_time = parm.glob_pref_time;
319 if (parm.ula_pref_time != 0 && parm.ula_pref_time < min_pref_time)
320 min_pref_time = parm.ula_pref_time;
322 if (parm.link_pref_time != 0 && parm.link_pref_time < min_pref_time)
323 min_pref_time = parm.link_pref_time;
325 /* Look for constructed contexts associated with addresses which have gone,
326 and advertise them with preferred_time == 0 RFC 6204 4.3 L-13 */
327 for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
331 if (context->if_index == iface && (context->flags & CONTEXT_OLD))
333 unsigned int old = difftime(now, context->address_lost_time);
335 if (old > context->saved_valid)
337 /* We've advertised this enough, time to go */
339 /* If this context held the timeout, and there's another context in use
340 transfer the timeout there. */
341 if (context->ra_time != 0 && parm.found_context && parm.found_context->ra_time == 0)
342 new_timeout(parm.found_context, iface_name, now);
349 struct prefix_opt *opt;
350 struct in6_addr local = context->start6;
355 /* zero net part of address */
356 setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
359 if (context->flags & CONTEXT_RA)
362 if (context->flags & CONTEXT_DHCP)
365 if (!(context->flags & CONTEXT_RA_STATELESS))
371 /* don't do RA for non-ra-only unless --enable-ra is set */
372 if (option_bool(OPT_RA))
379 if ((opt = expand(sizeof(struct prefix_opt))))
381 opt->type = ICMP6_OPT_PREFIX;
383 opt->prefix_len = context->prefix;
384 /* autonomous only if we're not doing dhcp, set
385 "on-link" unless "off-link" was specified */
386 opt->flags = (do_slaac ? 0x40 : 0) |
387 ((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80);
388 opt->valid_lifetime = htonl(context->saved_valid - old);
389 opt->preferred_lifetime = htonl(0);
393 inet_ntop(AF_INET6, &local, daemon->addrbuff, ADDRSTRLEN);
394 if (!option_bool(OPT_QUIET_RA))
395 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s old prefix", iface_name, daemon->addrbuff);
405 /* If we're advertising only old prefixes, set router lifetime to zero. */
406 if (old_prefix && !parm.found_context)
407 ra->lifetime = htons(0);
409 /* No prefixes to advertise. */
410 if (!old_prefix && !parm.found_context)
413 /* If we're sending router address instead of prefix in at least on prefix,
414 include the advertisement interval option. */
417 put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
420 /* interval value is in milliseconds */
421 put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
424 /* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */
425 /* an MTU of -1 prevents the option from being sent. */
428 #ifdef HAVE_LINUX_NETWORK
429 /* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
430 available from SIOCGIFMTU */
433 char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
434 sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? mtu_name : iface_name);
435 if ((f = fopen(daemon->namebuff, "r")))
437 if (fgets(daemon->namebuff, MAXDNAME, f))
438 mtu = atoi(daemon->namebuff);
445 put_opt6_char(ICMP6_OPT_MTU);
451 iface_enumerate(AF_LOCAL, &send_iface, add_lla);
453 /* RDNSS, RFC 6106, use relevant DHCP6 options */
454 (void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
456 for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
460 /* netids match and not encapsulated? */
461 if (!(opt_cfg->flags & DHOPT_TAGOK))
464 if (opt_cfg->opt == OPTION6_DNS_SERVER)
471 if (opt_cfg->len == 0)
474 /* reduce len for any addresses we can't substitute */
475 for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, i = 0;
476 i < opt_cfg->len; i += IN6ADDRSZ, a++)
477 if ((IN6_IS_ADDR_UNSPECIFIED(a) && parm.glob_pref_time == 0) ||
478 (IN6_IS_ADDR_ULA_ZERO(a) && parm.ula_pref_time == 0) ||
479 (IN6_IS_ADDR_LINK_LOCAL_ZERO(a) && parm.link_pref_time == 0))
484 put_opt6_char(ICMP6_OPT_RDNSS);
485 put_opt6_char((len/8) + 1);
487 put_opt6_long(min_pref_time);
489 for (a = (struct in6_addr *)opt_cfg->val, i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
490 if (IN6_IS_ADDR_UNSPECIFIED(a))
492 if (parm.glob_pref_time != 0)
493 put_opt6(&parm.link_global, IN6ADDRSZ);
495 else if (IN6_IS_ADDR_ULA_ZERO(a))
497 if (parm.ula_pref_time != 0)
498 put_opt6(&parm.ula, IN6ADDRSZ);
500 else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
502 if (parm.link_pref_time != 0)
503 put_opt6(&parm.link_local, IN6ADDRSZ);
506 put_opt6(a, IN6ADDRSZ);
510 if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0)
512 int len = ((opt_cfg->len+7)/8);
514 put_opt6_char(ICMP6_OPT_DNSSL);
515 put_opt6_char(len + 1);
517 put_opt6_long(min_pref_time);
518 put_opt6(opt_cfg->val, opt_cfg->len);
521 for (i = opt_cfg->len; i < len * 8; i++)
526 if (daemon->port == NAMESERVER_PORT && !done_dns && parm.link_pref_time != 0)
528 /* default == us, as long as we are supplying DNS service. */
529 put_opt6_char(ICMP6_OPT_RDNSS);
532 put_opt6_long(min_pref_time);
533 put_opt6(&parm.link_local, IN6ADDRSZ);
536 /* set managed bits unless we're providing only RA on this link */
538 ra->flags |= 0x80; /* M flag, managed, */
540 ra->flags |= 0x40; /* O flag, other */
542 /* decide where we're sending */
543 memset(&addr, 0, sizeof(addr));
544 #ifdef HAVE_SOCKADDR_SA_LEN
545 addr.sin6_len = sizeof(struct sockaddr_in6);
547 addr.sin6_family = AF_INET6;
548 addr.sin6_port = htons(IPPROTO_ICMPV6);
551 addr.sin6_addr = *dest;
552 if (IN6_IS_ADDR_LINKLOCAL(dest) ||
553 IN6_IS_ADDR_MC_LINKLOCAL(dest))
554 addr.sin6_scope_id = iface;
558 inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
559 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
564 struct sockaddr_in6 src;
565 src.sin6_family = AF_INET6;
566 src.sin6_addr = parm.link_local;
568 dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
572 while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
573 save_counter(-1), 0, (struct sockaddr *)&addr,
578 static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
580 /* Send an RA on the same interface that the RA content is based
582 send_ra_alias(now, iface, iface_name, dest, iface);
585 static int add_prefixes(struct in6_addr *local, int prefix,
586 int scope, int if_index, int flags,
587 unsigned int preferred, unsigned int valid, void *vparam)
589 struct ra_param *param = vparam;
591 (void)scope; /* warning */
593 if (if_index == param->ind)
595 if (IN6_IS_ADDR_LINKLOCAL(local))
597 /* Can there be more than one LL address?
598 Select the one with the longest preferred time
600 if (preferred > param->link_pref_time)
602 param->link_pref_time = preferred;
603 param->link_local = *local;
606 else if (!IN6_IS_ADDR_LOOPBACK(local) &&
607 !IN6_IS_ADDR_MULTICAST(local))
615 unsigned int time = 0xffffffff;
616 struct dhcp_context *context;
618 for (context = daemon->dhcp6; context; context = context->next)
619 if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
620 prefix <= context->prefix &&
621 is_same_net6(local, &context->start6, context->prefix) &&
622 is_same_net6(local, &context->end6, context->prefix))
624 context->saved_valid = valid;
626 if (context->flags & CONTEXT_RA)
629 if (context->flags & CONTEXT_DHCP)
632 if (!(context->flags & CONTEXT_RA_STATELESS))
638 /* don't do RA for non-ra-only unless --enable-ra is set */
639 if (!option_bool(OPT_RA))
645 /* Configured to advertise router address, not prefix. See RFC 3775 7.2
646 In this case we do all addresses associated with a context,
647 hence the real_prefix setting here. */
648 if (context->flags & CONTEXT_RA_ROUTER)
651 param->adv_router = 1;
652 real_prefix = context->prefix;
655 /* find floor time, don't reduce below 3 * RA interval.
656 If the lease time has been left as default, don't
657 use that as a floor. */
658 if ((context->flags & CONTEXT_SETLEASE) &&
659 time > context->lease_time)
661 time = context->lease_time;
662 if (time < ((unsigned int)(3 * param->adv_interval)))
663 time = 3 * param->adv_interval;
666 if (context->flags & CONTEXT_DEPRECATE)
669 if (context->flags & CONTEXT_CONSTRUCTED)
673 /* collect dhcp-range tags */
674 if (context->netid.next == &context->netid && context->netid.net)
676 context->netid.next = param->tags;
677 param->tags = &context->netid;
680 /* subsequent prefixes on the same interface
681 and subsequent instances of this prefix don't need timers.
682 Be careful not to find the same prefix twice with different
683 addresses unless we're advertising the actual addresses. */
684 if (!(context->flags & CONTEXT_RA_DONE))
687 context->ra_time = 0;
688 context->flags |= CONTEXT_RA_DONE;
689 real_prefix = context->prefix;
690 off_link = (context->flags & CONTEXT_RA_OFF_LINK);
694 /* found_context is the _last_ one we found, so if there's
695 more than one, it's not the first. */
696 param->found_context = context;
699 /* configured time is ceiling */
700 if (!constructed || valid > time)
703 if (flags & IFACE_DEPRECATED)
709 /* configured time is ceiling */
710 if (!constructed || preferred > time)
713 if (IN6_IS_ADDR_ULA(local))
715 if (preferred > param->ula_pref_time)
717 param->ula_pref_time = preferred;
723 if (preferred > param->glob_pref_time)
725 param->glob_pref_time = preferred;
726 param->link_global = *local;
730 if (real_prefix != 0)
732 struct prefix_opt *opt;
734 if ((opt = expand(sizeof(struct prefix_opt))))
736 /* zero net part of address */
738 setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
740 opt->type = ICMP6_OPT_PREFIX;
742 opt->prefix_len = real_prefix;
743 /* autonomous only if we're not doing dhcp, set
744 "on-link" unless "off-link" was specified */
745 opt->flags = (off_link ? 0 : 0x80);
750 opt->valid_lifetime = htonl(valid);
751 opt->preferred_lifetime = htonl(preferred);
753 opt->prefix = *local;
755 inet_ntop(AF_INET6, local, daemon->addrbuff, ADDRSTRLEN);
756 if (!option_bool(OPT_QUIET_RA))
757 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
765 static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm)
769 if (index == *((int *)parm))
771 /* size is in units of 8 octets and includes type and length (2 bytes)
773 int len = (maclen + 9) >> 3;
774 unsigned char *p = expand(len << 3);
777 memset(p, 0, len << 3);
778 *p++ = ICMP6_OPT_SOURCE_MAC;
780 memcpy(p, mac, maclen);
788 time_t periodic_ra(time_t now)
790 struct search_param param;
791 struct dhcp_context *context;
793 struct alias_param aparam;
800 /* find overdue events, and time of first future event */
801 for (next_event = 0, context = daemon->dhcp6; context; context = context->next)
802 if (context->ra_time != 0)
804 if (difftime(context->ra_time, now) <= 0.0)
807 if (next_event == 0 || difftime(next_event, context->ra_time) > 0.0)
808 next_event = context->ra_time;
815 if ((context->flags & CONTEXT_OLD) &&
816 context->if_index != 0 &&
817 indextoname(daemon->icmp6fd, context->if_index, param.name))
819 /* A context for an old address. We'll not find the interface by
820 looking for addresses, but we know it anyway, since the context is
822 param.iface = context->if_index;
823 new_timeout(context, param.name, now);
825 else if (iface_enumerate(AF_INET6, ¶m, iface_search))
826 /* There's a context overdue, but we can't find an interface
827 associated with it, because it's for a subnet we dont
828 have an interface on. Probably we're doing DHCP on
829 a remote subnet via a relay. Zero the timer, since we won't
830 ever be able to send ra's and satisfy it. */
831 context->ra_time = 0;
833 if (param.iface != 0 &&
834 iface_check(AF_LOCAL, NULL, param.name, NULL))
837 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
838 if (tmp->name && wildcard_match(tmp->name, param.name))
842 send_ra(now, param.iface, param.name, NULL);
844 /* Also send on all interfaces that are aliases of this
846 for (aparam.bridge = daemon->bridges;
848 aparam.bridge = aparam.bridge->next)
849 if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
851 /* Count the number of alias interfaces for this
852 'bridge', by calling iface_enumerate with
853 send_ra_to_aliases and NULL alias_ifs. */
854 aparam.iface = param.iface;
855 aparam.alias_ifs = NULL;
856 aparam.num_alias_ifs = 0;
857 iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
858 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)",
859 param.name, daemon->addrbuff, aparam.num_alias_ifs);
861 /* Allocate memory to store the alias interface
863 aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
865 if (aparam.alias_ifs)
867 /* Use iface_enumerate again to get the alias
868 interface indices, then send on each of
870 aparam.max_alias_ifs = aparam.num_alias_ifs;
871 aparam.num_alias_ifs = 0;
872 iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
873 for (; aparam.num_alias_ifs; aparam.num_alias_ifs--)
875 my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d",
876 param.name, daemon->addrbuff,
877 aparam.alias_ifs[aparam.num_alias_ifs - 1]);
882 aparam.alias_ifs[aparam.num_alias_ifs - 1]);
884 free(aparam.alias_ifs);
887 /* The source interface can only appear in at most
888 one --bridge-interface. */
897 static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
899 struct alias_param *aparam = (struct alias_param *)parm;
900 char ifrn_name[IFNAMSIZ];
901 struct dhcp_bridge *alias;
907 if (if_indextoname(index, ifrn_name))
908 for (alias = aparam->bridge->alias; alias; alias = alias->next)
909 if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ))
911 if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs))
912 aparam->alias_ifs[aparam->num_alias_ifs] = index;
913 aparam->num_alias_ifs++;
919 static int iface_search(struct in6_addr *local, int prefix,
920 int scope, int if_index, int flags,
921 int preferred, int valid, void *vparam)
923 struct search_param *param = vparam;
924 struct dhcp_context *context;
931 /* ignore interfaces we're not doing DHCP on. */
932 if (!indextoname(daemon->icmp6fd, if_index, param->name) ||
933 !iface_check(AF_LOCAL, NULL, param->name, NULL))
936 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
937 if (tmp->name && wildcard_match(tmp->name, param->name))
940 for (context = daemon->dhcp6; context; context = context->next)
941 if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
942 prefix <= context->prefix &&
943 is_same_net6(local, &context->start6, context->prefix) &&
944 is_same_net6(local, &context->end6, context->prefix) &&
945 context->ra_time != 0 &&
946 difftime(context->ra_time, param->now) <= 0.0)
948 /* found an interface that's overdue for RA determine new
949 timeout value and arrange for RA to be sent unless interface is
951 if (!(flags & IFACE_TENTATIVE))
952 param->iface = if_index;
954 new_timeout(context, param->name, param->now);
956 /* zero timers for other contexts on the same subnet, so they don't timeout
958 for (context = context->next; context; context = context->next)
959 if (prefix <= context->prefix &&
960 is_same_net6(local, &context->start6, context->prefix) &&
961 is_same_net6(local, &context->end6, context->prefix))
962 context->ra_time = 0;
964 return 0; /* found, abort */
967 return 1; /* keep searching */
970 static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now)
972 if (difftime(now, context->ra_short_period_start) < 60.0)
974 context->ra_time = now + 5 + (rand16()/4400);
977 /* range 3/4 - 1 times MaxRtrAdvInterval */
978 unsigned int adv_interval = calc_interval(find_iface_param(iface_name));
979 context->ra_time = now + (3 * adv_interval)/4 + ((adv_interval * (unsigned int)rand16()) >> 18);
983 static struct ra_interface *find_iface_param(char *iface)
985 struct ra_interface *ra;
987 for (ra = daemon->ra_interfaces; ra; ra = ra->next)
988 if (wildcard_match(ra->name, iface))
994 static unsigned int calc_interval(struct ra_interface *ra)
998 if (ra && ra->interval != 0)
1000 interval = ra->interval;
1001 if (interval > 1800)
1003 else if (interval < 4)
1007 return (unsigned int)interval;
1010 static unsigned int calc_lifetime(struct ra_interface *ra)
1012 int lifetime, interval = (int)calc_interval(ra);
1014 if (!ra || ra->lifetime == -1) /* not specified */
1015 lifetime = 3 * interval;
1018 lifetime = ra->lifetime;
1019 if (lifetime < interval && lifetime != 0)
1020 lifetime = interval;
1021 else if (lifetime > 9000)
1025 return (unsigned int)lifetime;
1028 static unsigned int calc_prio(struct ra_interface *ra)