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/>.
21 #include <netinet/icmp6.h>
24 struct dhcp_context
*current
;
25 struct dhcp_relay
*relay
;
26 struct in6_addr fallback
, relay_local
;
31 struct in6_addr
*target
;
37 static int complete_context6(struct in6_addr
*local
, int prefix
,
38 int scope
, int if_index
, int flags
,
39 unsigned int preferred
, unsigned int valid
, void *vparam
);
40 static int find_mac(int family
, char *addrp
, char *mac
, size_t maclen
, void *parmv
);
41 static int make_duid1(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
);
46 struct sockaddr_in6 saddr
;
47 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
48 int class = IPTOS_CLASS_CS6
;
52 if ((fd
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1 ||
53 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
54 setsockopt(fd
, IPPROTO_IPV6
, IPV6_TCLASS
, &class, sizeof(class)) == -1 ||
56 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &oneopt
, sizeof(oneopt
)) == -1 ||
59 die (_("cannot create DHCPv6 socket: %s"), NULL
, EC_BADNET
);
61 /* When bind-interfaces is set, there might be more than one dnmsasq
62 instance binding port 547. That's OK if they serve different networks.
63 Need to set REUSEADDR|REUSEPORT to make this posible.
64 Handle the case that REUSEPORT is defined, but the kernel doesn't
65 support it. This handles the introduction of REUSEPORT on Linux. */
66 if (option_bool(OPT_NOWILD
) || option_bool(OPT_CLEVERBIND
))
71 if ((rc
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &oneopt
, sizeof(oneopt
))) == -1 &&
77 rc
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &oneopt
, sizeof(oneopt
));
80 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL
, EC_BADNET
);
83 memset(&saddr
, 0, sizeof(saddr
));
84 #ifdef HAVE_SOCKADDR_SA_LEN
85 saddr
.sin6_len
= sizeof(struct sockaddr_in6
);
87 saddr
.sin6_family
= AF_INET6
;
88 saddr
.sin6_addr
= in6addr_any
;
89 saddr
.sin6_port
= htons(DHCPV6_SERVER_PORT
);
91 if (bind(fd
, (struct sockaddr
*)&saddr
, sizeof(struct sockaddr_in6
)))
92 die(_("failed to bind DHCPv6 server socket: %s"), NULL
, EC_BADNET
);
97 void dhcp6_packet(time_t now
)
99 struct dhcp_context
*context
;
100 struct dhcp_relay
*relay
;
101 struct iface_param parm
;
102 struct cmsghdr
*cmptr
;
106 struct cmsghdr align
; /* this ensures alignment */
107 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
109 struct sockaddr_in6 from
;
114 struct in6_addr dst_addr
;
116 memset(&dst_addr
, 0, sizeof(dst_addr
));
118 msg
.msg_control
= control_u
.control6
;
119 msg
.msg_controllen
= sizeof(control_u
);
121 msg
.msg_name
= &from
;
122 msg
.msg_namelen
= sizeof(from
);
123 msg
.msg_iov
= &daemon
->dhcp_packet
;
126 if ((sz
= recv_dhcp_packet(daemon
->dhcp6fd
, &msg
)) == -1)
129 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
130 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&& cmptr
->cmsg_type
== daemon
->v6pktinfo
)
134 struct in6_pktinfo
*p
;
136 p
.c
= CMSG_DATA(cmptr
);
138 if_index
= p
.p
->ipi6_ifindex
;
139 dst_addr
= p
.p
->ipi6_addr
;
142 if (!indextoname(daemon
->dhcp6fd
, if_index
, ifr
.ifr_name
))
145 if ((port
= relay_reply6(&from
, sz
, ifr
.ifr_name
)) == 0)
147 for (tmp
= daemon
->if_except
; tmp
; tmp
= tmp
->next
)
148 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
151 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
152 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
157 memset(&parm
.relay_local
, 0, IN6ADDRSZ
);
160 memset(&parm
.fallback
, 0, IN6ADDRSZ
);
162 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
163 if (IN6_IS_ADDR_UNSPECIFIED(&context
->start6
) && context
->prefix
== 0)
165 /* wildcard context for DHCP-stateless only */
166 parm
.current
= context
;
167 context
->current
= NULL
;
171 /* unlinked contexts are marked by context->current == context */
172 context
->current
= context
;
173 memset(&context
->local6
, 0, IN6ADDRSZ
);
176 for (relay
= daemon
->relay6
; relay
; relay
= relay
->next
)
177 relay
->current
= relay
;
179 if (!iface_enumerate(AF_INET6
, &parm
, complete_context6
))
182 if (daemon
->if_names
|| daemon
->if_addrs
)
185 for (tmp
= daemon
->if_names
; tmp
; tmp
= tmp
->next
)
186 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
189 if (!tmp
&& !parm
.addr_match
)
195 /* Ignore requests sent to the ALL_SERVERS multicast address for relay when
196 we're listening there for DHCPv6 server reasons. */
197 struct in6_addr all_servers
;
199 inet_pton(AF_INET6
, ALL_SERVERS
, &all_servers
);
201 if (!IN6_ARE_ADDR_EQUAL(&dst_addr
, &all_servers
))
202 relay_upstream6(parm
.relay
, sz
, &from
.sin6_addr
, from
.sin6_scope_id
);
206 /* May have configured relay, but not DHCP server */
207 if (!daemon
->doing_dhcp6
)
210 lease_prune(NULL
, now
); /* lose any expired leases */
212 port
= dhcp6_reply(parm
.current
, if_index
, ifr
.ifr_name
, &parm
.fallback
,
213 sz
, &from
.sin6_addr
, now
);
215 lease_update_file(now
);
219 /* The port in the source address of the original request should
220 be correct, but at least once client sends from the server port,
221 so we explicitly send to the client port to a client, and the
222 server port to a relay. */
225 from
.sin6_port
= htons(port
);
226 while (sendto(daemon
->dhcp6fd
, daemon
->outpacket
.iov_base
, save_counter(0),
227 0, (struct sockaddr
*)&from
, sizeof(from
)) == -1 &&
232 void get_client_mac(struct in6_addr
*client
, int iface
, unsigned char *mac
, unsigned int *maclenp
, unsigned int *mactypep
)
234 /* Recieving a packet from a host does not populate the neighbour
235 cache, so we send a neighbour discovery request if we can't
236 find the sender. Repeat a few times in case of packet loss. */
238 struct neigh_packet neigh
;
239 struct sockaddr_in6 addr
;
240 struct mac_param mac_param
;
243 neigh
.type
= ND_NEIGHBOR_SOLICIT
;
246 neigh
.target
= *client
;
248 memset(&addr
, 0, sizeof(addr
));
249 #ifdef HAVE_SOCKADDR_SA_LEN
250 addr
.sin6_len
= sizeof(struct sockaddr_in6
);
252 addr
.sin6_family
= AF_INET6
;
253 addr
.sin6_port
= htons(IPPROTO_ICMPV6
);
254 addr
.sin6_addr
= *client
;
255 addr
.sin6_scope_id
= iface
;
257 mac_param
.target
= client
;
258 mac_param
.maclen
= 0;
261 for (i
= 0; i
< 5; i
++)
265 iface_enumerate(AF_UNSPEC
, &mac_param
, find_mac
);
267 if (mac_param
.maclen
!= 0)
270 sendto(daemon
->icmp6fd
, &neigh
, sizeof(neigh
), 0, (struct sockaddr
*)&addr
, sizeof(addr
));
273 ts
.tv_nsec
= 100000000; /* 100ms */
274 nanosleep(&ts
, NULL
);
277 *maclenp
= mac_param
.maclen
;
278 *mactypep
= ARPHRD_ETHER
;
281 static int find_mac(int family
, char *addrp
, char *mac
, size_t maclen
, void *parmv
)
283 struct mac_param
*parm
= parmv
;
285 if (family
== AF_INET6
&& IN6_ARE_ADDR_EQUAL(parm
->target
, (struct in6_addr
*)addrp
))
287 if (maclen
<= DHCP_CHADDR_MAX
)
289 parm
->maclen
= maclen
;
290 memcpy(parm
->mac
, mac
, maclen
);
293 return 0; /* found, abort */
299 static int complete_context6(struct in6_addr
*local
, int prefix
,
300 int scope
, int if_index
, int flags
, unsigned int preferred
,
301 unsigned int valid
, void *vparam
)
303 struct dhcp_context
*context
;
304 struct dhcp_relay
*relay
;
305 struct iface_param
*param
= vparam
;
308 (void)scope
; /* warning */
310 if (if_index
== param
->ind
)
312 if (!IN6_IS_ADDR_LOOPBACK(local
) &&
313 !IN6_IS_ADDR_LINKLOCAL(local
) &&
314 !IN6_IS_ADDR_MULTICAST(local
))
316 /* if we have --listen-address config, see if the
317 arrival interface has a matching address. */
318 for (tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
319 if (tmp
->addr
.sa
.sa_family
== AF_INET6
&&
320 IN6_ARE_ADDR_EQUAL(&tmp
->addr
.in6
.sin6_addr
, local
))
321 param
->addr_match
= 1;
323 /* Determine a globally address on the arrival interface, even
324 if we have no matching dhcp-context, because we're only
325 allocating on remote subnets via relays. This
326 is used as a default for the DNS server option. */
327 param
->fallback
= *local
;
329 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
331 if ((context
->flags
& CONTEXT_DHCP
) &&
332 !(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
334 prefix
<= context
->prefix
&&
336 prefix
== context
->prefix
&&
338 is_same_net6(local
, &context
->start6
, prefix
) &&
339 is_same_net6(local
, &context
->end6
, prefix
))
343 /* link it onto the current chain if we've not seen it before */
344 if (context
->current
== context
)
346 struct dhcp_context
*tmp
, **up
;
348 /* use interface values only for contructed contexts */
349 if (!(context
->flags
& CONTEXT_CONSTRUCTED
))
350 preferred
= valid
= 0xffffffff;
351 else if (flags
& IFACE_DEPRECATED
)
354 if (context
->flags
& CONTEXT_DEPRECATE
)
357 /* order chain, longest preferred time first */
358 for (up
= ¶m
->current
, tmp
= param
->current
; tmp
; tmp
= tmp
->current
)
359 if (tmp
->preferred
<= preferred
)
364 context
->current
= *up
;
366 context
->local6
= *local
;
367 context
->preferred
= preferred
;
368 context
->valid
= valid
;
374 for (relay
= daemon
->relay6
; relay
; relay
= relay
->next
)
375 if (IN6_ARE_ADDR_EQUAL(local
, &relay
->local
.addr
.addr6
) && relay
->current
== relay
&&
376 (IN6_IS_ADDR_UNSPECIFIED(¶m
->relay_local
) || IN6_ARE_ADDR_EQUAL(local
, ¶m
->relay_local
)))
378 relay
->current
= param
->relay
;
379 param
->relay
= relay
;
380 param
->relay_local
= *local
;
388 struct dhcp_config
*config_find_by_address6(struct dhcp_config
*configs
, struct in6_addr
*net
, int prefix
, u64 addr
)
390 struct dhcp_config
*config
;
392 for (config
= configs
; config
; config
= config
->next
)
393 if ((config
->flags
& CONFIG_ADDR6
) &&
394 is_same_net6(&config
->addr6
, net
, prefix
) &&
395 (prefix
== 128 || addr6part(&config
->addr6
) == addr
))
401 struct dhcp_context
*address6_allocate(struct dhcp_context
*context
, unsigned char *clid
, int clid_len
, int temp_addr
,
402 int iaid
, int serial
, struct dhcp_netid
*netids
, int plain_range
, struct in6_addr
*ans
)
404 /* Find a free address: exclude anything in use and anything allocated to
405 a particular hwaddr/clientid/hostname in our configuration.
406 Try to return from contexts which match netids first.
408 Note that we assume the address prefix lengths are 64 or greater, so we can
409 get by with 64 bit arithmetic.
413 struct dhcp_context
*c
, *d
;
417 /* hash hwaddr: use the SDBM hashing algorithm. This works
418 for MAC addresses, let's see how it manages with client-ids!
419 For temporary addresses, we generate a new random one each time. */
423 for (j
= iaid
, i
= 0; i
< clid_len
; i
++)
424 j
+= clid
[i
] + (j
<< 6) + (j
<< 16) - j
;
426 for (pass
= 0; pass
<= plain_range
? 1 : 0; pass
++)
427 for (c
= context
; c
; c
= c
->current
)
428 if (c
->flags
& (CONTEXT_DEPRECATE
| CONTEXT_STATIC
| CONTEXT_RA_STATELESS
| CONTEXT_USED
))
430 else if (!match_netid(c
->filter
, netids
, pass
))
434 if (!temp_addr
&& option_bool(OPT_CONSEC_ADDR
))
435 /* seed is largest extant lease addr in this context */
436 start
= lease_find_max_addr6(c
) + serial
;
438 start
= addr6part(&c
->start6
) + ((j
+ c
->addr_epoch
) % (1 + addr6part(&c
->end6
) - addr6part(&c
->start6
)));
440 /* iterate until we find a free address. */
444 /* eliminate addresses in use by the server. */
445 for (d
= context
; d
; d
= d
->current
)
446 if (addr
== addr6part(&d
->local6
))
450 !lease6_find_by_addr(&c
->start6
, c
->prefix
, addr
) &&
451 !config_find_by_address6(daemon
->dhcp_conf
, &c
->start6
, c
->prefix
, addr
))
454 setaddr6part (ans
, addr
);
460 if (addr
== addr6part(&c
->end6
) + 1)
461 addr
= addr6part(&c
->start6
);
463 } while (addr
!= start
);
469 /* can dynamically allocate addr */
470 struct dhcp_context
*address6_available(struct dhcp_context
*context
,
471 struct in6_addr
*taddr
,
472 struct dhcp_netid
*netids
,
475 u64 start
, end
, addr
= addr6part(taddr
);
476 struct dhcp_context
*tmp
;
478 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
480 start
= addr6part(&tmp
->start6
);
481 end
= addr6part(&tmp
->end6
);
483 if (!(tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_RA_STATELESS
)) &&
484 is_same_net6(&tmp
->start6
, taddr
, tmp
->prefix
) &&
485 is_same_net6(&tmp
->end6
, taddr
, tmp
->prefix
) &&
488 match_netid(tmp
->filter
, netids
, plain_range
))
495 /* address OK if configured */
496 struct dhcp_context
*address6_valid(struct dhcp_context
*context
,
497 struct in6_addr
*taddr
,
498 struct dhcp_netid
*netids
,
501 struct dhcp_context
*tmp
;
503 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
504 if (is_same_net6(&tmp
->start6
, taddr
, tmp
->prefix
) &&
505 match_netid(tmp
->filter
, netids
, plain_range
))
511 int config_valid(struct dhcp_config
*config
, struct dhcp_context
*context
, struct in6_addr
*addr
)
513 if (!config
|| !(config
->flags
& CONFIG_ADDR6
))
516 if ((config
->flags
& CONFIG_WILDCARD
) && context
->prefix
== 64)
518 *addr
= context
->start6
;
519 setaddr6part(addr
, addr6part(&config
->addr6
));
523 if (is_same_net6(&context
->start6
, &config
->addr6
, context
->prefix
))
525 *addr
= config
->addr6
;
532 void make_duid(time_t now
)
536 if (daemon
->duid_config
)
540 daemon
->duid
= p
= safe_malloc(daemon
->duid_config_len
+ 6);
541 daemon
->duid_len
= daemon
->duid_config_len
+ 6;
542 PUTSHORT(2, p
); /* DUID_EN */
543 PUTLONG(daemon
->duid_enterprise
, p
);
544 memcpy(p
, daemon
->duid_config
, daemon
->duid_config_len
);
550 /* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */
551 #ifndef HAVE_BROKEN_RTC
552 /* rebase epoch to 1/1/2000 */
553 if (!option_bool(OPT_LEASE_RO
) || daemon
->lease_change_command
)
554 newnow
= now
- 946684800;
557 iface_enumerate(AF_LOCAL
, &newnow
, make_duid1
);
560 die("Cannot create DHCPv6 server DUID: %s", NULL
, EC_MISC
);
564 static int make_duid1(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
)
566 /* create DUID as specified in RFC3315. We use the MAC of the
567 first interface we find that isn't loopback or P-to-P and
568 has address-type < 256. Address types above 256 are things like
569 tunnels which don't have usable MAC addresses. */
574 time_t newnow
= *((time_t *)parm
);
581 daemon
->duid
= p
= safe_malloc(maclen
+ 4);
582 daemon
->duid_len
= maclen
+ 4;
583 PUTSHORT(3, p
); /* DUID_LL */
584 PUTSHORT(type
, p
); /* address type */
588 daemon
->duid
= p
= safe_malloc(maclen
+ 8);
589 daemon
->duid_len
= maclen
+ 8;
590 PUTSHORT(1, p
); /* DUID_LLT */
591 PUTSHORT(type
, p
); /* address type */
592 PUTLONG(*((time_t *)parm
), p
); /* time */
595 memcpy(p
, mac
, maclen
);
605 static int construct_worker(struct in6_addr
*local
, int prefix
,
606 int scope
, int if_index
, int flags
,
607 int preferred
, int valid
, void *vparam
)
609 char ifrn_name
[IFNAMSIZ
];
610 struct in6_addr start6
, end6
;
611 struct dhcp_context
*template, *context
;
618 struct cparam
*param
= vparam
;
620 if (IN6_IS_ADDR_LOOPBACK(local
) ||
621 IN6_IS_ADDR_LINKLOCAL(local
) ||
622 IN6_IS_ADDR_MULTICAST(local
))
625 if (!(flags
& IFACE_PERMANENT
))
628 if (flags
& IFACE_DEPRECATED
)
631 if (!indextoname(daemon
->icmp6fd
, if_index
, ifrn_name
))
634 for (template = daemon
->dhcp6
; template; template = template->next
)
635 if (!(template->flags
& CONTEXT_TEMPLATE
))
637 /* non-template entries, just fill in interface and local addresses */
639 if (prefix
<= template->prefix
&&
641 if (prefix
== template->prefix
&&
643 is_same_net6(local
, &template->start6
, prefix
) &&
644 is_same_net6(local
, &template->end6
, prefix
))
646 template->if_index
= if_index
;
647 template->local6
= *local
;
651 else if (wildcard_match(template->template_interface
, ifrn_name
) &&
653 template->prefix
>= prefix
)
655 template->prefix
== prefix
)
659 setaddr6part(&start6
, addr6part(&template->start6
));
661 setaddr6part(&end6
, addr6part(&template->end6
));
663 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
664 if ((context
->flags
& CONTEXT_CONSTRUCTED
) &&
665 IN6_ARE_ADDR_EQUAL(&start6
, &context
->start6
) &&
666 IN6_ARE_ADDR_EQUAL(&end6
, &context
->end6
))
668 int flags
= context
->flags
;
669 context
->flags
&= ~(CONTEXT_GC
| CONTEXT_OLD
);
670 if (flags
& CONTEXT_OLD
)
672 /* address went, now it's back */
673 log_context(AF_INET6
, context
);
674 /* fast RAs for a while */
675 ra_start_unsolicted(param
->now
, context
);
677 /* Add address to name again */
678 if (context
->flags
& CONTEXT_RA_NAME
)
684 if (!context
&& (context
= whine_malloc(sizeof (struct dhcp_context
))))
686 *context
= *template;
687 context
->start6
= start6
;
688 context
->end6
= end6
;
689 context
->flags
&= ~CONTEXT_TEMPLATE
;
690 context
->flags
|= CONTEXT_CONSTRUCTED
;
691 context
->if_index
= if_index
;
692 context
->local6
= *local
;
693 context
->saved_valid
= 0;
695 context
->next
= daemon
->dhcp6
;
696 daemon
->dhcp6
= context
;
698 ra_start_unsolicted(param
->now
, context
);
699 /* we created a new one, need to call
700 lease_update_file to get periodic functions called */
703 /* Will need to add new putative SLAAC addresses to existing leases */
704 if (context
->flags
& CONTEXT_RA_NAME
)
707 log_context(AF_INET6
, context
);
714 void dhcp_construct_contexts(time_t now
)
716 struct dhcp_context
*context
, *tmp
, **up
;
722 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
723 if (context
->flags
& CONTEXT_CONSTRUCTED
)
724 context
->flags
|= CONTEXT_GC
;
726 iface_enumerate(AF_INET6
, ¶m
, construct_worker
);
728 for (up
= &daemon
->dhcp6
, context
= daemon
->dhcp6
; context
; context
= tmp
)
733 if (context
->flags
& CONTEXT_GC
&& !(context
->flags
& CONTEXT_OLD
))
736 if ((context
->flags
& (CONTEXT_RA_ONLY
| CONTEXT_RA_NAME
| CONTEXT_RA_STATELESS
)) ||
739 /* previously constructed context has gone. advertise it's demise */
740 context
->flags
|= CONTEXT_OLD
;
741 context
->address_lost_time
= now
;
742 /* Apply same ceiling of configured lease time as in radv.c */
743 if (context
->saved_valid
> context
->lease_time
)
744 context
->saved_valid
= context
->lease_time
;
745 /* maximum time is 2 hours, from RFC */
746 if (context
->saved_valid
> 7200) /* 2 hours */
747 context
->saved_valid
= 7200;
748 ra_start_unsolicted(now
, context
);
749 param
.newone
= 1; /* include deletion */
751 if (context
->flags
& CONTEXT_RA_NAME
)
754 log_context(AF_INET6
, context
);
760 /* we were never doing RA for this, so free now */
771 if (daemon
->dhcp
|| daemon
->doing_dhcp6
)
774 lease_update_slaac(now
);
775 lease_update_file(now
);
778 /* Not doing DHCP, so no lease system, manage alarms for ra only */
779 send_alarm(periodic_ra(now
), now
);