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/>.
22 struct dhcp_context
*current
;
23 struct dhcp_relay
*relay
;
24 struct in6_addr fallback
, relay_local
;
28 static int complete_context6(struct in6_addr
*local
, int prefix
,
29 int scope
, int if_index
, int flags
,
30 unsigned int preferred
, unsigned int valid
, void *vparam
);
32 static int make_duid1(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
);
37 struct sockaddr_in6 saddr
;
38 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
39 int class = IPTOS_CLASS_CS6
;
43 if ((fd
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1 ||
44 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
45 setsockopt(fd
, IPPROTO_IPV6
, IPV6_TCLASS
, &class, sizeof(class)) == -1 ||
47 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &oneopt
, sizeof(oneopt
)) == -1 ||
50 die (_("cannot create DHCPv6 socket: %s"), NULL
, EC_BADNET
);
52 /* When bind-interfaces is set, there might be more than one dnmsasq
53 instance binding port 547. That's OK if they serve different networks.
54 Need to set REUSEADDR|REUSEPORT to make this posible.
55 Handle the case that REUSEPORT is defined, but the kernel doesn't
56 support it. This handles the introduction of REUSEPORT on Linux. */
57 if (option_bool(OPT_NOWILD
) || option_bool(OPT_CLEVERBIND
))
62 if ((rc
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &oneopt
, sizeof(oneopt
))) == -1 &&
68 rc
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &oneopt
, sizeof(oneopt
));
71 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL
, EC_BADNET
);
74 memset(&saddr
, 0, sizeof(saddr
));
75 #ifdef HAVE_SOCKADDR_SA_LEN
76 saddr
.sin6_len
= sizeof(struct sockaddr_in6
);
78 saddr
.sin6_family
= AF_INET6
;
79 saddr
.sin6_addr
= in6addr_any
;
80 saddr
.sin6_port
= htons(DHCPV6_SERVER_PORT
);
82 if (bind(fd
, (struct sockaddr
*)&saddr
, sizeof(struct sockaddr_in6
)))
83 die(_("failed to bind DHCPv6 server socket: %s"), NULL
, EC_BADNET
);
88 void dhcp6_packet(time_t now
)
90 struct dhcp_context
*context
;
91 struct dhcp_relay
*relay
;
92 struct iface_param parm
;
93 struct cmsghdr
*cmptr
;
97 struct cmsghdr align
; /* this ensures alignment */
98 char control6
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
100 struct sockaddr_in6 from
;
106 msg
.msg_control
= control_u
.control6
;
107 msg
.msg_controllen
= sizeof(control_u
);
109 msg
.msg_name
= &from
;
110 msg
.msg_namelen
= sizeof(from
);
111 msg
.msg_iov
= &daemon
->dhcp_packet
;
114 if ((sz
= recv_dhcp_packet(daemon
->dhcp6fd
, &msg
)) == -1)
117 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
118 if (cmptr
->cmsg_level
== IPPROTO_IPV6
&& cmptr
->cmsg_type
== daemon
->v6pktinfo
)
122 struct in6_pktinfo
*p
;
124 p
.c
= CMSG_DATA(cmptr
);
126 if_index
= p
.p
->ipi6_ifindex
;
129 if (!indextoname(daemon
->dhcp6fd
, if_index
, ifr
.ifr_name
))
132 if ((port
= relay_reply6(&from
, sz
, ifr
.ifr_name
)) == 0)
135 for (tmp
= daemon
->if_except
; tmp
; tmp
= tmp
->next
)
136 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
139 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
140 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
145 memset(&parm
.relay_local
, 0, IN6ADDRSZ
);
148 memset(&parm
.fallback
, 0, IN6ADDRSZ
);
150 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
151 if (IN6_IS_ADDR_UNSPECIFIED(&context
->start6
) && context
->prefix
== 0)
153 /* wildcard context for DHCP-stateless only */
154 parm
.current
= context
;
155 context
->current
= NULL
;
159 /* unlinked contexts are marked by context->current == context */
160 context
->current
= context
;
161 memset(&context
->local6
, 0, IN6ADDRSZ
);
164 for (relay
= daemon
->relay6
; relay
; relay
= relay
->next
)
165 relay
->current
= relay
;
167 if (!iface_enumerate(AF_INET6
, &parm
, complete_context6
))
170 if (daemon
->if_names
|| daemon
->if_addrs
)
173 for (tmp
= daemon
->if_names
; tmp
; tmp
= tmp
->next
)
174 if (tmp
->name
&& wildcard_match(tmp
->name
, ifr
.ifr_name
))
177 if (!tmp
&& !parm
.addr_match
)
183 relay_upstream6(parm
.relay
, sz
, &from
.sin6_addr
, from
.sin6_scope_id
);
187 /* May have configured relay, but not DHCP server */
188 if (!daemon
->doing_dhcp6
)
191 lease_prune(NULL
, now
); /* lose any expired leases */
193 port
= dhcp6_reply(parm
.current
, if_index
, ifr
.ifr_name
, &parm
.fallback
,
194 sz
, IN6_IS_ADDR_MULTICAST(&from
.sin6_addr
), now
);
196 lease_update_file(now
);
200 /* The port in the source address of the original request should
201 be correct, but at least once client sends from the server port,
202 so we explicitly send to the client port to a client, and the
203 server port to a relay. */
206 from
.sin6_port
= htons(port
);
207 while (sendto(daemon
->dhcp6fd
, daemon
->outpacket
.iov_base
, save_counter(0),
208 0, (struct sockaddr
*)&from
, sizeof(from
)) == -1 &&
213 static int complete_context6(struct in6_addr
*local
, int prefix
,
214 int scope
, int if_index
, int flags
, unsigned int preferred
,
215 unsigned int valid
, void *vparam
)
217 struct dhcp_context
*context
;
218 struct dhcp_relay
*relay
;
219 struct iface_param
*param
= vparam
;
222 (void)scope
; /* warning */
224 if (if_index
== param
->ind
)
226 if (!IN6_IS_ADDR_LOOPBACK(local
) &&
227 !IN6_IS_ADDR_LINKLOCAL(local
) &&
228 !IN6_IS_ADDR_MULTICAST(local
))
230 /* if we have --listen-address config, see if the
231 arrival interface has a matching address. */
232 for (tmp
= daemon
->if_addrs
; tmp
; tmp
= tmp
->next
)
233 if (tmp
->addr
.sa
.sa_family
== AF_INET6
&&
234 IN6_ARE_ADDR_EQUAL(&tmp
->addr
.in6
.sin6_addr
, local
))
235 param
->addr_match
= 1;
237 /* Determine a globally address on the arrival interface, even
238 if we have no matching dhcp-context, because we're only
239 allocating on remote subnets via relays. This
240 is used as a default for the DNS server option. */
241 param
->fallback
= *local
;
243 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
245 if ((context
->flags
& CONTEXT_DHCP
) &&
246 !(context
->flags
& (CONTEXT_TEMPLATE
| CONTEXT_OLD
)) &&
247 prefix
== context
->prefix
&&
248 is_same_net6(local
, &context
->start6
, prefix
) &&
249 is_same_net6(local
, &context
->end6
, prefix
))
253 /* link it onto the current chain if we've not seen it before */
254 if (context
->current
== context
)
256 struct dhcp_context
*tmp
, **up
;
258 /* use interface values only for contructed contexts */
259 if (!(context
->flags
& CONTEXT_CONSTRUCTED
))
260 preferred
= valid
= 0xffffffff;
261 else if (flags
& IFACE_DEPRECATED
)
264 if (context
->flags
& CONTEXT_DEPRECATE
)
267 /* order chain, longest preferred time first */
268 for (up
= ¶m
->current
, tmp
= param
->current
; tmp
; tmp
= tmp
->current
)
269 if (tmp
->preferred
<= preferred
)
274 context
->current
= *up
;
276 context
->local6
= *local
;
277 context
->preferred
= preferred
;
278 context
->valid
= valid
;
284 for (relay
= daemon
->relay6
; relay
; relay
= relay
->next
)
285 if (IN6_ARE_ADDR_EQUAL(local
, &relay
->local
.addr
.addr6
) && relay
->current
== relay
&&
286 (IN6_IS_ADDR_UNSPECIFIED(¶m
->relay_local
) || IN6_ARE_ADDR_EQUAL(local
, ¶m
->relay_local
)))
288 relay
->current
= param
->relay
;
289 param
->relay
= relay
;
290 param
->relay_local
= *local
;
298 struct dhcp_config
*config_find_by_address6(struct dhcp_config
*configs
, struct in6_addr
*net
, int prefix
, u64 addr
)
300 struct dhcp_config
*config
;
302 for (config
= configs
; config
; config
= config
->next
)
303 if ((config
->flags
& CONFIG_ADDR6
) &&
304 is_same_net6(&config
->addr6
, net
, prefix
) &&
305 (prefix
== 128 || addr6part(&config
->addr6
) == addr
))
311 struct dhcp_context
*address6_allocate(struct dhcp_context
*context
, unsigned char *clid
, int clid_len
,
312 int iaid
, int serial
, struct dhcp_netid
*netids
, int plain_range
, struct in6_addr
*ans
)
314 /* Find a free address: exclude anything in use and anything allocated to
315 a particular hwaddr/clientid/hostname in our configuration.
316 Try to return from contexts which match netids first.
318 Note that we assume the address prefix lengths are 64 or greater, so we can
319 get by with 64 bit arithmetic.
323 struct dhcp_context
*c
, *d
;
327 /* hash hwaddr: use the SDBM hashing algorithm. This works
328 for MAC addresses, let's see how it manages with client-ids! */
329 for (j
= iaid
, i
= 0; i
< clid_len
; i
++)
330 j
+= clid
[i
] + (j
<< 6) + (j
<< 16) - j
;
332 for (pass
= 0; pass
<= plain_range
? 1 : 0; pass
++)
333 for (c
= context
; c
; c
= c
->current
)
334 if (c
->flags
& (CONTEXT_DEPRECATE
| CONTEXT_STATIC
| CONTEXT_RA_STATELESS
| CONTEXT_USED
))
336 else if (!match_netid(c
->filter
, netids
, pass
))
340 if (option_bool(OPT_CONSEC_ADDR
))
341 /* seed is largest extant lease addr in this context */
342 start
= lease_find_max_addr6(c
) + serial
;
344 start
= addr6part(&c
->start6
) + ((j
+ c
->addr_epoch
) % (1 + addr6part(&c
->end6
) - addr6part(&c
->start6
)));
346 /* iterate until we find a free address. */
350 /* eliminate addresses in use by the server. */
351 for (d
= context
; d
; d
= d
->current
)
352 if (addr
== addr6part(&d
->local6
))
356 !lease6_find_by_addr(&c
->start6
, c
->prefix
, addr
) &&
357 !config_find_by_address6(daemon
->dhcp_conf
, &c
->start6
, c
->prefix
, addr
))
360 setaddr6part (ans
, addr
);
366 if (addr
== addr6part(&c
->end6
) + 1)
367 addr
= addr6part(&c
->start6
);
369 } while (addr
!= start
);
375 /* can dynamically allocate addr */
376 struct dhcp_context
*address6_available(struct dhcp_context
*context
,
377 struct in6_addr
*taddr
,
378 struct dhcp_netid
*netids
,
381 u64 start
, end
, addr
= addr6part(taddr
);
382 struct dhcp_context
*tmp
;
384 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
386 start
= addr6part(&tmp
->start6
);
387 end
= addr6part(&tmp
->end6
);
389 if (!(tmp
->flags
& (CONTEXT_STATIC
| CONTEXT_RA_STATELESS
)) &&
390 is_same_net6(&tmp
->start6
, taddr
, tmp
->prefix
) &&
391 is_same_net6(&tmp
->end6
, taddr
, tmp
->prefix
) &&
394 match_netid(tmp
->filter
, netids
, plain_range
))
401 /* address OK if configured */
402 struct dhcp_context
*address6_valid(struct dhcp_context
*context
,
403 struct in6_addr
*taddr
,
404 struct dhcp_netid
*netids
,
407 struct dhcp_context
*tmp
;
409 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
410 if (is_same_net6(&tmp
->start6
, taddr
, tmp
->prefix
) &&
411 match_netid(tmp
->filter
, netids
, plain_range
))
417 int config_valid(struct dhcp_config
*config
, struct dhcp_context
*context
, struct in6_addr
*addr
)
419 if (!config
|| !(config
->flags
& CONFIG_ADDR6
))
422 if ((config
->flags
& CONFIG_WILDCARD
) && context
->prefix
== 64)
424 *addr
= context
->start6
;
425 setaddr6part(addr
, addr6part(&config
->addr6
));
429 if (is_same_net6(&context
->start6
, &config
->addr6
, context
->prefix
))
431 *addr
= config
->addr6
;
438 static int is_config_in_context6(struct dhcp_context
*context
, struct dhcp_config
*config
)
440 if (!(config
->flags
& CONFIG_ADDR6
) ||
441 (config
->flags
& CONFIG_WILDCARD
))
445 for (; context
; context
= context
->current
)
446 if (is_same_net6(&config
->addr6
, &context
->start6
, context
->prefix
))
453 struct dhcp_config
*find_config6(struct dhcp_config
*configs
,
454 struct dhcp_context
*context
,
455 unsigned char *duid
, int duid_len
,
458 struct dhcp_config
*config
;
461 for (config
= configs
; config
; config
= config
->next
)
462 if (config
->flags
& CONFIG_CLID
)
464 if (config
->clid_len
== duid_len
&&
465 memcmp(config
->clid
, duid
, duid_len
) == 0 &&
466 is_config_in_context6(context
, config
))
470 if (hostname
&& context
)
471 for (config
= configs
; config
; config
= config
->next
)
472 if ((config
->flags
& CONFIG_NAME
) &&
473 hostname_isequal(config
->hostname
, hostname
) &&
474 is_config_in_context6(context
, config
))
480 void make_duid(time_t now
)
482 if (daemon
->duid_config
)
486 daemon
->duid
= p
= safe_malloc(daemon
->duid_config_len
+ 6);
487 daemon
->duid_len
= daemon
->duid_config_len
+ 6;
488 PUTSHORT(2, p
); /* DUID_EN */
489 PUTLONG(daemon
->duid_enterprise
, p
);
490 memcpy(p
, daemon
->duid_config
, daemon
->duid_config_len
);
494 /* rebase epoch to 1/1/2000 */
495 time_t newnow
= now
- 946684800;
497 iface_enumerate(AF_LOCAL
, &newnow
, make_duid1
);
500 die("Cannot create DHCPv6 server DUID: %s", NULL
, EC_MISC
);
504 static int make_duid1(int index
, unsigned int type
, char *mac
, size_t maclen
, void *parm
)
506 /* create DUID as specified in RFC3315. We use the MAC of the
507 first interface we find that isn't loopback or P-to-P and
508 has address-type < 256. Address types above 256 are things like
509 tunnels which don't have usable MAC addresses. */
517 #ifdef HAVE_BROKEN_RTC
518 daemon
->duid
= p
= safe_malloc(maclen
+ 4);
519 daemon
->duid_len
= maclen
+ 4;
520 PUTSHORT(3, p
); /* DUID_LL */
521 PUTSHORT(type
, p
); /* address type */
523 daemon
->duid
= p
= safe_malloc(maclen
+ 8);
524 daemon
->duid_len
= maclen
+ 8;
525 PUTSHORT(1, p
); /* DUID_LLT */
526 PUTSHORT(type
, p
); /* address type */
527 PUTLONG(*((time_t *)parm
), p
); /* time */
530 memcpy(p
, mac
, maclen
);
540 static int construct_worker(struct in6_addr
*local
, int prefix
,
541 int scope
, int if_index
, int flags
,
542 int preferred
, int valid
, void *vparam
)
544 char ifrn_name
[IFNAMSIZ
];
545 struct in6_addr start6
, end6
;
546 struct dhcp_context
*template, *context
;
553 struct cparam
*param
= vparam
;
555 if (IN6_IS_ADDR_LOOPBACK(local
) ||
556 IN6_IS_ADDR_LINKLOCAL(local
) ||
557 IN6_IS_ADDR_MULTICAST(local
))
560 if (!indextoname(daemon
->doing_dhcp6
? daemon
->dhcp6fd
: daemon
->icmp6fd
, if_index
, ifrn_name
))
563 for (template = daemon
->dhcp6
; template; template = template->next
)
564 if (!(template->flags
& CONTEXT_TEMPLATE
))
566 /* non-template entries, just fill in interface and local addresses */
567 if (prefix
== template->prefix
&&
568 is_same_net6(local
, &template->start6
, prefix
) &&
569 is_same_net6(local
, &template->end6
, prefix
))
571 template->if_index
= if_index
;
572 template->local6
= *local
;
576 else if ((addr6part(local
) == addr6part(&template->start6
) ||
577 addr6part(local
) == addr6part(&template->end6
) ||
578 (IN6_IS_ADDR_UNSPECIFIED(&template->start6
) &&
579 IFACE_PERMANENT
== (flags
& (IFACE_PERMANENT
| IFACE_DEPRECATED
)))) &&
580 wildcard_match(template->template_interface
, ifrn_name
))
583 setaddr6part(&start6
, addr6part(&template->start6
));
585 setaddr6part(&end6
, addr6part(&template->end6
));
587 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
588 if ((context
->flags
& CONTEXT_CONSTRUCTED
) &&
589 IN6_ARE_ADDR_EQUAL(&start6
, &context
->start6
) &&
590 IN6_ARE_ADDR_EQUAL(&end6
, &context
->end6
))
592 int flags
= context
->flags
;
593 context
->flags
&= ~(CONTEXT_GC
| CONTEXT_OLD
);
594 if (flags
& CONTEXT_OLD
)
596 /* address went, now it's back */
597 log_context(AF_INET6
, context
);
598 /* fast RAs for a while */
599 ra_start_unsolicted(param
->now
, context
);
600 /* Add address to name again */
601 if (context
->flags
& CONTEXT_RA_NAME
)
607 if (!context
&& (context
= whine_malloc(sizeof (struct dhcp_context
))))
609 *context
= *template;
610 context
->start6
= start6
;
611 context
->end6
= end6
;
612 context
->flags
&= ~CONTEXT_TEMPLATE
;
613 context
->flags
|= CONTEXT_CONSTRUCTED
;
614 context
->if_index
= if_index
;
615 context
->local6
= *local
;
616 context
->saved_valid
= 0;
618 context
->next
= daemon
->dhcp6
;
619 daemon
->dhcp6
= context
;
621 ra_start_unsolicted(param
->now
, context
);
622 /* we created a new one, need to call
623 lease_update_file to get periodic functions called */
626 /* Will need to add new putative SLAAC addresses to existing leases */
627 if (context
->flags
& CONTEXT_RA_NAME
)
630 log_context(AF_INET6
, context
);
637 void dhcp_construct_contexts(time_t now
)
639 struct dhcp_context
*context
, *tmp
, **up
;
645 for (context
= daemon
->dhcp6
; context
; context
= context
->next
)
646 if (context
->flags
& CONTEXT_CONSTRUCTED
)
647 context
->flags
|= CONTEXT_GC
;
649 iface_enumerate(AF_INET6
, ¶m
, construct_worker
);
651 for (up
= &daemon
->dhcp6
, context
= daemon
->dhcp6
; context
; context
= tmp
)
656 if (context
->flags
& CONTEXT_GC
&& !(context
->flags
& CONTEXT_OLD
))
659 if ((context
->flags
& (CONTEXT_RA_ONLY
| CONTEXT_RA_NAME
| CONTEXT_RA_STATELESS
)) ||
662 /* previously constructed context has gone. advertise it's demise */
663 context
->flags
|= CONTEXT_OLD
;
664 context
->address_lost_time
= now
;
665 /* Apply same ceiling of configured lease time as in radv.c */
666 if (context
->saved_valid
> context
->lease_time
)
667 context
->saved_valid
= context
->lease_time
;
668 /* maximum time is 2 hours, from RFC */
669 if (context
->saved_valid
> 7200) /* 2 hours */
670 context
->saved_valid
= 7200;
671 ra_start_unsolicted(now
, context
);
672 param
.newone
= 1; /* include deletion */
674 if (context
->flags
& CONTEXT_RA_NAME
)
677 log_context(AF_INET6
, context
);
683 /* we were never doing RA for this, so free now */
694 if (daemon
->dhcp
|| daemon
->doing_dhcp6
)
697 lease_update_slaac(now
);
698 lease_update_file(now
);
701 /* Not doing DHCP, so no lease system, manage alarms for ra only */
702 send_alarm(periodic_ra(now
), now
);