Imported Upstream version 2.88
[platform/upstream/dnsmasq.git] / src / radv.c
1 /* dnsmasq is Copyright (c) 2000-2022 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
29 struct ra_param {
30   time_t now;
31   int ind, managed, other, 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   struct dhcp_context *found_context;
37 };
38
39 struct search_param {
40   time_t now; int iface;
41   char name[IF_NAMESIZE+1];
42 };
43
44 struct alias_param {
45   int iface;
46   struct dhcp_bridge *bridge;
47   int num_alias_ifs;
48   int max_alias_ifs;
49   int *alias_ifs;
50 };
51
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,
54                     int send_iface);
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);
68
69 static int hop_limit;
70
71 void ra_init(time_t now)
72 {
73   struct icmp6_filter filter;
74   int fd;
75 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
76   int class = IPTOS_CLASS_CS6;
77 #endif
78   int val = 255; /* radvd uses this value */
79   socklen_t len = sizeof(int);
80   struct dhcp_context *context;
81   
82   /* ensure this is around even if we're not doing DHCPv6 */
83   expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
84  
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))
88       break;
89   
90   /* Need ICMP6 socket for transmission for DHCPv6 even when not doing RA. */
91
92   ICMP6_FILTER_SETBLOCKALL(&filter);
93   if (daemon->doing_ra)
94     {
95       ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
96       if (context)
97         ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter);
98     }
99   
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 ||
104 #endif
105       !fix_fd(fd) ||
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);
111   
112    daemon->icmp6fd = fd;
113    
114    if (daemon->doing_ra)
115      ra_start_unsolicited(now, NULL);
116 }
117
118 void ra_start_unsolicited(time_t now, struct dhcp_context *context)
119 {   
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 */
124   
125   if (context)
126     {
127       context->ra_short_period_start = now;
128       /* start after 1 second to get logging right at startup. */
129       context->ra_time = now + 1;
130     }
131   else
132     for (context = daemon->dhcp6; context; context = context->next)
133       if (!(context->flags & CONTEXT_TEMPLATE))
134         {
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;
138         }
139 }
140
141 void icmp6_packet(time_t now)
142 {
143   char interface[IF_NAMESIZE+1];
144   ssize_t sz; 
145   int if_index = 0;
146   struct cmsghdr *cmptr;
147   struct msghdr msg;
148   union {
149     struct cmsghdr align; /* this ensures alignment */
150     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
151   } control_u;
152   struct sockaddr_in6 from;
153   unsigned char *packet;
154   struct iname *tmp;
155
156   /* Note: use outpacket for input buffer */
157   msg.msg_control = control_u.control6;
158   msg.msg_controllen = sizeof(control_u);
159   msg.msg_flags = 0;
160   msg.msg_name = &from;
161   msg.msg_namelen = sizeof(from);
162   msg.msg_iov = &daemon->outpacket;
163   msg.msg_iovlen = 1;
164   
165   if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8)
166     return;
167    
168   packet = (unsigned char *)daemon->outpacket.iov_base;
169
170   for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
171     if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
172       {
173         union {
174           unsigned char *c;
175           struct in6_pktinfo *p;
176         } p;
177         p.c = CMSG_DATA(cmptr);
178         
179         if_index = p.p->ipi6_ifindex;
180       }
181   
182   if (!indextoname(daemon->icmp6fd, if_index, interface))
183     return;
184     
185   if (!iface_check(AF_LOCAL, NULL, interface, NULL))
186     return;
187   
188   for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
189     if (tmp->name && wildcard_match(tmp->name, interface))
190       return;
191  
192   if (packet[1] != 0)
193     return;
194
195   if (packet[0] == ICMP6_ECHO_REPLY)
196     lease_ping_reply(&from.sin6_addr, packet, interface); 
197   else if (packet[0] == ND_ROUTER_SOLICIT)
198     {
199       char *mac = "";
200       struct dhcp_bridge *bridge, *alias;
201       ssize_t rem;
202       unsigned char *p;
203       int opt_sz;
204       
205 #ifdef HAVE_DUMPFILE
206       dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
207 #endif           
208       
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)
211         {
212           opt_sz = p[1] * 8;
213           
214           if (opt_sz == 0 || opt_sz > rem)
215             return; /* Bad packet */
216           
217           if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME))
218             {
219               print_mac(daemon->namebuff, &p[2], opt_sz - 2);
220               mac = daemon->namebuff;
221             }
222         }
223       
224       if (!option_bool(OPT_QUIET_RA))
225         my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
226
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)
231         {
232           int bridge_index = if_nametoindex(bridge->iface);
233           if (bridge_index)
234             {
235               for (alias = bridge->alias; alias; alias = alias->next)
236                 if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
237                   {
238                     /* Send an RA on if_index with information from
239                        bridge_index. */
240                     send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
241                     break;
242                   }
243               if (alias)
244                 break;
245             }
246         }
247
248       /* If the incoming interface wasn't an alias, send an RA using
249          the context of the incoming interface. */
250       if (!bridge)
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);
253     }
254 }
255
256 static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
257 {
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
268   FILE *f;
269 #endif
270   
271   parm.ind = iface;
272   parm.managed = 0;
273   parm.other = 0;
274   parm.found_context = NULL;
275   parm.adv_router = 0;
276   parm.if_name = iface_name;
277   parm.first = 1;
278   parm.now = now;
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);
282   
283   reset_counter();
284   
285   if (!(ra = expand(sizeof(struct ra_packet))))
286     return;
287   
288   ra->type = ND_ROUTER_ADVERT;
289   ra->code = 0;
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;
295
296   /* set tag with name == interface */
297   iface_id.net = iface_name;
298   iface_id.next = NULL;
299   parm.tags = &iface_id; 
300   
301   for (context = daemon->dhcp6; context; context = context->next)
302     {
303       context->flags &= ~CONTEXT_RA_DONE;
304       context->netid.next = &context->netid;
305     }
306
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)
311     return;
312
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;
318   
319   if (parm.ula_pref_time != 0 && parm.ula_pref_time < min_pref_time)
320     min_pref_time = parm.ula_pref_time;
321
322   if (parm.link_pref_time != 0 && parm.link_pref_time < min_pref_time)
323     min_pref_time = parm.link_pref_time;
324
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)
328     {
329       tmp = context->next;
330
331       if (context->if_index == iface && (context->flags & CONTEXT_OLD))
332         {
333           unsigned int old = difftime(now, context->address_lost_time);
334           
335           if (old > context->saved_valid)
336             { 
337               /* We've advertised this enough, time to go */
338              
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);
343               
344               *up = context->next;
345               free(context);
346             }
347           else
348             {
349               struct prefix_opt *opt;
350               struct in6_addr local = context->start6;
351               int do_slaac = 0;
352
353               old_prefix = 1;
354
355               /* zero net part of address */
356               setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
357              
358               
359               if (context->flags & CONTEXT_RA)
360                 {
361                   do_slaac = 1;
362                   if (context->flags & CONTEXT_DHCP)
363                     {
364                       parm.other = 1; 
365                       if (!(context->flags & CONTEXT_RA_STATELESS))
366                         parm.managed = 1;
367                     }
368                 }
369               else
370                 {
371                   /* don't do RA for non-ra-only unless --enable-ra is set */
372                   if (option_bool(OPT_RA))
373                     {
374                       parm.managed = 1;
375                       parm.other = 1;
376                     }
377                 }
378
379               if ((opt = expand(sizeof(struct prefix_opt))))
380                 {
381                   opt->type = ICMP6_OPT_PREFIX;
382                   opt->len = 4;
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);
390                   opt->reserved = 0; 
391                   opt->prefix = local;
392                   
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);                    
396                 }
397            
398               up = &context->next;
399             }
400         }
401       else
402         up = &context->next;
403     }
404     
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);
408
409   /* No prefixes to advertise. */
410   if (!old_prefix && !parm.found_context)
411     return; 
412   
413   /* If we're sending router address instead of prefix in at least on prefix,
414      include the advertisement interval option. */
415   if (parm.adv_router)
416     {
417       put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
418       put_opt6_char(1);
419       put_opt6_short(0);
420       /* interval value is in milliseconds */
421       put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
422     }
423
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. */
426   if (ra_param)
427     mtu = ra_param->mtu;
428 #ifdef HAVE_LINUX_NETWORK
429   /* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
430      available from SIOCGIFMTU */
431   if (mtu == 0)
432     {
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")))
436         {
437           if (fgets(daemon->namebuff, MAXDNAME, f))
438             mtu = atoi(daemon->namebuff);
439           fclose(f);
440         }
441     }
442 #endif
443   if (mtu > 0)
444     {
445       put_opt6_char(ICMP6_OPT_MTU);
446       put_opt6_char(1);
447       put_opt6_short(0);
448       put_opt6_long(mtu);
449     }
450      
451   iface_enumerate(AF_LOCAL, &send_iface, add_lla);
452  
453   /* RDNSS, RFC 6106, use relevant DHCP6 options */
454   (void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
455   
456   for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
457     {
458       int i;
459       
460       /* netids match and not encapsulated? */
461       if (!(opt_cfg->flags & DHOPT_TAGOK))
462         continue;
463       
464       if (opt_cfg->opt == OPTION6_DNS_SERVER)
465         {
466           struct in6_addr *a;
467           int len;
468
469           done_dns = 1;
470
471           if (opt_cfg->len == 0)
472             continue;
473           
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))
480               len -= IN6ADDRSZ;
481
482           if (len != 0)
483             {
484               put_opt6_char(ICMP6_OPT_RDNSS);
485               put_opt6_char((len/8) + 1);
486               put_opt6_short(0);
487               put_opt6_long(min_pref_time);
488          
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))
491                   {
492                     if (parm.glob_pref_time != 0)
493                       put_opt6(&parm.link_global, IN6ADDRSZ);
494                   }
495                 else if (IN6_IS_ADDR_ULA_ZERO(a))
496                   {
497                     if (parm.ula_pref_time != 0)
498                     put_opt6(&parm.ula, IN6ADDRSZ);
499                   }
500                 else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
501                   {
502                     if (parm.link_pref_time != 0)
503                       put_opt6(&parm.link_local, IN6ADDRSZ);
504                   }
505                 else
506                   put_opt6(a, IN6ADDRSZ);
507             }
508         }
509       
510       if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0)
511         {
512           int len = ((opt_cfg->len+7)/8);
513           
514           put_opt6_char(ICMP6_OPT_DNSSL);
515           put_opt6_char(len + 1);
516           put_opt6_short(0);
517           put_opt6_long(min_pref_time); 
518           put_opt6(opt_cfg->val, opt_cfg->len);
519           
520           /* pad */
521           for (i = opt_cfg->len; i < len * 8; i++)
522             put_opt6_char(0);
523         }
524     }
525         
526   if (daemon->port == NAMESERVER_PORT && !done_dns && parm.link_pref_time != 0)
527     {
528       /* default == us, as long as we are supplying DNS service. */
529       put_opt6_char(ICMP6_OPT_RDNSS);
530       put_opt6_char(3);
531       put_opt6_short(0);
532       put_opt6_long(min_pref_time); 
533       put_opt6(&parm.link_local, IN6ADDRSZ);
534     }
535
536   /* set managed bits unless we're providing only RA on this link */
537   if (parm.managed)
538     ra->flags |= 0x80; /* M flag, managed, */
539    if (parm.other)
540     ra->flags |= 0x40; /* O flag, other */ 
541                         
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);
546 #endif
547   addr.sin6_family = AF_INET6;
548   addr.sin6_port = htons(IPPROTO_ICMPV6);
549   if (dest)
550     {
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;
555     }
556   else
557     {
558       inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr); 
559       setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
560     }
561   
562 #ifdef HAVE_DUMPFILE
563   {
564     struct sockaddr_in6 src;
565     src.sin6_family = AF_INET6;
566     src.sin6_addr = parm.link_local;
567     
568     dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
569   }
570 #endif
571
572   while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, 
573                            save_counter(-1), 0, (struct sockaddr *)&addr, 
574                            sizeof(addr))));
575   
576 }
577
578 static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
579 {
580   /* Send an RA on the same interface that the RA content is based
581      on. */
582   send_ra_alias(now, iface, iface_name, dest, iface);
583 }
584
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)
588 {
589   struct ra_param *param = vparam;
590
591   (void)scope; /* warning */
592   
593   if (if_index == param->ind)
594     {
595       if (IN6_IS_ADDR_LINKLOCAL(local))
596         {
597           /* Can there be more than one LL address?
598              Select the one with the longest preferred time 
599              if there is. */
600           if (preferred > param->link_pref_time)
601             {
602               param->link_pref_time = preferred;
603               param->link_local = *local;
604             }
605         }
606       else if (!IN6_IS_ADDR_LOOPBACK(local) &&
607                !IN6_IS_ADDR_MULTICAST(local))
608         {
609           int real_prefix = 0;
610           int do_slaac = 0;
611           int deprecate  = 0;
612           int constructed = 0;
613           int adv_router = 0;
614           int off_link = 0;
615           unsigned int time = 0xffffffff;
616           struct dhcp_context *context;
617           
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))
623               {
624                 context->saved_valid = valid;
625
626                 if (context->flags & CONTEXT_RA) 
627                   {
628                     do_slaac = 1;
629                     if (context->flags & CONTEXT_DHCP)
630                       {
631                         param->other = 1; 
632                         if (!(context->flags & CONTEXT_RA_STATELESS))
633                           param->managed = 1;
634                       }
635                   }
636                 else
637                   {
638                     /* don't do RA for non-ra-only unless --enable-ra is set */
639                     if (!option_bool(OPT_RA))
640                       continue;
641                     param->managed = 1;
642                     param->other = 1;
643                   }
644
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)
649                   {
650                     adv_router = 1;
651                     param->adv_router = 1;
652                     real_prefix = context->prefix;
653                   }
654
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)
660                   {
661                     time = context->lease_time;
662                     if (time < ((unsigned int)(3 * param->adv_interval)))
663                       time = 3 * param->adv_interval;
664                   }
665
666                 if (context->flags & CONTEXT_DEPRECATE)
667                   deprecate = 1;
668                 
669                 if (context->flags & CONTEXT_CONSTRUCTED)
670                   constructed = 1;
671
672
673                 /* collect dhcp-range tags */
674                 if (context->netid.next == &context->netid && context->netid.net)
675                   {
676                     context->netid.next = param->tags;
677                     param->tags = &context->netid;
678                   }
679                   
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))
685                   {
686                     if (!param->first)
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);
691                   }
692
693                 param->first = 0;
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;
697               }
698
699           /* configured time is ceiling */
700           if (!constructed || valid > time)
701             valid = time;
702           
703           if (flags & IFACE_DEPRECATED)
704             preferred = 0;
705           
706           if (deprecate)
707             time = 0;
708           
709           /* configured time is ceiling */
710           if (!constructed || preferred > time)
711             preferred = time;
712           
713           if (IN6_IS_ADDR_ULA(local))
714             {
715               if (preferred > param->ula_pref_time)
716                 {
717                   param->ula_pref_time = preferred;
718                   param->ula = *local;
719                 }
720             }
721           else 
722             {
723               if (preferred > param->glob_pref_time)
724                 {
725                   param->glob_pref_time = preferred;
726                   param->link_global = *local;
727                 }
728             }
729           
730           if (real_prefix != 0)
731             {
732               struct prefix_opt *opt;
733                       
734               if ((opt = expand(sizeof(struct prefix_opt))))
735                 {
736                   /* zero net part of address */
737                   if (!adv_router)
738                     setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
739                   
740                   opt->type = ICMP6_OPT_PREFIX;
741                   opt->len = 4;
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);
746                   if (do_slaac)
747                     opt->flags |= 0x40;
748                   if (adv_router)
749                     opt->flags |= 0x20;
750                   opt->valid_lifetime = htonl(valid);
751                   opt->preferred_lifetime = htonl(preferred);
752                   opt->reserved = 0; 
753                   opt->prefix = *local;
754                   
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);                   
758                 }
759             }
760         }
761     }          
762   return 1;
763 }
764
765 static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm)
766 {
767   (void)type;
768
769   if (index == *((int *)parm))
770     {
771       /* size is in units of 8 octets and includes type and length (2 bytes)
772          add 7 to round up */
773       int len = (maclen + 9) >> 3;
774       unsigned char *p = expand(len << 3);
775       if (!p)
776         return 1;
777       memset(p, 0, len << 3);
778       *p++ = ICMP6_OPT_SOURCE_MAC;
779       *p++ = len;
780       memcpy(p, mac, maclen);
781
782       return 0;
783     }
784
785   return 1;
786 }
787
788 time_t periodic_ra(time_t now)
789 {
790   struct search_param param;
791   struct dhcp_context *context;
792   time_t next_event;
793   struct alias_param aparam;
794     
795   param.now = now;
796   param.iface = 0;
797
798   while (1)
799     {
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)
803           {
804             if (difftime(context->ra_time, now) <= 0.0)
805               break; /* overdue */
806             
807             if (next_event == 0 || difftime(next_event, context->ra_time) > 0.0)
808               next_event = context->ra_time;
809           }
810       
811       /* none overdue */
812       if (!context)
813         break;
814       
815       if ((context->flags & CONTEXT_OLD) && 
816           context->if_index != 0 && 
817           indextoname(daemon->icmp6fd, context->if_index, param.name))
818         {
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
821              constructed */
822           param.iface = context->if_index;
823           new_timeout(context, param.name, now);
824         }
825       else if (iface_enumerate(AF_INET6, &param, 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;
832       
833       if (param.iface != 0 &&
834           iface_check(AF_LOCAL, NULL, param.name, NULL))
835         {
836           struct iname *tmp;
837           for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
838             if (tmp->name && wildcard_match(tmp->name, param.name))
839               break;
840           if (!tmp)
841             {
842               send_ra(now, param.iface, param.name, NULL); 
843
844               /* Also send on all interfaces that are aliases of this
845                  one. */
846               for (aparam.bridge = daemon->bridges;
847                    aparam.bridge;
848                    aparam.bridge = aparam.bridge->next)
849                 if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
850                   {
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);
860
861                     /* Allocate memory to store the alias interface
862                        indices. */
863                     aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
864                                                            sizeof(int));
865                     if (aparam.alias_ifs)
866                       {
867                         /* Use iface_enumerate again to get the alias
868                            interface indices, then send on each of
869                            those. */
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--)
874                           {
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]);
878                             send_ra_alias(now,
879                                           param.iface,
880                                           param.name,
881                                           NULL,
882                                           aparam.alias_ifs[aparam.num_alias_ifs - 1]);
883                           }
884                         free(aparam.alias_ifs);
885                       }
886
887                     /* The source interface can only appear in at most
888                        one --bridge-interface. */
889                     break;
890                   }
891             }
892         }
893     }      
894   return next_event;
895 }
896
897 static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
898 {
899   struct alias_param *aparam = (struct alias_param *)parm;
900   char ifrn_name[IFNAMSIZ];
901   struct dhcp_bridge *alias;
902
903   (void)type;
904   (void)mac;
905   (void)maclen;
906
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))
910         {
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++;
914         }
915
916   return 1;
917 }
918
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)
922 {
923   struct search_param *param = vparam;
924   struct dhcp_context *context;
925   struct iname *tmp;
926   
927   (void)scope;
928   (void)preferred;
929   (void)valid;
930
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))
934     return 1;
935
936   for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
937     if (tmp->name && wildcard_match(tmp->name, param->name))
938       return 1;
939
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)
947       {
948         /* found an interface that's overdue for RA determine new 
949            timeout value and arrange for RA to be sent unless interface is
950            still doing DAD.*/
951         if (!(flags & IFACE_TENTATIVE))
952           param->iface = if_index;
953         
954         new_timeout(context, param->name, param->now);
955         
956         /* zero timers for other contexts on the same subnet, so they don't timeout 
957            independently */
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;
963         
964         return 0; /* found, abort */
965       }
966   
967   return 1; /* keep searching */
968 }
969  
970 static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now)
971 {
972   if (difftime(now, context->ra_short_period_start) < 60.0)
973     /* range 5 - 20 */
974     context->ra_time = now + 5 + (rand16()/4400);
975   else
976     {
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);
980     }
981 }
982
983 static struct ra_interface *find_iface_param(char *iface)
984 {
985   struct ra_interface *ra;
986   
987   for (ra = daemon->ra_interfaces; ra; ra = ra->next)
988     if (wildcard_match(ra->name, iface))
989       return ra;
990
991   return NULL;
992 }
993
994 static unsigned int calc_interval(struct ra_interface *ra)
995 {
996   int interval = 600;
997   
998   if (ra && ra->interval != 0)
999     {
1000       interval = ra->interval;
1001       if (interval > 1800)
1002         interval = 1800;
1003       else if (interval < 4)
1004         interval = 4;
1005     }
1006   
1007   return (unsigned int)interval;
1008 }
1009
1010 static unsigned int calc_lifetime(struct ra_interface *ra)
1011 {
1012   int lifetime, interval = (int)calc_interval(ra);
1013   
1014   if (!ra || ra->lifetime == -1) /* not specified */
1015     lifetime = 3 * interval;
1016   else
1017     {
1018       lifetime = ra->lifetime;
1019       if (lifetime < interval && lifetime != 0)
1020         lifetime = interval;
1021       else if (lifetime > 9000)
1022         lifetime = 9000;
1023     }
1024   
1025   return (unsigned int)lifetime;
1026 }
1027
1028 static unsigned int calc_prio(struct ra_interface *ra)
1029 {
1030   if (ra)
1031     return ra->prio;
1032   
1033   return 0;
1034 }
1035
1036 #endif