1 /* dnsmasq is Copyright (c) 2000-2016 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 recieve 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_unsolicted(now
, NULL
);
118 void ra_start_unsolicted(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 */
126 context
->ra_short_period_start
= context
->ra_time
= now
;
128 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
129 if (!(context
->flags
& CONTEXT_TEMPLATE
))
131 context
->ra_time
= now
+ (rand16()/13000); /* range 0 - 5 */
132 /* re-do frequently for a minute or so, in case the first gets lost. */
133 context
->ra_short_period_start
= now
;
137 void icmp6_packet(time_t now
)
139 char interface
[IF_NAMESIZE
+1];
142 struct cmsghdr
*cmptr
;
145 struct cmsghdr align
; /* this ensures alignment */
146 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
148 struct sockaddr_in6 from
;
149 unsigned char *packet
;
152 /* Note: use outpacket for input buffer */
153 msg
.msg_control
= control_u
.control6
;
154 msg
.msg_controllen
= sizeof(control_u
);
156 msg
.msg_name
= &from
;
157 msg
.msg_namelen
= sizeof(from
);
158 msg
.msg_iov
= &daemon
->outpacket
;
161 if ((sz
= recv_dhcp_packet(daemon
->icmp6fd
, &msg
)) == -1 || sz
< 8)
164 packet
= (unsigned char *)daemon
->outpacket
.iov_base
;
166 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
167 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&& cmptr
->cmsg_type
== daemon
->v6pktinfo
)
171 struct in6_pktinfo
*p
;
173 p
.c
= CMSG_DATA(cmptr
);
175 if_index
= p
.p
->ipi6_ifindex
;
178 if (!indextoname(daemon
->icmp6fd
, if_index
, interface
))
181 if (!iface_check(AF_LOCAL
, NULL
, interface
, NULL
))
184 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
185 if (tmp
->name
&& wildcard_match(tmp
->name
, interface
))
191 if (packet
[0] == ICMP6_ECHO_REPLY
)
192 lease_ping_reply(&from
.sin6_addr
, packet
, interface
);
193 else if (packet
[0] == ND_ROUTER_SOLICIT
)
196 struct dhcp_bridge
*bridge
, *alias
;
198 /* look for link-layer address option for logging */
199 if (sz
>= 16 && packet
[8] == ICMP6_OPT_SOURCE_MAC
&& (packet
[9] * 8) + 8 <= sz
)
201 print_mac(daemon
->namebuff
, &packet
[10], (packet
[9] * 8) - 2);
202 mac
= daemon
->namebuff
;
205 if (!option_bool(OPT_QUIET_RA
))
206 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-SOLICIT(%s) %s", interface
, mac
);
208 /* If the incoming interface is an alias of some other one (as
209 specified by the --bridge-interface option), send an RA using
210 the context of the aliased interface. */
211 for (bridge
= daemon
->bridges
; bridge
; bridge
= bridge
->next
)
213 int bridge_index
= if_nametoindex(bridge
->iface
);
216 for (alias
= bridge
->alias
; alias
; alias
= alias
->next
)
217 if (wildcard_matchn(alias
->iface
, interface
, IF_NAMESIZE
))
219 /* Send an RA on if_index with information from
221 send_ra_alias(now
, bridge_index
, bridge
->iface
, NULL
, if_index
);
229 /* If the incoming interface wasn't an alias, send an RA using
230 the context of the incoming interface. */
232 /* source address may not be valid in solicit request. */
233 send_ra(now
, if_index
, interface
, !IN6_IS_ADDR_UNSPECIFIED(&from
.sin6_addr
) ? &from
.sin6_addr
: NULL
);
237 static void send_ra_alias(time_t now
, int iface
, char *iface_name
, struct in6_addr
*dest
, int send_iface
)
239 struct ra_packet
*ra
;
240 struct ra_param parm
;
241 struct sockaddr_in6 addr
;
242 struct dhcp_context
*context
, *tmp
, **up
;
243 struct dhcp_netid iface_id
;
244 struct dhcp_opt
*opt_cfg
;
245 struct ra_interface
*ra_param
= find_iface_param(iface_name
);
246 int done_dns
= 0, old_prefix
= 0;
247 unsigned int min_pref_time
;
248 #ifdef HAVE_LINUX_NETWORK
255 parm
.found_context
= NULL
;
257 parm
.if_name
= iface_name
;
260 parm
.glob_pref_time
= parm
.link_pref_time
= parm
.ula_pref_time
= 0;
261 parm
.adv_interval
= calc_interval(ra_param
);
262 parm
.prio
= calc_prio(ra_param
);
265 ra
= expand(sizeof(struct ra_packet
));
267 ra
->type
= ND_ROUTER_ADVERT
;
269 ra
->hop_limit
= hop_limit
;
270 ra
->flags
= parm
.prio
;
271 ra
->lifetime
= htons(calc_lifetime(ra_param
));
272 ra
->reachable_time
= 0;
273 ra
->retrans_time
= 0;
275 /* set tag with name == interface */
276 iface_id
.net
= iface_name
;
277 iface_id
.next
= NULL
;
278 parm
.tags
= &iface_id
;
280 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
282 context
->flags
&= ~CONTEXT_RA_DONE
;
283 context
->netid
.next
= &context
->netid
;
286 if (!iface_enumerate(AF_INET6
, &parm
, add_prefixes
))
289 /* Find smallest preferred time within address classes,
290 to use as lifetime for options. This is a rather arbitrary choice. */
291 min_pref_time
= 0xffffffff;
292 if (parm
.glob_pref_time
!= 0 && parm
.glob_pref_time
< min_pref_time
)
293 min_pref_time
= parm
.glob_pref_time
;
295 if (parm
.ula_pref_time
!= 0 && parm
.ula_pref_time
< min_pref_time
)
296 min_pref_time
= parm
.ula_pref_time
;
298 if (parm
.link_pref_time
!= 0 && parm
.link_pref_time
< min_pref_time
)
299 min_pref_time
= parm
.link_pref_time
;
301 /* Look for constructed contexts associated with addresses which have gone,
302 and advertise them with preferred_time == 0 RFC 6204 4.3 L-13 */
303 for (up
= &daemon
->dhcp6
, context
= daemon
->dhcp6
; context
; context
= tmp
)
307 if (context
->if_index
== iface
&& (context
->flags
& CONTEXT_OLD
))
309 unsigned int old
= difftime(now
, context
->address_lost_time
);
311 if (old
> context
->saved_valid
)
313 /* We've advertised this enough, time to go */
315 /* If this context held the timeout, and there's another context in use
316 transfer the timeout there. */
317 if (context
->ra_time
!= 0 && parm
.found_context
&& parm
.found_context
->ra_time
== 0)
318 new_timeout(parm
.found_context
, iface_name
, now
);
325 struct prefix_opt
*opt
;
326 struct in6_addr local
= context
->start6
;
331 /* zero net part of address */
332 setaddr6part(&local
, addr6part(&local
) & ~((context
->prefix
== 64) ? (u64
)-1LL : (1LLU << (128 - context
->prefix
)) - 1LLU));
335 if (context
->flags
& CONTEXT_RA
)
338 if (context
->flags
& CONTEXT_DHCP
)
341 if (!(context
->flags
& CONTEXT_RA_STATELESS
))
347 /* don't do RA for non-ra-only unless --enable-ra is set */
348 if (option_bool(OPT_RA
))
355 if ((opt
= expand(sizeof(struct prefix_opt
))))
357 opt
->type
= ICMP6_OPT_PREFIX
;
359 opt
->prefix_len
= context
->prefix
;
360 /* autonomous only if we're not doing dhcp, set
361 "on-link" unless "off-link" was specified */
362 opt
->flags
= (do_slaac
? 0x40 : 0) |
363 ((context
->flags
& CONTEXT_RA_OFF_LINK
) ? 0 : 0x80);
364 opt
->valid_lifetime
= htonl(context
->saved_valid
- old
);
365 opt
->preferred_lifetime
= htonl(0);
369 inet_ntop(AF_INET6
, &local
, daemon
->addrbuff
, ADDRSTRLEN
);
370 if (!option_bool(OPT_QUIET_RA
))
371 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s old prefix", iface_name
, daemon
->addrbuff
);
381 /* If we're advertising only old prefixes, set router lifetime to zero. */
382 if (old_prefix
&& !parm
.found_context
)
383 ra
->lifetime
= htons(0);
385 /* No prefixes to advertise. */
386 if (!old_prefix
&& !parm
.found_context
)
389 /* If we're sending router address instead of prefix in at least on prefix,
390 include the advertisement interval option. */
393 put_opt6_char(ICMP6_OPT_ADV_INTERVAL
);
396 /* interval value is in milliseconds */
397 put_opt6_long(1000 * calc_interval(find_iface_param(iface_name
)));
400 #ifdef HAVE_LINUX_NETWORK
401 /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
402 available from SIOCGIFMTU */
403 sprintf(daemon
->namebuff
, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name
);
404 if ((f
= fopen(daemon
->namebuff
, "r")))
406 if (fgets(daemon
->namebuff
, MAXDNAME
, f
))
408 put_opt6_char(ICMP6_OPT_MTU
);
411 put_opt6_long(atoi(daemon
->namebuff
));
417 iface_enumerate(AF_LOCAL
, &send_iface
, add_lla
);
419 /* RDNSS, RFC 6106, use relevant DHCP6 options */
420 (void)option_filter(parm
.tags
, NULL
, daemon
->dhcp_opts6
);
422 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
426 /* netids match and not encapsulated? */
427 if (!(opt_cfg
->flags
& DHOPT_TAGOK
))
430 if (opt_cfg
->opt
== OPTION6_DNS_SERVER
)
437 if (opt_cfg
->len
== 0)
440 /* reduce len for any addresses we can't substitute */
441 for (a
= (struct in6_addr
*)opt_cfg
->val
, len
= opt_cfg
->len
, i
= 0;
442 i
< opt_cfg
->len
; i
+= IN6ADDRSZ
, a
++)
443 if ((IN6_IS_ADDR_UNSPECIFIED(a
) && parm
.glob_pref_time
== 0) ||
444 (IN6_IS_ADDR_ULA_ZERO(a
) && parm
.ula_pref_time
== 0) ||
445 (IN6_IS_ADDR_LINK_LOCAL_ZERO(a
) && parm
.link_pref_time
== 0))
450 put_opt6_char(ICMP6_OPT_RDNSS
);
451 put_opt6_char((len
/8) + 1);
453 put_opt6_long(min_pref_time
);
455 for (a
= (struct in6_addr
*)opt_cfg
->val
, i
= 0; i
< opt_cfg
->len
; i
+= IN6ADDRSZ
, a
++)
456 if (IN6_IS_ADDR_UNSPECIFIED(a
))
458 if (parm
.glob_pref_time
!= 0)
459 put_opt6(&parm
.link_global
, IN6ADDRSZ
);
461 else if (IN6_IS_ADDR_ULA_ZERO(a
))
463 if (parm
.ula_pref_time
!= 0)
464 put_opt6(&parm
.ula
, IN6ADDRSZ
);
466 else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a
))
468 if (parm
.link_pref_time
!= 0)
469 put_opt6(&parm
.link_local
, IN6ADDRSZ
);
472 put_opt6(a
, IN6ADDRSZ
);
476 if (opt_cfg
->opt
== OPTION6_DOMAIN_SEARCH
&& opt_cfg
->len
!= 0)
478 int len
= ((opt_cfg
->len
+7)/8);
480 put_opt6_char(ICMP6_OPT_DNSSL
);
481 put_opt6_char(len
+ 1);
483 put_opt6_long(min_pref_time
);
484 put_opt6(opt_cfg
->val
, opt_cfg
->len
);
487 for (i
= opt_cfg
->len
; i
< len
* 8; i
++)
492 if (daemon
->port
== NAMESERVER_PORT
&& !done_dns
&& parm
.link_pref_time
!= 0)
494 /* default == us, as long as we are supplying DNS service. */
495 put_opt6_char(ICMP6_OPT_RDNSS
);
498 put_opt6_long(min_pref_time
);
499 put_opt6(&parm
.link_local
, IN6ADDRSZ
);
502 /* set managed bits unless we're providing only RA on this link */
504 ra
->flags
|= 0x80; /* M flag, managed, */
506 ra
->flags
|= 0x40; /* O flag, other */
508 /* decide where we're sending */
509 memset(&addr
, 0, sizeof(addr
));
510 #ifdef HAVE_SOCKADDR_SA_LEN
511 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
513 addr
.sin6_family
= AF_INET6
;
514 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
517 addr
.sin6_addr
= *dest
;
518 if (IN6_IS_ADDR_LINKLOCAL(dest
) ||
519 IN6_IS_ADDR_MC_LINKLOCAL(dest
))
520 addr
.sin6_scope_id
= iface
;
524 inet_pton(AF_INET6
, ALL_NODES
, &addr
.sin6_addr
);
525 setsockopt(daemon
->icmp6fd
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
, &send_iface
, sizeof(send_iface
));
528 while (retry_send(sendto(daemon
->icmp6fd
, daemon
->outpacket
.iov_base
,
529 save_counter(0), 0, (struct sockaddr
*)&addr
,
534 static void send_ra(time_t now
, int iface
, char *iface_name
, struct in6_addr
*dest
)
536 /* Send an RA on the same interface that the RA content is based
538 send_ra_alias(now
, iface
, iface_name
, dest
, iface
);
541 static int add_prefixes(struct in6_addr
*local
, int prefix
,
542 int scope
, int if_index
, int flags
,
543 unsigned int preferred
, unsigned int valid
, void *vparam
)
545 struct ra_param
*param
= vparam
;
547 (void)scope
; /* warning */
549 if (if_index
== param
->ind
)
551 if (IN6_IS_ADDR_LINKLOCAL(local
))
553 /* Can there be more than one LL address?
554 Select the one with the longest preferred time
556 if (preferred
> param
->link_pref_time
)
558 param
->link_pref_time
= preferred
;
559 param
->link_local
= *local
;
562 else if (!IN6_IS_ADDR_LOOPBACK(local
) &&
563 !IN6_IS_ADDR_MULTICAST(local
))
571 unsigned int time
= 0xffffffff;
572 struct dhcp_context
*context
;
574 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
575 if (!(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
576 prefix
<= context
->prefix
&&
577 is_same_net6(local
, &context
->start6
, context
->prefix
) &&
578 is_same_net6(local
, &context
->end6
, context
->prefix
))
580 context
->saved_valid
= valid
;
582 if (context
->flags
& CONTEXT_RA
)
585 if (context
->flags
& CONTEXT_DHCP
)
588 if (!(context
->flags
& CONTEXT_RA_STATELESS
))
594 /* don't do RA for non-ra-only unless --enable-ra is set */
595 if (!option_bool(OPT_RA
))
601 /* Configured to advertise router address, not prefix. See RFC 3775 7.2
602 In this case we do all addresses associated with a context,
603 hence the real_prefix setting here. */
604 if (context
->flags
& CONTEXT_RA_ROUTER
)
607 param
->adv_router
= 1;
608 real_prefix
= context
->prefix
;
611 /* find floor time, don't reduce below 3 * RA interval. */
612 if (time
> context
->lease_time
)
614 time
= context
->lease_time
;
615 if (time
< ((unsigned int)(3 * param
->adv_interval
)))
616 time
= 3 * param
->adv_interval
;
619 if (context
->flags
& CONTEXT_DEPRECATE
)
622 if (context
->flags
& CONTEXT_CONSTRUCTED
)
626 /* collect dhcp-range tags */
627 if (context
->netid
.next
== &context
->netid
&& context
->netid
.net
)
629 context
->netid
.next
= param
->tags
;
630 param
->tags
= &context
->netid
;
633 /* subsequent prefixes on the same interface
634 and subsequent instances of this prefix don't need timers.
635 Be careful not to find the same prefix twice with different
636 addresses unless we're advertising the actual addresses. */
637 if (!(context
->flags
& CONTEXT_RA_DONE
))
640 context
->ra_time
= 0;
641 context
->flags
|= CONTEXT_RA_DONE
;
642 real_prefix
= context
->prefix
;
643 off_link
= (context
->flags
& CONTEXT_RA_OFF_LINK
);
647 /* found_context is the _last_ one we found, so if there's
648 more than one, it's not the first. */
649 param
->found_context
= context
;
652 /* configured time is ceiling */
653 if (!constructed
|| valid
> time
)
656 if (flags
& IFACE_DEPRECATED
)
662 /* configured time is ceiling */
663 if (!constructed
|| preferred
> time
)
666 if (IN6_IS_ADDR_ULA(local
))
668 if (preferred
> param
->ula_pref_time
)
670 param
->ula_pref_time
= preferred
;
676 if (preferred
> param
->glob_pref_time
)
678 param
->glob_pref_time
= preferred
;
679 param
->link_global
= *local
;
683 if (real_prefix
!= 0)
685 struct prefix_opt
*opt
;
687 if ((opt
= expand(sizeof(struct prefix_opt
))))
689 /* zero net part of address */
691 setaddr6part(local
, addr6part(local
) & ~((real_prefix
== 64) ? (u64
)-1LL : (1LLU << (128 - real_prefix
)) - 1LLU));
693 opt
->type
= ICMP6_OPT_PREFIX
;
695 opt
->prefix_len
= real_prefix
;
696 /* autonomous only if we're not doing dhcp, set
697 "on-link" unless "off-link" was specified */
698 opt
->flags
= (off_link
? 0 : 0x80);
703 opt
->valid_lifetime
= htonl(valid
);
704 opt
->preferred_lifetime
= htonl(preferred
);
706 opt
->prefix
= *local
;
708 inet_ntop(AF_INET6
, local
, daemon
->addrbuff
, ADDRSTRLEN
);
709 if (!option_bool(OPT_QUIET_RA
))
710 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s", param
->if_name
, daemon
->addrbuff
);
718 static int add_lla(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
)
722 if (index
== *((int *)parm
))
724 /* size is in units of 8 octets and includes type and length (2 bytes)
726 int len
= (maclen
+ 9) >> 3;
727 unsigned char *p
= expand(len
<< 3);
728 memset(p
, 0, len
<< 3);
729 *p
++ = ICMP6_OPT_SOURCE_MAC
;
731 memcpy(p
, mac
, maclen
);
739 time_t periodic_ra(time_t now
)
741 struct search_param param
;
742 struct dhcp_context
*context
;
744 struct alias_param aparam
;
751 /* find overdue events, and time of first future event */
752 for (next_event
= 0, context
= daemon
->dhcp6
; context
; context
= context
->next
)
753 if (context
->ra_time
!= 0)
755 if (difftime(context
->ra_time
, now
) <= 0.0)
758 if (next_event
== 0 || difftime(next_event
, context
->ra_time
) > 0.0)
759 next_event
= context
->ra_time
;
766 if ((context
->flags
& CONTEXT_OLD
) &&
767 context
->if_index
!= 0 &&
768 indextoname(daemon
->icmp6fd
, context
->if_index
, param
.name
))
770 /* A context for an old address. We'll not find the interface by
771 looking for addresses, but we know it anyway, since the context is
773 param
.iface
= context
->if_index
;
774 new_timeout(context
, param
.name
, now
);
776 else if (iface_enumerate(AF_INET6
, ¶m
, iface_search
))
777 /* There's a context overdue, but we can't find an interface
778 associated with it, because it's for a subnet we dont
779 have an interface on. Probably we're doing DHCP on
780 a remote subnet via a relay. Zero the timer, since we won't
781 ever be able to send ra's and satistfy it. */
782 context
->ra_time
= 0;
784 if (param
.iface
!= 0 &&
785 iface_check(AF_LOCAL
, NULL
, param
.name
, NULL
))
788 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
789 if (tmp
->name
&& wildcard_match(tmp
->name
, param
.name
))
793 send_ra(now
, param
.iface
, param
.name
, NULL
);
795 /* Also send on all interfaces that are aliases of this
797 for (aparam
.bridge
= daemon
->bridges
;
799 aparam
.bridge
= aparam
.bridge
->next
)
800 if ((int)if_nametoindex(aparam
.bridge
->iface
) == param
.iface
)
802 /* Count the number of alias interfaces for this
803 'bridge', by calling iface_enumerate with
804 send_ra_to_aliases and NULL alias_ifs. */
805 aparam
.iface
= param
.iface
;
806 aparam
.alias_ifs
= NULL
;
807 aparam
.num_alias_ifs
= 0;
808 iface_enumerate(AF_LOCAL
, &aparam
, send_ra_to_aliases
);
809 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s => %d alias(es)",
810 param
.name
, daemon
->addrbuff
, aparam
.num_alias_ifs
);
812 /* Allocate memory to store the alias interface
814 aparam
.alias_ifs
= (int *)whine_malloc(aparam
.num_alias_ifs
*
816 if (aparam
.alias_ifs
)
818 /* Use iface_enumerate again to get the alias
819 interface indices, then send on each of
821 aparam
.max_alias_ifs
= aparam
.num_alias_ifs
;
822 aparam
.num_alias_ifs
= 0;
823 iface_enumerate(AF_LOCAL
, &aparam
, send_ra_to_aliases
);
824 for (; aparam
.num_alias_ifs
; aparam
.num_alias_ifs
--)
826 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s => i/f %d",
827 param
.name
, daemon
->addrbuff
,
828 aparam
.alias_ifs
[aparam
.num_alias_ifs
- 1]);
833 aparam
.alias_ifs
[aparam
.num_alias_ifs
- 1]);
835 free(aparam
.alias_ifs
);
838 /* The source interface can only appear in at most
839 one --bridge-interface. */
848 static int send_ra_to_aliases(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
)
850 struct alias_param
*aparam
= (struct alias_param
*)parm
;
851 char ifrn_name
[IFNAMSIZ
];
852 struct dhcp_bridge
*alias
;
858 if (if_indextoname(index
, ifrn_name
))
859 for (alias
= aparam
->bridge
->alias
; alias
; alias
= alias
->next
)
860 if (wildcard_matchn(alias
->iface
, ifrn_name
, IFNAMSIZ
))
862 if (aparam
->alias_ifs
&& (aparam
->num_alias_ifs
< aparam
->max_alias_ifs
))
863 aparam
->alias_ifs
[aparam
->num_alias_ifs
] = index
;
864 aparam
->num_alias_ifs
++;
870 static int iface_search(struct in6_addr
*local
, int prefix
,
871 int scope
, int if_index
, int flags
,
872 int preferred
, int valid
, void *vparam
)
874 struct search_param
*param
= vparam
;
875 struct dhcp_context
*context
;
881 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
882 if (!(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
883 prefix
<= context
->prefix
&&
884 is_same_net6(local
, &context
->start6
, context
->prefix
) &&
885 is_same_net6(local
, &context
->end6
, context
->prefix
) &&
886 context
->ra_time
!= 0 &&
887 difftime(context
->ra_time
, param
->now
) <= 0.0)
889 /* found an interface that's overdue for RA determine new
890 timeout value and arrange for RA to be sent unless interface is
893 if (!(flags
& IFACE_TENTATIVE
))
894 param
->iface
= if_index
;
896 /* should never fail */
897 if (!indextoname(daemon
->icmp6fd
, if_index
, param
->name
))
903 new_timeout(context
, param
->name
, param
->now
);
905 /* zero timers for other contexts on the same subnet, so they don't timeout
907 for (context
= context
->next
; context
; context
= context
->next
)
908 if (prefix
<= context
->prefix
&&
909 is_same_net6(local
, &context
->start6
, context
->prefix
) &&
910 is_same_net6(local
, &context
->end6
, context
->prefix
))
911 context
->ra_time
= 0;
913 return 0; /* found, abort */
916 return 1; /* keep searching */
919 static void new_timeout(struct dhcp_context
*context
, char *iface_name
, time_t now
)
921 if (difftime(now
, context
->ra_short_period_start
) < 60.0)
923 context
->ra_time
= now
+ 5 + (rand16()/4400);
926 /* range 3/4 - 1 times MaxRtrAdvInterval */
927 unsigned int adv_interval
= calc_interval(find_iface_param(iface_name
));
928 context
->ra_time
= now
+ (3 * adv_interval
)/4 + ((adv_interval
* (unsigned int)rand16()) >> 18);
932 static struct ra_interface
*find_iface_param(char *iface
)
934 struct ra_interface
*ra
;
936 for (ra
= daemon
->ra_interfaces
; ra
; ra
= ra
->next
)
937 if (wildcard_match(ra
->name
, iface
))
943 static unsigned int calc_interval(struct ra_interface
*ra
)
947 if (ra
&& ra
->interval
!= 0)
949 interval
= ra
->interval
;
952 else if (interval
< 4)
956 return (unsigned int)interval
;
959 static unsigned int calc_lifetime(struct ra_interface
*ra
)
961 int lifetime
, interval
= (int)calc_interval(ra
);
963 if (!ra
|| ra
->lifetime
== -1) /* not specified */
964 lifetime
= 3 * interval
;
967 lifetime
= ra
->lifetime
;
968 if (lifetime
< interval
&& lifetime
!= 0)
970 else if (lifetime
> 9000)
974 return (unsigned int)lifetime
;
977 static unsigned int calc_prio(struct ra_interface
*ra
)