1 /* dnsmasq is Copyright (c) 2000-2013 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
, found_context
, first
;
33 struct dhcp_netid
*tags
;
34 struct in6_addr link_local
, link_global
;
35 unsigned int pref_time
;
39 time_t now
; int iface
;
42 static void send_ra(time_t now
, int iface
, char *iface_name
, struct in6_addr
*dest
);
43 static int add_prefixes(struct in6_addr
*local
, int prefix
,
44 int scope
, int if_index
, int flags
,
45 unsigned int preferred
, unsigned int valid
, void *vparam
);
46 static int iface_search(struct in6_addr
*local
, int prefix
,
47 int scope
, int if_index
, int flags
,
48 int prefered
, int valid
, void *vparam
);
49 static int add_lla(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
);
50 static void new_timeout(struct dhcp_context
*context
, time_t now
);
54 void ra_init(time_t now
)
56 struct icmp6_filter filter
;
58 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
59 int class = IPTOS_CLASS_CS6
;
61 int val
= 255; /* radvd uses this value */
62 socklen_t len
= sizeof(int);
63 struct dhcp_context
*context
;
65 /* ensure this is around even if we're not doing DHCPv6 */
66 expand_buf(&daemon
->outpacket
, sizeof(struct dhcp_packet
));
68 /* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
69 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
70 if ((context
->flags
& CONTEXT_RA_NAME
))
73 /* Need ICMP6 socket for transmission for DHCPv6 even when not doing RA. */
75 ICMP6_FILTER_SETBLOCKALL(&filter
);
78 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT
, &filter
);
80 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY
, &filter
);
83 if ((fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
)) == -1 ||
84 getsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &hop_limit
, &len
) ||
85 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
86 setsockopt(fd
, IPPROTO_IPV6
, IPV6_TCLASS
, &class, sizeof(class)) == -1 ||
89 !set_ipv6pktinfo(fd
) ||
90 setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &val
, sizeof(val
)) ||
91 setsockopt(fd
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &val
, sizeof(val
)) ||
92 setsockopt(fd
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
, sizeof(filter
)) == -1)
93 die (_("cannot create ICMPv6 socket: %s"), NULL
, EC_BADNET
);
98 ra_start_unsolicted(now
, NULL
);
101 void ra_start_unsolicted(time_t now
, struct dhcp_context
*context
)
103 /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
104 if it's not appropriate to advertise those contexts.
105 This gets re-called on a netlink route-change to re-do the advertisement
106 and pick up new interfaces */
109 context
->ra_short_period_start
= context
->ra_time
= now
;
111 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
112 if (!(context
->flags
& CONTEXT_TEMPLATE
))
114 context
->ra_time
= now
+ (rand16()/13000); /* range 0 - 5 */
115 /* re-do frequently for a minute or so, in case the first gets lost. */
116 context
->ra_short_period_start
= now
;
120 void icmp6_packet(time_t now
)
122 char interface
[IF_NAMESIZE
+1];
125 struct cmsghdr
*cmptr
;
128 struct cmsghdr align
; /* this ensures alignment */
129 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
131 struct sockaddr_in6 from
;
132 unsigned char *packet
;
135 /* Note: use outpacket for input buffer */
136 msg
.msg_control
= control_u
.control6
;
137 msg
.msg_controllen
= sizeof(control_u
);
139 msg
.msg_name
= &from
;
140 msg
.msg_namelen
= sizeof(from
);
141 msg
.msg_iov
= &daemon
->outpacket
;
144 if ((sz
= recv_dhcp_packet(daemon
->icmp6fd
, &msg
)) == -1 || sz
< 8)
147 packet
= (unsigned char *)daemon
->outpacket
.iov_base
;
149 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
150 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&& cmptr
->cmsg_type
== daemon
->v6pktinfo
)
154 struct in6_pktinfo
*p
;
156 p
.c
= CMSG_DATA(cmptr
);
158 if_index
= p
.p
->ipi6_ifindex
;
161 if (!indextoname(daemon
->icmp6fd
, if_index
, interface
))
164 if (!iface_check(AF_LOCAL
, NULL
, interface
, NULL
))
167 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
168 if (tmp
->name
&& wildcard_match(tmp
->name
, interface
))
174 if (packet
[0] == ICMP6_ECHO_REPLY
)
175 lease_ping_reply(&from
.sin6_addr
, packet
, interface
);
176 else if (packet
[0] == ND_ROUTER_SOLICIT
)
180 /* look for link-layer address option for logging */
181 if (sz
>= 16 && packet
[8] == ICMP6_OPT_SOURCE_MAC
&& (packet
[9] * 8) + 8 <= sz
)
183 print_mac(daemon
->namebuff
, &packet
[10], (packet
[9] * 8) - 2);
184 mac
= daemon
->namebuff
;
187 #ifdef HAVE_QUIET_DHCP
188 if (!option_bool(OPT_QUIET_RA
))
190 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-SOLICIT(%s) %s", interface
, mac
);
191 /* source address may not be valid in solicit request. */
192 send_ra(now
, if_index
, interface
, !IN6_IS_ADDR_UNSPECIFIED(&from
.sin6_addr
) ? &from
.sin6_addr
: NULL
);
196 static void send_ra(time_t now
, int iface
, char *iface_name
, struct in6_addr
*dest
)
198 struct ra_packet
*ra
;
199 struct ra_param parm
;
200 struct sockaddr_in6 addr
;
201 struct dhcp_context
*context
, *tmp
, **up
;
202 struct dhcp_netid iface_id
;
203 struct dhcp_opt
*opt_cfg
;
205 #ifdef HAVE_LINUX_NETWORK
210 ra
= expand(sizeof(struct ra_packet
));
212 ra
->type
= ND_ROUTER_ADVERT
;
214 ra
->hop_limit
= hop_limit
;
216 ra
->lifetime
= htons(RA_INTERVAL
* 3); /* AdvDefaultLifetime * 3 */
217 ra
->reachable_time
= 0;
218 ra
->retrans_time
= 0;
223 parm
.found_context
= 0;
224 parm
.if_name
= iface_name
;
229 /* set tag with name == interface */
230 iface_id
.net
= iface_name
;
231 iface_id
.next
= NULL
;
232 parm
.tags
= &iface_id
;
234 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
236 context
->flags
&= ~CONTEXT_RA_DONE
;
237 context
->netid
.next
= &context
->netid
;
240 if (!iface_enumerate(AF_INET6
, &parm
, add_prefixes
))
243 /* Look for constructed contexts associated with addresses which have gone,
244 and advertise them with preferred_time == 0 RFC 6204 4.3 L-13 */
245 for (up
= &daemon
->dhcp6
, context
= daemon
->dhcp6
; context
; context
= tmp
)
249 if (context
->if_index
== iface
&& (context
->flags
& CONTEXT_OLD
))
251 unsigned int old
= difftime(now
, context
->address_lost_time
);
253 if (old
> context
->saved_valid
)
255 /* We've advertised this enough, time to go */
261 struct prefix_opt
*opt
;
262 struct in6_addr local
= context
->start6
;
265 parm
.found_context
= 1;
267 /* zero net part of address */
268 setaddr6part(&local
, addr6part(&local
) & ~((context
->prefix
== 64) ? (u64
)-1LL : (1LLU << (128 - context
->prefix
)) - 1LLU));
270 if ((context
->flags
&
271 (CONTEXT_RA_ONLY
| CONTEXT_RA_NAME
| CONTEXT_RA_STATELESS
)))
274 if ((opt
= expand(sizeof(struct prefix_opt
))))
276 opt
->type
= ICMP6_OPT_PREFIX
;
278 opt
->prefix_len
= context
->prefix
;
279 /* autonomous only if we're not doing dhcp, always set "on-link" */
280 opt
->flags
= do_slaac
? 0xC0 : 0x80;
281 opt
->valid_lifetime
= htonl(context
->saved_valid
- old
);
282 opt
->preferred_lifetime
= htonl(0);
286 inet_ntop(AF_INET6
, &local
, daemon
->addrbuff
, ADDRSTRLEN
);
287 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s old prefix", iface_name
, daemon
->addrbuff
);
297 if (!parm
.found_context
)
300 #ifdef HAVE_LINUX_NETWORK
301 /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
302 available from SIOCGIFMTU */
303 sprintf(daemon
->namebuff
, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name
);
304 if ((f
= fopen(daemon
->namebuff
, "r")))
306 if (fgets(daemon
->namebuff
, MAXDNAME
, f
))
308 put_opt6_char(ICMP6_OPT_MTU
);
311 put_opt6_long(atoi(daemon
->namebuff
));
317 iface_enumerate(AF_LOCAL
, &iface
, add_lla
);
319 /* RDNSS, RFC 6106, use relevant DHCP6 options */
320 (void)option_filter(parm
.tags
, NULL
, daemon
->dhcp_opts6
);
322 for (opt_cfg
= daemon
->dhcp_opts6
; opt_cfg
; opt_cfg
= opt_cfg
->next
)
326 /* netids match and not encapsulated? */
327 if (!(opt_cfg
->flags
& DHOPT_TAGOK
))
330 if (opt_cfg
->opt
== OPTION6_DNS_SERVER
)
332 struct in6_addr
*a
= (struct in6_addr
*)opt_cfg
->val
;
335 if (opt_cfg
->len
== 0)
338 put_opt6_char(ICMP6_OPT_RDNSS
);
339 put_opt6_char((opt_cfg
->len
/8) + 1);
341 put_opt6_long(RA_INTERVAL
* 2); /* lifetime - twice RA retransmit */
342 /* zero means "self" */
343 for (i
= 0; i
< opt_cfg
->len
; i
+= IN6ADDRSZ
, a
++)
344 if (IN6_IS_ADDR_UNSPECIFIED(a
))
345 put_opt6(&parm
.link_global
, IN6ADDRSZ
);
347 put_opt6(a
, IN6ADDRSZ
);
350 if (opt_cfg
->opt
== OPTION6_DOMAIN_SEARCH
&& opt_cfg
->len
!= 0)
352 int len
= ((opt_cfg
->len
+7)/8);
354 put_opt6_char(ICMP6_OPT_DNSSL
);
355 put_opt6_char(len
+ 1);
357 put_opt6_long(RA_INTERVAL
* 2); /* lifetime - twice RA retransmit */
358 put_opt6(opt_cfg
->val
, opt_cfg
->len
);
361 for (i
= opt_cfg
->len
; i
< len
* 8; i
++)
366 if (daemon
->port
== NAMESERVER_PORT
&& !done_dns
)
368 /* default == us, as long as we are supplying DNS service. */
369 put_opt6_char(ICMP6_OPT_RDNSS
);
372 put_opt6_long(RA_INTERVAL
* 2); /* lifetime - twice RA retransmit */
373 put_opt6(&parm
.link_global
, IN6ADDRSZ
);
376 /* set managed bits unless we're providing only RA on this link */
378 ra
->flags
|= 0x80; /* M flag, managed, */
380 ra
->flags
|= 0x40; /* O flag, other */
382 /* decide where we're sending */
383 memset(&addr
, 0, sizeof(addr
));
384 #ifdef HAVE_SOCKADDR_SA_LEN
385 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
387 addr
.sin6_family
= AF_INET6
;
388 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
391 addr
.sin6_addr
= *dest
;
392 if (IN6_IS_ADDR_LINKLOCAL(dest
) ||
393 IN6_IS_ADDR_MC_LINKLOCAL(dest
))
394 addr
.sin6_scope_id
= iface
;
397 inet_pton(AF_INET6
, ALL_NODES
, &addr
.sin6_addr
);
399 send_from(daemon
->icmp6fd
, 0, daemon
->outpacket
.iov_base
, save_counter(0),
400 (union mysockaddr
*)&addr
, (struct all_addr
*)&parm
.link_local
, iface
);
404 static int add_prefixes(struct in6_addr
*local
, int prefix
,
405 int scope
, int if_index
, int flags
,
406 unsigned int preferred
, unsigned int valid
, void *vparam
)
408 struct ra_param
*param
= vparam
;
410 (void)scope
; /* warning */
412 if (if_index
== param
->ind
)
414 if (IN6_IS_ADDR_LINKLOCAL(local
))
415 param
->link_local
= *local
;
416 else if (!IN6_IS_ADDR_LOOPBACK(local
) &&
417 !IN6_IS_ADDR_MULTICAST(local
))
423 unsigned int time
= 0xffffffff;
424 struct dhcp_context
*context
;
426 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
427 if (!(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
428 prefix
== context
->prefix
&&
429 is_same_net6(local
, &context
->start6
, prefix
) &&
430 is_same_net6(local
, &context
->end6
, prefix
))
432 context
->saved_valid
= valid
;
434 if ((context
->flags
&
435 (CONTEXT_RA_ONLY
| CONTEXT_RA_NAME
| CONTEXT_RA_STATELESS
)))
438 if (context
->flags
& CONTEXT_DHCP
)
441 if (!(context
->flags
& CONTEXT_RA_STATELESS
))
447 /* don't do RA for non-ra-only unless --enable-ra is set */
448 if (!option_bool(OPT_RA
))
454 /* find floor time, don't reduce below 3 * RA interval. */
455 if (time
> context
->lease_time
)
457 time
= context
->lease_time
;
458 if (time
< ((unsigned int)(3 * RA_INTERVAL
)))
459 time
= 3 * RA_INTERVAL
;
462 if (context
->flags
& CONTEXT_DEPRECATE
)
465 if (context
->flags
& CONTEXT_CONSTRUCTED
)
469 /* collect dhcp-range tags */
470 if (context
->netid
.next
== &context
->netid
&& context
->netid
.net
)
472 context
->netid
.next
= param
->tags
;
473 param
->tags
= &context
->netid
;
476 /* subsequent prefixes on the same interface
477 and subsequent instances of this prefix don't need timers.
478 Be careful not to find the same prefix twice with different
480 if (!(context
->flags
& CONTEXT_RA_DONE
))
483 context
->ra_time
= 0;
484 context
->flags
|= CONTEXT_RA_DONE
;
489 param
->found_context
= 1;
492 /* configured time is ceiling */
493 if (!constructed
|| valid
> time
)
496 if (flags
& IFACE_DEPRECATED
)
502 /* configured time is ceiling */
503 if (!constructed
|| preferred
> time
)
506 if (preferred
> param
->pref_time
)
508 param
->pref_time
= preferred
;
509 param
->link_global
= *local
;
514 struct prefix_opt
*opt
;
516 if ((opt
= expand(sizeof(struct prefix_opt
))))
518 /* zero net part of address */
519 setaddr6part(local
, addr6part(local
) & ~((prefix
== 64) ? (u64
)-1LL : (1LLU << (128 - prefix
)) - 1LLU));
521 opt
->type
= ICMP6_OPT_PREFIX
;
523 opt
->prefix_len
= prefix
;
524 /* autonomous only if we're not doing dhcp, always set "on-link" */
525 opt
->flags
= do_slaac
? 0xC0 : 0x80;
526 opt
->valid_lifetime
= htonl(valid
);
527 opt
->preferred_lifetime
= htonl(preferred
);
529 opt
->prefix
= *local
;
531 inet_ntop(AF_INET6
, local
, daemon
->addrbuff
, ADDRSTRLEN
);
532 #ifdef HAVE_QUIET_DHCP
533 if (!option_bool(OPT_QUIET_RA
))
535 my_syslog(MS_DHCP
| LOG_INFO
, "RTR-ADVERT(%s) %s", param
->if_name
, daemon
->addrbuff
);
544 static int add_lla(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
)
548 if (index
== *((int *)parm
))
550 /* size is in units of 8 octets and includes type and length (2 bytes)
552 int len
= (maclen
+ 9) >> 3;
553 unsigned char *p
= expand(len
<< 3);
554 memset(p
, 0, len
<< 3);
555 *p
++ = ICMP6_OPT_SOURCE_MAC
;
557 memcpy(p
, mac
, maclen
);
565 time_t periodic_ra(time_t now
)
567 struct search_param param
;
568 struct dhcp_context
*context
;
570 char interface
[IF_NAMESIZE
+1];
577 /* find overdue events, and time of first future event */
578 for (next_event
= 0, context
= daemon
->dhcp6
; context
; context
= context
->next
)
579 if (context
->ra_time
!= 0)
581 if (difftime(context
->ra_time
, now
) <= 0.0)
584 if (next_event
== 0 || difftime(next_event
, context
->ra_time
) > 0.0)
585 next_event
= context
->ra_time
;
592 if ((context
->flags
& CONTEXT_OLD
) && context
->if_index
!= 0)
594 /* A context for an old address. We'll not find the interface by
595 looking for addresses, but we know it anyway, as long as we
596 sent at least one RA whilst the address was current. */
597 param
.iface
= context
->if_index
;
598 new_timeout(context
, now
);
600 else if (iface_enumerate(AF_INET6
, ¶m
, iface_search
))
601 /* There's a context overdue, but we can't find an interface
602 associated with it, because it's for a subnet we dont
603 have an interface on. Probably we're doing DHCP on
604 a remote subnet via a relay. Zero the timer, since we won't
605 ever be able to send ra's and satistfy it. */
606 context
->ra_time
= 0;
608 if (param
.iface
!= 0 &&
609 indextoname(daemon
->icmp6fd
, param
.iface
, interface
) &&
610 iface_check(AF_LOCAL
, NULL
, interface
, NULL
))
613 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
614 if (tmp
->name
&& wildcard_match(tmp
->name
, interface
))
617 send_ra(now
, param
.iface
, interface
, NULL
);
623 static int iface_search(struct in6_addr
*local
, int prefix
,
624 int scope
, int if_index
, int flags
,
625 int preferred
, int valid
, void *vparam
)
627 struct search_param
*param
= vparam
;
628 struct dhcp_context
*context
;
634 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
635 if (!(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
636 prefix
== context
->prefix
&&
637 is_same_net6(local
, &context
->start6
, prefix
) &&
638 is_same_net6(local
, &context
->end6
, prefix
) &&
639 context
->ra_time
!= 0 &&
640 difftime(context
->ra_time
, param
->now
) <= 0.0)
642 /* found an interface that's overdue for RA determine new
643 timeout value and arrange for RA to be sent unless interface is
646 if (!(flags
& IFACE_TENTATIVE
))
647 param
->iface
= if_index
;
649 new_timeout(context
, param
->now
);
651 /* zero timers for other contexts on the same subnet, so they don't timeout
653 for (context
= context
->next
; context
; context
= context
->next
)
654 if (prefix
== context
->prefix
&&
655 is_same_net6(local
, &context
->start6
, prefix
) &&
656 is_same_net6(local
, &context
->end6
, prefix
))
657 context
->ra_time
= 0;
659 return 0; /* found, abort */
662 return 1; /* keep searching */
665 static void new_timeout(struct dhcp_context
*context
, time_t now
)
667 if (difftime(now
, context
->ra_short_period_start
) < 60.0 || option_bool(OPT_FAST_RA
))
669 context
->ra_time
= now
+ 5 + (rand16()/4400);
671 /* range 3/4 - 1 times RA_INTERVAL */
672 context
->ra_time
= now
+ (3 * RA_INTERVAL
)/4 + ((RA_INTERVAL
* (unsigned int)rand16()) >> 18);