1 /* dnsmasq is Copyright (c) 2000-2022 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 in6_addr fallback, ll_addr, ula_addr;
30 static int complete_context6(struct in6_addr *local, int prefix,
31 int scope, int if_index, int flags,
32 unsigned int preferred, unsigned int valid, void *vparam);
33 static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
38 struct sockaddr_in6 saddr;
39 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
40 int class = IPTOS_CLASS_CS6;
44 if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
45 #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
46 setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
48 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &oneopt, sizeof(oneopt)) == -1 ||
51 die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
53 /* When bind-interfaces is set, there might be more than one dnsmasq
54 instance binding port 547. That's OK if they serve different networks.
55 Need to set REUSEADDR|REUSEPORT to make this possible.
56 Handle the case that REUSEPORT is defined, but the kernel doesn't
57 support it. This handles the introduction of REUSEPORT on Linux. */
58 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
63 if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
69 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
72 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
75 memset(&saddr, 0, sizeof(saddr));
76 #ifdef HAVE_SOCKADDR_SA_LEN
77 saddr.sin6_len = sizeof(struct sockaddr_in6);
79 saddr.sin6_family = AF_INET6;
80 saddr.sin6_addr = in6addr_any;
81 saddr.sin6_port = htons(DHCPV6_SERVER_PORT);
83 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)))
84 die(_("failed to bind DHCPv6 server socket: %s"), NULL, EC_BADNET);
89 void dhcp6_packet(time_t now)
91 struct dhcp_context *context;
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;
105 struct in6_addr dst_addr;
106 struct in6_addr all_servers;
108 memset(&dst_addr, 0, sizeof(dst_addr));
110 msg.msg_control = control_u.control6;
111 msg.msg_controllen = sizeof(control_u);
113 msg.msg_name = &from;
114 msg.msg_namelen = sizeof(from);
115 msg.msg_iov = &daemon->dhcp_packet;
118 if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
122 dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
123 (union mysockaddr *)&from, NULL, daemon->dhcp6fd);
126 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
127 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
131 struct in6_pktinfo *p;
133 p.c = CMSG_DATA(cmptr);
135 if_index = p.p->ipi6_ifindex;
136 dst_addr = p.p->ipi6_addr;
139 if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
142 if (relay_reply6(&from, sz, ifr.ifr_name))
145 dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
146 (union mysockaddr *)&from, daemon->dhcp6fd);
149 while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
150 save_counter(-1), 0, (struct sockaddr *)&from,
155 struct dhcp_bridge *bridge, *alias;
157 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
158 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
161 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
162 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
168 memset(&parm.fallback, 0, IN6ADDRSZ);
169 memset(&parm.ll_addr, 0, IN6ADDRSZ);
170 memset(&parm.ula_addr, 0, IN6ADDRSZ);
172 /* If the interface on which the DHCPv6 request was received is
173 an alias of some other interface (as specified by the
174 --bridge-interface option), change parm.ind so that we look
175 for DHCPv6 contexts associated with the aliased interface
176 instead of with the aliasing one. */
177 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
179 for (alias = bridge->alias; alias; alias = alias->next)
180 if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
182 parm.ind = if_nametoindex(bridge->iface);
185 my_syslog(MS_DHCP | LOG_WARNING,
186 _("unknown interface %s in bridge-interface"),
196 for (context = daemon->dhcp6; context; context = context->next)
197 if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
199 /* wildcard context for DHCP-stateless only */
200 parm.current = context;
201 context->current = NULL;
205 /* unlinked contexts are marked by context->current == context */
206 context->current = context;
207 memset(&context->local6, 0, IN6ADDRSZ);
210 /* Ignore requests sent to the ALL_SERVERS multicast address for relay when
211 we're listening there for DHCPv6 server reasons. */
212 inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
214 if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
215 relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
218 if (!iface_enumerate(AF_INET6, &parm, complete_context6))
221 /* Check for a relay again after iface_enumerate/complete_context has had
222 chance to fill in relay->iface_index fields. This handles first time through
223 and any changes in interface config. */
224 if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
225 relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
228 if (daemon->if_names || daemon->if_addrs)
231 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
232 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
235 if (!tmp && !parm.addr_match)
239 /* May have configured relay, but not DHCP server */
240 if (!daemon->doing_dhcp6)
243 lease_prune(NULL, now); /* lose any expired leases */
245 port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
246 &parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
248 /* The port in the source address of the original request should
249 be correct, but at least once client sends from the server port,
250 so we explicitly send to the client port to a client, and the
251 server port to a relay. */
254 from.sin6_port = htons(port);
257 dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
258 NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
261 while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
262 save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from))));
265 /* These need to be called _after_ we send DHCPv6 packet, since lease_update_file()
266 may trigger sending an RA packet, which overwrites our buffer. */
267 lease_update_file(now);
272 void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
274 /* Receiving a packet from a host does not populate the neighbour
275 cache, so we send a neighbour discovery request if we can't
276 find the sender. Repeat a few times in case of packet loss. */
278 struct neigh_packet neigh;
279 union mysockaddr addr;
282 neigh.type = ND_NEIGHBOR_SOLICIT;
285 neigh.target = *client;
286 /* RFC4443 section-2.3: checksum has to be zero to be calculated */
289 memset(&addr, 0, sizeof(addr));
290 #ifdef HAVE_SOCKADDR_SA_LEN
291 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
293 addr.in6.sin6_family = AF_INET6;
294 addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
295 addr.in6.sin6_addr = *client;
296 addr.in6.sin6_scope_id = iface;
298 for (i = 0; i < 5; i++)
302 if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
305 while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr))));
308 ts.tv_nsec = 100000000; /* 100ms */
309 nanosleep(&ts, NULL);
313 *mactypep = ARPHRD_ETHER;
316 static int complete_context6(struct in6_addr *local, int prefix,
317 int scope, int if_index, int flags, unsigned int preferred,
318 unsigned int valid, void *vparam)
320 struct dhcp_context *context;
321 struct shared_network *share;
322 struct dhcp_relay *relay;
323 struct iface_param *param = vparam;
325 int match = !daemon->if_addrs;
327 (void)scope; /* warning */
329 if (if_index != param->ind)
332 if (IN6_IS_ADDR_LINKLOCAL(local))
333 param->ll_addr = *local;
334 else if (IN6_IS_ADDR_ULA(local))
335 param->ula_addr = *local;
337 if (IN6_IS_ADDR_LOOPBACK(local) ||
338 IN6_IS_ADDR_LINKLOCAL(local) ||
339 IN6_IS_ADDR_MULTICAST(local))
342 /* if we have --listen-address config, see if the
343 arrival interface has a matching address. */
344 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
345 if (tmp->addr.sa.sa_family == AF_INET6 &&
346 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
347 match = param->addr_match = 1;
349 /* Determine a globally address on the arrival interface, even
350 if we have no matching dhcp-context, because we're only
351 allocating on remote subnets via relays. This
352 is used as a default for the DNS server option. */
353 param->fallback = *local;
355 for (context = daemon->dhcp6; context; context = context->next)
356 if ((context->flags & CONTEXT_DHCP) &&
357 !(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
358 prefix <= context->prefix &&
359 context->current == context)
361 if (is_same_net6(local, &context->start6, context->prefix) &&
362 is_same_net6(local, &context->end6, context->prefix))
364 struct dhcp_context *tmp, **up;
366 /* use interface values only for constructed contexts */
367 if (!(context->flags & CONTEXT_CONSTRUCTED))
368 preferred = valid = 0xffffffff;
369 else if (flags & IFACE_DEPRECATED)
372 if (context->flags & CONTEXT_DEPRECATE)
375 /* order chain, longest preferred time first */
376 for (up = ¶m->current, tmp = param->current; tmp; tmp = tmp->current)
377 if (tmp->preferred <= preferred)
382 context->current = *up;
384 context->local6 = *local;
385 context->preferred = preferred;
386 context->valid = valid;
390 for (share = daemon->shared_networks; share; share = share->next)
392 /* IPv4 shared_address - ignore */
393 if (share->shared_addr.s_addr != 0)
396 if (share->if_index != 0)
398 if (share->if_index != if_index)
403 if (!IN6_ARE_ADDR_EQUAL(&share->match_addr6, local))
407 if (is_same_net6(&share->shared_addr6, &context->start6, context->prefix) &&
408 is_same_net6(&share->shared_addr6, &context->end6, context->prefix))
410 context->current = param->current;
411 param->current = context;
412 context->local6 = *local;
413 context->preferred = context->flags & CONTEXT_DEPRECATE ? 0 :0xffffffff;
414 context->valid = 0xffffffff;
421 for (relay = daemon->relay6; relay; relay = relay->next)
422 if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6))
423 relay->iface_index = if_index;
428 struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, struct in6_addr *addr)
430 struct dhcp_config *config;
432 for (config = configs; config; config = config->next)
433 if (config->flags & CONFIG_ADDR6)
435 struct addrlist *addr_list;
437 for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
438 if ((!net || is_same_net6(&addr_list->addr.addr6, net, prefix) || ((addr_list->flags & ADDRLIST_WILDCARD) && prefix == 64)) &&
439 is_same_net6(&addr_list->addr.addr6, addr, (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128))
446 struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
447 unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
449 /* Find a free address: exclude anything in use and anything allocated to
450 a particular hwaddr/clientid/hostname in our configuration.
451 Try to return from contexts which match netids first.
453 Note that we assume the address prefix lengths are 64 or greater, so we can
454 get by with 64 bit arithmetic.
458 struct dhcp_context *c, *d;
462 /* hash hwaddr: use the SDBM hashing algorithm. This works
463 for MAC addresses, let's see how it manages with client-ids!
464 For temporary addresses, we generate a new random one each time. */
468 for (j = iaid, i = 0; i < clid_len; i++)
469 j = clid[i] + (j << 6) + (j << 16) - j;
471 for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
472 for (c = context; c; c = c->current)
473 if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS | CONTEXT_USED))
475 else if (!match_netid(c->filter, netids, pass))
479 if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
481 /* seed is largest extant lease addr in this context,
482 skip addresses equal to the number of addresses rejected
483 by clients. This should avoid the same client being offered the same
484 address after it has rjected it. */
485 start = lease_find_max_addr6(c) + 1 + serial + c->addr_epoch;
491 u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
492 u64 offset = j + c->addr_epoch;
494 /* don't divide by zero if range is whole 2^64 */
496 offset = offset % range;
498 start = addr6part(&c->start6) + offset;
501 /* iterate until we find a free address. */
505 /* eliminate addresses in use by the server. */
506 for (d = context; d; d = d->current)
507 if (addr == addr6part(&d->local6))
511 setaddr6part (ans, addr);
514 !lease6_find_by_addr(&c->start6, c->prefix, addr) &&
515 !config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, ans))
520 if (addr == addr6part(&c->end6) + 1)
521 addr = addr6part(&c->start6);
523 } while (addr != start);
529 /* can dynamically allocate addr */
530 struct dhcp_context *address6_available(struct dhcp_context *context,
531 struct in6_addr *taddr,
532 struct dhcp_netid *netids,
535 u64 start, end, addr = addr6part(taddr);
536 struct dhcp_context *tmp;
538 for (tmp = context; tmp; tmp = tmp->current)
540 start = addr6part(&tmp->start6);
541 end = addr6part(&tmp->end6);
543 if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS)) &&
544 is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
545 is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
548 match_netid(tmp->filter, netids, plain_range))
555 /* address OK if configured */
556 struct dhcp_context *address6_valid(struct dhcp_context *context,
557 struct in6_addr *taddr,
558 struct dhcp_netid *netids,
561 struct dhcp_context *tmp;
563 for (tmp = context; tmp; tmp = tmp->current)
564 if (is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
565 match_netid(tmp->filter, netids, plain_range))
571 void make_duid(time_t now)
575 if (daemon->duid_config)
579 daemon->duid = p = safe_malloc(daemon->duid_config_len + 6);
580 daemon->duid_len = daemon->duid_config_len + 6;
581 PUTSHORT(2, p); /* DUID_EN */
582 PUTLONG(daemon->duid_enterprise, p);
583 memcpy(p, daemon->duid_config, daemon->duid_config_len);
589 /* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */
590 #ifndef HAVE_BROKEN_RTC
591 /* rebase epoch to 1/1/2000 */
592 if (!option_bool(OPT_LEASE_RO) || daemon->lease_change_command)
593 newnow = now - 946684800;
596 iface_enumerate(AF_LOCAL, &newnow, make_duid1);
599 die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
603 static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm)
605 /* create DUID as specified in RFC3315. We use the MAC of the
606 first interface we find that isn't loopback or P-to-P and
607 has address-type < 256. Address types above 256 are things like
608 tunnels which don't have usable MAC addresses. */
613 time_t newnow = *((time_t *)parm);
620 daemon->duid = p = safe_malloc(maclen + 4);
621 daemon->duid_len = maclen + 4;
622 PUTSHORT(3, p); /* DUID_LL */
623 PUTSHORT(type, p); /* address type */
627 daemon->duid = p = safe_malloc(maclen + 8);
628 daemon->duid_len = maclen + 8;
629 PUTSHORT(1, p); /* DUID_LLT */
630 PUTSHORT(type, p); /* address type */
631 PUTLONG(*((time_t *)parm), p); /* time */
634 memcpy(p, mac, maclen);
644 static int construct_worker(struct in6_addr *local, int prefix,
645 int scope, int if_index, int flags,
646 int preferred, int valid, void *vparam)
648 char ifrn_name[IFNAMSIZ];
649 struct in6_addr start6, end6;
650 struct dhcp_context *template, *context;
658 struct cparam *param = vparam;
660 if (IN6_IS_ADDR_LOOPBACK(local) ||
661 IN6_IS_ADDR_LINKLOCAL(local) ||
662 IN6_IS_ADDR_MULTICAST(local))
665 if (!(flags & IFACE_PERMANENT))
668 if (flags & IFACE_DEPRECATED)
671 /* Ignore interfaces where we're not doing RA/DHCP6 */
672 if (!indextoname(daemon->icmp6fd, if_index, ifrn_name) ||
673 !iface_check(AF_LOCAL, NULL, ifrn_name, NULL))
676 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
677 if (tmp->name && wildcard_match(tmp->name, ifrn_name))
680 for (template = daemon->dhcp6; template; template = template->next)
681 if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
683 /* non-template entries, just fill in interface and local addresses */
684 if (prefix <= template->prefix &&
685 is_same_net6(local, &template->start6, template->prefix) &&
686 is_same_net6(local, &template->end6, template->prefix))
688 /* First time found, do fast RA. */
689 if (template->if_index == 0)
691 ra_start_unsolicited(param->now, template);
695 template->if_index = if_index;
696 template->local6 = *local;
700 else if (wildcard_match(template->template_interface, ifrn_name) &&
701 template->prefix >= prefix)
704 setaddr6part(&start6, addr6part(&template->start6));
706 setaddr6part(&end6, addr6part(&template->end6));
708 for (context = daemon->dhcp6; context; context = context->next)
709 if (!(context->flags & CONTEXT_TEMPLATE) &&
710 IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
711 IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
713 /* If there's an absolute address context covering this address
714 then don't construct one as well. */
715 if (!(context->flags & CONTEXT_CONSTRUCTED))
718 if (context->if_index == if_index)
720 int cflags = context->flags;
721 context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
722 if (cflags & CONTEXT_OLD)
724 /* address went, now it's back, and on the same interface */
725 log_context(AF_INET6, context);
726 /* fast RAs for a while */
727 ra_start_unsolicited(param->now, context);
729 /* Add address to name again */
730 if (context->flags & CONTEXT_RA_NAME)
738 if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
740 *context = *template;
741 context->start6 = start6;
742 context->end6 = end6;
743 context->flags &= ~CONTEXT_TEMPLATE;
744 context->flags |= CONTEXT_CONSTRUCTED;
745 context->if_index = if_index;
746 context->local6 = *local;
747 context->saved_valid = 0;
749 context->next = daemon->dhcp6;
750 daemon->dhcp6 = context;
752 ra_start_unsolicited(param->now, context);
753 /* we created a new one, need to call
754 lease_update_file to get periodic functions called */
757 /* Will need to add new putative SLAAC addresses to existing leases */
758 if (context->flags & CONTEXT_RA_NAME)
761 log_context(AF_INET6, context);
768 void dhcp_construct_contexts(time_t now)
770 struct dhcp_context *context, *tmp, **up;
776 for (context = daemon->dhcp6; context; context = context->next)
777 if (context->flags & CONTEXT_CONSTRUCTED)
778 context->flags |= CONTEXT_GC;
780 iface_enumerate(AF_INET6, ¶m, construct_worker);
782 for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
787 if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
789 if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
791 /* previously constructed context has gone. advertise it's demise */
792 context->flags |= CONTEXT_OLD;
793 context->address_lost_time = now;
794 /* Apply same ceiling of configured lease time as in radv.c */
795 if (context->saved_valid > context->lease_time)
796 context->saved_valid = context->lease_time;
797 /* maximum time is 2 hours, from RFC */
798 if (context->saved_valid > 7200) /* 2 hours */
799 context->saved_valid = 7200;
800 ra_start_unsolicited(now, context);
801 param.newone = 1; /* include deletion */
803 if (context->flags & CONTEXT_RA_NAME)
806 log_context(AF_INET6, context);
812 /* we were never doing RA for this, so free now */
823 if (daemon->dhcp || daemon->doing_dhcp6)
826 lease_update_slaac(now);
827 lease_update_file(now);
830 /* Not doing DHCP, so no lease system, manage alarms for ra only */
831 send_alarm(periodic_ra(now), now);
835 #endif /* HAVE_DHCP6 */