Import dhcpcd-8.0.4 to vendor branch.
[dragonfly.git] / contrib / dhcpcd / src / dhcp6.c
blob3c22005c1a9b9eab244428f6ddc9a45c1b643b7c
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
5 * All rights reserved
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 /* TODO: We should decline dupliate addresses detected */
31 #include <sys/stat.h>
32 #include <sys/utsname.h>
34 #include <netinet/in.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <inttypes.h>
41 #include <stdbool.h>
42 #include <stddef.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <fcntl.h>
48 #define ELOOP_QUEUE 4
49 #include "config.h"
50 #include "common.h"
51 #include "dhcp.h"
52 #include "dhcp6.h"
53 #include "duid.h"
54 #include "eloop.h"
55 #include "if.h"
56 #include "if-options.h"
57 #include "ipv6nd.h"
58 #include "logerr.h"
59 #include "script.h"
61 #ifdef HAVE_SYS_BITOPS_H
62 #include <sys/bitops.h>
63 #else
64 #include "compat/bitops.h"
65 #endif
67 /* DHCPCD Project has been assigned an IANA PEN of 40712 */
68 #define DHCPCD_IANA_PEN 40712
70 /* Unsure if I want this */
71 //#define VENDOR_SPLIT
73 /* Support older systems with different defines */
74 #if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
75 #define IPV6_RECVPKTINFO IPV6_PKTINFO
76 #endif
78 #ifdef DHCP6
80 /* Assert the correct structure size for on wire */
81 struct dhcp6_message {
82 uint8_t type;
83 uint8_t xid[3];
84 /* followed by options */
86 __CTASSERT(sizeof(struct dhcp6_message) == 4);
88 struct dhcp6_option {
89 uint16_t code;
90 uint16_t len;
91 /* followed by data */
93 __CTASSERT(sizeof(struct dhcp6_option) == 4);
95 struct dhcp6_ia_na {
96 uint8_t iaid[4];
97 uint32_t t1;
98 uint32_t t2;
100 __CTASSERT(sizeof(struct dhcp6_ia_na) == 12);
102 struct dhcp6_ia_ta {
103 uint8_t iaid[4];
105 __CTASSERT(sizeof(struct dhcp6_ia_ta) == 4);
107 struct dhcp6_ia_addr {
108 struct in6_addr addr;
109 uint32_t pltime;
110 uint32_t vltime;
112 __CTASSERT(sizeof(struct dhcp6_ia_addr) == 16 + 8);
114 /* XXX FIXME: This is the only packed structure and it does not align.
115 * Maybe manually decode it? */
116 struct dhcp6_pd_addr {
117 uint32_t pltime;
118 uint32_t vltime;
119 uint8_t prefix_len;
120 struct in6_addr prefix;
121 } __packed;
122 __CTASSERT(sizeof(struct dhcp6_pd_addr) == 8 + 1 + 16);
124 struct dhcp6_op {
125 uint16_t type;
126 const char *name;
129 static const struct dhcp6_op dhcp6_ops[] = {
130 { DHCP6_SOLICIT, "SOLICIT6" },
131 { DHCP6_ADVERTISE, "ADVERTISE6" },
132 { DHCP6_REQUEST, "REQUEST6" },
133 { DHCP6_REPLY, "REPLY6" },
134 { DHCP6_RENEW, "RENEW6" },
135 { DHCP6_REBIND, "REBIND6" },
136 { DHCP6_CONFIRM, "CONFIRM6" },
137 { DHCP6_INFORMATION_REQ, "INFORM6" },
138 { DHCP6_RELEASE, "RELEASE6" },
139 { DHCP6_RECONFIGURE, "RECONFIGURE6" },
140 { 0, NULL }
143 struct dhcp_compat {
144 uint8_t dhcp_opt;
145 uint16_t dhcp6_opt;
148 const struct dhcp_compat dhcp_compats[] = {
149 { DHO_DNSSERVER, D6_OPTION_DNS_SERVERS },
150 { DHO_HOSTNAME, D6_OPTION_FQDN },
151 { DHO_DNSDOMAIN, D6_OPTION_FQDN },
152 { DHO_NISSERVER, D6_OPTION_NIS_SERVERS },
153 { DHO_NTPSERVER, D6_OPTION_SNTP_SERVERS },
154 { DHO_RAPIDCOMMIT, D6_OPTION_RAPID_COMMIT },
155 { DHO_FQDN, D6_OPTION_FQDN },
156 { DHO_VIVCO, D6_OPTION_VENDOR_CLASS },
157 { DHO_VIVSO, D6_OPTION_VENDOR_OPTS },
158 { DHO_DNSSEARCH, D6_OPTION_DOMAIN_LIST },
159 { 0, 0 }
162 static const char * const dhcp6_statuses[] = {
163 "Success",
164 "Unspecified Failure",
165 "No Addresses Available",
166 "No Binding",
167 "Not On Link",
168 "Use Multicast",
169 "No Prefix Available"
172 static void dhcp6_bind(struct interface *, const char *, const char *);
173 static void dhcp6_failinform(void *);
174 static int dhcp6_listen(struct dhcpcd_ctx *, struct ipv6_addr *);
175 static void dhcp6_recvaddr(void *);
177 void
178 dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
179 const struct dhcp_opt *opts, size_t opts_len)
181 size_t i, j;
182 const struct dhcp_opt *opt, *opt2;
183 int cols;
185 for (i = 0, opt = ctx->dhcp6_opts;
186 i < ctx->dhcp6_opts_len; i++, opt++)
188 for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
189 if (opt2->option == opt->option)
190 break;
191 if (j == opts_len) {
192 cols = printf("%05d %s", opt->option, opt->var);
193 dhcp_print_option_encoding(opt, cols);
196 for (i = 0, opt = opts; i < opts_len; i++, opt++) {
197 cols = printf("%05d %s", opt->option, opt->var);
198 dhcp_print_option_encoding(opt, cols);
202 static size_t
203 dhcp6_makeuser(void *data, const struct interface *ifp)
205 const struct if_options *ifo = ifp->options;
206 struct dhcp6_option o;
207 uint8_t *p;
208 const uint8_t *up, *ue;
209 uint16_t ulen, unlen;
210 size_t olen;
212 /* Convert the DHCPv4 user class option to DHCPv6 */
213 up = ifo->userclass;
214 ulen = *up++;
215 if (ulen == 0)
216 return 0;
218 p = data;
219 olen = 0;
220 if (p != NULL)
221 p += sizeof(o);
223 ue = up + ulen;
224 for (; up < ue; up += ulen) {
225 ulen = *up++;
226 olen += sizeof(ulen) + ulen;
227 if (data == NULL)
228 continue;
229 unlen = htons(ulen);
230 memcpy(p, &unlen, sizeof(unlen));
231 p += sizeof(unlen);
232 memcpy(p, up, ulen);
233 p += ulen;
235 if (data != NULL) {
236 o.code = htons(D6_OPTION_USER_CLASS);
237 o.len = htons((uint16_t)olen);
238 memcpy(data, &o, sizeof(o));
241 return sizeof(o) + olen;
244 static size_t
245 dhcp6_makevendor(void *data, const struct interface *ifp)
247 const struct if_options *ifo;
248 size_t len, i;
249 uint8_t *p;
250 ssize_t vlen;
251 const struct vivco *vivco;
252 char vendor[VENDORCLASSID_MAX_LEN];
253 struct dhcp6_option o;
255 ifo = ifp->options;
256 len = sizeof(uint32_t); /* IANA PEN */
257 if (ifo->vivco_en) {
258 for (i = 0, vivco = ifo->vivco;
259 i < ifo->vivco_len;
260 i++, vivco++)
261 len += sizeof(uint16_t) + vivco->len;
262 vlen = 0; /* silence bogus gcc warning */
263 } else {
264 vlen = dhcp_vendor(vendor, sizeof(vendor));
265 if (vlen == -1)
266 vlen = 0;
267 else
268 len += sizeof(uint16_t) + (size_t)vlen;
271 if (len > UINT16_MAX) {
272 logerrx("%s: DHCPv6 Vendor Class too big", ifp->name);
273 return 0;
276 if (data != NULL) {
277 uint32_t pen;
278 uint16_t hvlen;
280 p = data;
281 o.code = htons(D6_OPTION_VENDOR_CLASS);
282 o.len = htons((uint16_t)len);
283 memcpy(p, &o, sizeof(o));
284 p += sizeof(o);
285 pen = htonl(ifo->vivco_en ? ifo->vivco_en : DHCPCD_IANA_PEN);
286 memcpy(p, &pen, sizeof(pen));
287 p += sizeof(pen);
289 if (ifo->vivco_en) {
290 for (i = 0, vivco = ifo->vivco;
291 i < ifo->vivco_len;
292 i++, vivco++)
294 hvlen = htons((uint16_t)vivco->len);
295 memcpy(p, &hvlen, sizeof(hvlen));
296 p += sizeof(hvlen);
297 memcpy(p, vivco->data, vivco->len);
298 p += vivco->len;
300 } else if (vlen) {
301 hvlen = htons((uint16_t)vlen);
302 memcpy(p, &hvlen, sizeof(hvlen));
303 p += sizeof(hvlen);
304 memcpy(p, vendor, (size_t)vlen);
308 return sizeof(o) + len;
311 static void *
312 dhcp6_findoption(void *data, size_t data_len, uint16_t code, uint16_t *len)
314 uint8_t *d;
315 struct dhcp6_option o;
317 code = htons(code);
318 for (d = data; data_len != 0; d += o.len, data_len -= o.len) {
319 if (data_len < sizeof(o)) {
320 errno = EINVAL;
321 return NULL;
323 memcpy(&o, d, sizeof(o));
324 d += sizeof(o);
325 data_len -= sizeof(o);
326 o.len = htons(o.len);
327 if (data_len < o.len) {
328 errno = EINVAL;
329 return NULL;
331 if (o.code == code) {
332 if (len != NULL)
333 *len = o.len;
334 return d;
338 errno = ENOENT;
339 return NULL;
342 static void *
343 dhcp6_findmoption(void *data, size_t data_len, uint16_t code,
344 uint16_t *len)
346 uint8_t *d;
348 if (data_len < sizeof(struct dhcp6_message)) {
349 errno = EINVAL;
350 return false;
352 d = data;
353 d += sizeof(struct dhcp6_message);
354 data_len -= sizeof(struct dhcp6_message);
355 return dhcp6_findoption(d, data_len, code, len);
358 static const uint8_t *
359 dhcp6_getoption(struct dhcpcd_ctx *ctx,
360 size_t *os, unsigned int *code, size_t *len,
361 const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
363 struct dhcp6_option o;
364 size_t i;
365 struct dhcp_opt *opt;
367 if (od != NULL) {
368 *os = sizeof(o);
369 if (ol < *os) {
370 errno = EINVAL;
371 return NULL;
373 memcpy(&o, od, sizeof(o));
374 *len = ntohs(o.len);
375 if (*len > ol - *os) {
376 errno = ERANGE;
377 return NULL;
379 *code = ntohs(o.code);
382 *oopt = NULL;
383 for (i = 0, opt = ctx->dhcp6_opts;
384 i < ctx->dhcp6_opts_len; i++, opt++)
386 if (opt->option == *code) {
387 *oopt = opt;
388 break;
392 if (od != NULL)
393 return od + sizeof(o);
394 return NULL;
397 static bool
398 dhcp6_updateelapsed(struct interface *ifp, struct dhcp6_message *m, size_t len)
400 uint8_t *opt;
401 uint16_t opt_len;
402 struct dhcp6_state *state;
403 struct timespec tv;
404 time_t hsec;
405 uint16_t sec;
407 opt = dhcp6_findmoption(m, len, D6_OPTION_ELAPSED, &opt_len);
408 if (opt == NULL)
409 return false;
410 if (opt_len != sizeof(sec)) {
411 errno = EINVAL;
412 return false;
415 state = D6_STATE(ifp);
416 clock_gettime(CLOCK_MONOTONIC, &tv);
417 if (state->RTC == 0) {
418 /* An RTC of zero means we're the first message
419 * out of the door, so the elapsed time is zero. */
420 state->started = tv;
421 hsec = 0;
422 } else {
423 timespecsub(&tv, &state->started, &tv);
424 /* Elapsed time is measured in centiseconds.
425 * We need to be sure it will not potentially overflow. */
426 if (tv.tv_sec >= (UINT16_MAX / CSEC_PER_SEC) + 1)
427 hsec = UINT16_MAX;
428 else {
429 hsec = (tv.tv_sec * CSEC_PER_SEC) +
430 (tv.tv_nsec / NSEC_PER_CSEC);
431 if (hsec > UINT16_MAX)
432 hsec = UINT16_MAX;
435 sec = htons((uint16_t)hsec);
436 memcpy(opt, &sec, sizeof(sec));
437 return true;
440 static void
441 dhcp6_newxid(const struct interface *ifp, struct dhcp6_message *m)
443 const struct interface *ifp1;
444 const struct dhcp6_state *state1;
445 uint32_t xid;
447 if (ifp->options->options & DHCPCD_XID_HWADDR &&
448 ifp->hwlen >= sizeof(xid))
449 /* The lower bits are probably more unique on the network */
450 memcpy(&xid, (ifp->hwaddr + ifp->hwlen) - sizeof(xid),
451 sizeof(xid));
452 else {
453 again:
454 xid = arc4random();
457 m->xid[0] = (xid >> 16) & 0xff;
458 m->xid[1] = (xid >> 8) & 0xff;
459 m->xid[2] = xid & 0xff;
461 /* Ensure it's unique */
462 TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
463 if (ifp == ifp1)
464 continue;
465 if ((state1 = D6_CSTATE(ifp1)) == NULL)
466 continue;
467 if (state1->send != NULL &&
468 state1->send->xid[0] == m->xid[0] &&
469 state1->send->xid[1] == m->xid[1] &&
470 state1->send->xid[2] == m->xid[2])
471 break;
474 if (ifp1 != NULL) {
475 if (ifp->options->options & DHCPCD_XID_HWADDR &&
476 ifp->hwlen >= sizeof(xid))
478 logerrx("%s: duplicate xid on %s",
479 ifp->name, ifp1->name);
480 return;
482 goto again;
486 #ifndef SMALL
487 static const struct if_sla *
488 dhcp6_findselfsla(struct interface *ifp)
490 size_t i, j;
491 struct if_ia *ia;
493 for (i = 0; i < ifp->options->ia_len; i++) {
494 ia = &ifp->options->ia[i];
495 if (ia->ia_type != D6_OPTION_IA_PD)
496 continue;
497 for (j = 0; j < ia->sla_len; j++) {
498 if (strcmp(ia->sla[j].ifname, ifp->name) == 0)
499 return &ia->sla[j];
502 return NULL;
505 static int
506 dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
507 const struct ipv6_addr *prefix, const struct if_sla *sla, struct if_ia *ia)
509 struct dhcp6_state *state;
510 struct if_sla asla;
511 char sabuf[INET6_ADDRSTRLEN];
512 const char *sa;
514 state = D6_STATE(ifp);
515 if (state == NULL) {
516 ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
517 state = D6_STATE(ifp);
518 if (state == NULL) {
519 logerr(__func__);
520 return -1;
523 TAILQ_INIT(&state->addrs);
524 state->state = DH6S_DELEGATED;
525 state->reason = "DELEGATED6";
528 if (sla == NULL || sla->sla_set == 0) {
529 /* No SLA set, so make an assumption of
530 * desired SLA and prefix length. */
531 asla.sla = ifp->index;
532 asla.prefix_len = 0;
533 asla.sla_set = 0;
534 sla = &asla;
535 } else if (sla->sla == 0 && sla->prefix_len == 0) {
536 /* An SLA of 0 was set with no prefix length specified.
537 * This means we delegate the whole prefix. */
538 asla.sla = sla->sla;
539 asla.prefix_len = prefix->prefix_len;
540 asla.sla_set = 0;
541 sla = &asla;
542 } else if (sla->prefix_len == 0) {
543 /* An SLA was given, but prefix length was not.
544 * We need to work out a suitable prefix length for
545 * potentially more than one interface. */
546 asla.sla = sla->sla;
547 asla.prefix_len = 0;
548 asla.sla_set = 0;
549 sla = &asla;
552 if (sla->prefix_len == 0) {
553 uint32_t sla_max;
554 int bits;
556 if (ia->sla_max == 0) {
557 const struct interface *ifi;
559 sla_max = 0;
560 TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
561 if (ifi->index > sla_max)
562 sla_max = ifi->index;
564 } else
565 sla_max = ia->sla_max;
567 bits = fls32(sla_max);
569 if (prefix->prefix_len + bits > (int)UINT8_MAX)
570 asla.prefix_len = UINT8_MAX;
571 else {
572 asla.prefix_len = (uint8_t)(prefix->prefix_len + bits);
574 /* Make a 64 prefix by default, as this makes SLAAC
575 * possible.
576 * Otherwise round up to the nearest 4 bits. */
577 if (asla.prefix_len <= 64)
578 asla.prefix_len = 64;
579 else
580 asla.prefix_len =
581 (uint8_t)ROUNDUP4(asla.prefix_len);
584 #define BIT(n) (1UL << (n))
585 #define BIT_MASK(len) (BIT(len) - 1)
586 if (ia->sla_max == 0) {
587 /* Work out the real sla_max from our bits used */
588 bits = asla.prefix_len - prefix->prefix_len;
589 /* Make static analysis happy.
590 * Bits cannot be bigger than 32 thanks to fls32. */
591 assert(bits <= 32);
592 ia->sla_max = (uint32_t)BIT_MASK(bits);
596 if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
597 sla->sla, addr, sla->prefix_len) == -1)
599 sa = inet_ntop(AF_INET6, &prefix->prefix,
600 sabuf, sizeof(sabuf));
601 logerr("%s: invalid prefix %s/%d + %d/%d",
602 ifp->name, sa, prefix->prefix_len,
603 sla->sla, sla->prefix_len);
604 return -1;
607 if (prefix->prefix_exclude_len &&
608 IN6_ARE_ADDR_EQUAL(addr, &prefix->prefix_exclude))
610 sa = inet_ntop(AF_INET6, &prefix->prefix_exclude,
611 sabuf, sizeof(sabuf));
612 logerrx("%s: cannot delegate excluded prefix %s/%d",
613 ifp->name, sa, prefix->prefix_exclude_len);
614 return -1;
617 return sla->prefix_len;
619 #endif
621 static int
622 dhcp6_makemessage(struct interface *ifp)
624 struct dhcp6_state *state;
625 struct dhcp6_message *m;
626 struct dhcp6_option o;
627 uint8_t *p, *si, *unicast, IA;
628 size_t n, l, len, ml, hl;
629 uint8_t type;
630 uint16_t si_len, uni_len, n_options;
631 uint8_t *o_lenp;
632 struct if_options *ifo;
633 const struct dhcp_opt *opt, *opt2;
634 const struct ipv6_addr *ap;
635 char hbuf[HOSTNAME_MAX_LEN + 1];
636 const char *hostname;
637 int fqdn;
638 struct dhcp6_ia_na ia_na;
639 uint16_t ia_na_len;
640 struct if_ia *ifia;
641 #ifdef AUTH
642 uint16_t auth_len;
643 #endif
645 state = D6_STATE(ifp);
646 if (state->send) {
647 free(state->send);
648 state->send = NULL;
651 ifo = ifp->options;
652 fqdn = ifo->fqdn;
654 if (fqdn == FQDN_DISABLE && ifo->options & DHCPCD_HOSTNAME) {
655 /* We're sending the DHCPv4 hostname option, so send FQDN as
656 * DHCPv6 has no FQDN option and DHCPv4 must not send
657 * hostname and FQDN according to RFC4702 */
658 fqdn = FQDN_BOTH;
660 if (fqdn != FQDN_DISABLE)
661 hostname = dhcp_get_hostname(hbuf, sizeof(hbuf), ifo);
662 else
663 hostname = NULL; /* appearse gcc */
665 /* Work out option size first */
666 n_options = 0;
667 len = 0;
668 si = NULL;
669 hl = 0; /* Appease gcc */
670 if (state->state != DH6S_RELEASE) {
671 for (l = 0, opt = ifp->ctx->dhcp6_opts;
672 l < ifp->ctx->dhcp6_opts_len;
673 l++, opt++)
675 for (n = 0, opt2 = ifo->dhcp6_override;
676 n < ifo->dhcp6_override_len;
677 n++, opt2++)
679 if (opt->option == opt2->option)
680 break;
682 if (n < ifo->dhcp6_override_len)
683 continue;
684 if (!(opt->type & OT_NOREQ) &&
685 (opt->type & OT_REQUEST ||
686 has_option_mask(ifo->requestmask6, opt->option)))
688 n_options++;
689 len += sizeof(o.len);
692 #ifndef SMALL
693 for (l = 0, opt = ifo->dhcp6_override;
694 l < ifo->dhcp6_override_len;
695 l++, opt++)
697 if (!(opt->type & OT_NOREQ) &&
698 (opt->type & OT_REQUEST ||
699 has_option_mask(ifo->requestmask6, opt->option)))
701 n_options++;
702 len += sizeof(o.len);
705 if (dhcp6_findselfsla(ifp)) {
706 n_options++;
707 len += sizeof(o.len);
709 #endif
710 if (len)
711 len += sizeof(o);
713 if (fqdn != FQDN_DISABLE) {
714 hl = encode_rfc1035(hostname, NULL);
715 len += sizeof(o) + 1 + hl;
718 if (ifo->mudurl[0])
719 len += sizeof(o) + ifo->mudurl[0];
721 #ifdef AUTH
722 if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
723 DHCPCD_AUTH_SENDREQUIRE)
724 len += sizeof(o); /* Reconfigure Accept */
725 #endif
728 len += sizeof(*state->send);
729 len += sizeof(o) + ifp->ctx->duid_len;
730 len += sizeof(o) + sizeof(uint16_t); /* elapsed */
731 if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
732 len += dhcp6_makeuser(NULL, ifp);
733 if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
734 len += dhcp6_makevendor(NULL, ifp);
736 /* IA */
737 m = NULL;
738 ml = 0;
739 switch(state->state) {
740 case DH6S_REQUEST:
741 m = state->recv;
742 ml = state->recv_len;
743 /* FALLTHROUGH */
744 case DH6S_RELEASE:
745 /* FALLTHROUGH */
746 case DH6S_RENEW:
747 if (m == NULL) {
748 m = state->new;
749 ml = state->new_len;
751 si = dhcp6_findmoption(m, ml, D6_OPTION_SERVERID, &si_len);
752 if (si == NULL)
753 return -1;
754 len += sizeof(o) + si_len;
755 /* FALLTHROUGH */
756 case DH6S_REBIND:
757 /* FALLTHROUGH */
758 case DH6S_CONFIRM:
759 /* FALLTHROUGH */
760 case DH6S_DISCOVER:
761 if (m == NULL) {
762 m = state->new;
763 ml = state->new_len;
765 TAILQ_FOREACH(ap, &state->addrs, next) {
766 if (ap->flags & IPV6_AF_STALE)
767 continue;
768 if (ap->prefix_vltime == 0 &&
769 !(ap->flags & IPV6_AF_REQUEST))
770 continue;
771 if (ap->ia_type == D6_OPTION_IA_PD) {
772 #ifndef SMALL
773 len += sizeof(o) + sizeof(struct dhcp6_pd_addr);
774 if (ap->prefix_exclude_len)
775 len += sizeof(o) + 1 +
776 (uint8_t)((ap->prefix_exclude_len -
777 ap->prefix_len - 1) / NBBY) + 1;
778 #endif
779 } else
780 len += sizeof(o) + sizeof(struct dhcp6_ia_addr);
782 /* FALLTHROUGH */
783 case DH6S_INIT:
784 for (l = 0; l < ifo->ia_len; l++) {
785 len += sizeof(o) + sizeof(uint32_t); /* IAID */
786 /* IA_TA does not have T1 or T2 timers */
787 if (ifo->ia[l].ia_type != D6_OPTION_IA_TA)
788 len += sizeof(uint32_t) + sizeof(uint32_t);
790 IA = 1;
791 break;
792 default:
793 IA = 0;
796 if (state->state == DH6S_DISCOVER &&
797 !(ifp->ctx->options & DHCPCD_TEST) &&
798 has_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT))
799 len += sizeof(o);
801 if (m == NULL) {
802 m = state->new;
803 ml = state->new_len;
806 switch(state->state) {
807 case DH6S_INIT: /* FALLTHROUGH */
808 case DH6S_DISCOVER:
809 type = DHCP6_SOLICIT;
810 break;
811 case DH6S_REQUEST:
812 type = DHCP6_REQUEST;
813 break;
814 case DH6S_CONFIRM:
815 type = DHCP6_CONFIRM;
816 break;
817 case DH6S_REBIND:
818 type = DHCP6_REBIND;
819 break;
820 case DH6S_RENEW:
821 type = DHCP6_RENEW;
822 break;
823 case DH6S_INFORM:
824 type = DHCP6_INFORMATION_REQ;
825 break;
826 case DH6S_RELEASE:
827 type = DHCP6_RELEASE;
828 break;
829 default:
830 errno = EINVAL;
831 return -1;
834 switch(state->state) {
835 case DH6S_REQUEST: /* FALLTHROUGH */
836 case DH6S_RENEW: /* FALLTHROUGH */
837 case DH6S_RELEASE:
838 if (has_option_mask(ifo->nomask6, D6_OPTION_UNICAST)) {
839 unicast = NULL;
840 break;
842 unicast = dhcp6_findmoption(m, ml, D6_OPTION_UNICAST, &uni_len);
843 break;
844 default:
845 unicast = NULL;
846 break;
849 /* In non master mode we listen and send from fixed addresses.
850 * We should try and match an address we have to unicast to,
851 * but for now this is the safest policy. */
852 if (unicast != NULL && !(ifp->ctx->options & DHCPCD_MASTER)) {
853 logdebugx("%s: ignoring unicast option as not master",
854 ifp->name);
855 unicast = NULL;
858 #ifdef AUTH
859 auth_len = 0;
860 if (ifo->auth.options & DHCPCD_AUTH_SEND) {
861 ssize_t alen = dhcp_auth_encode(&ifo->auth,
862 state->auth.token, NULL, 0, 6, type, NULL, 0);
863 if (alen != -1 && alen > UINT16_MAX) {
864 errno = ERANGE;
865 alen = -1;
867 if (alen == -1)
868 logerr("%s: %s: dhcp_auth_encode", __func__, ifp->name);
869 else if (alen != 0) {
870 auth_len = (uint16_t)alen;
871 len += sizeof(o) + auth_len;
874 #endif
876 state->send = malloc(len);
877 if (state->send == NULL)
878 return -1;
880 state->send_len = len;
881 state->send->type = type;
883 /* If we found a unicast option, copy it to our state for sending */
884 if (unicast && uni_len == sizeof(state->unicast))
885 memcpy(&state->unicast, unicast, sizeof(state->unicast));
886 else
887 state->unicast = in6addr_any;
889 dhcp6_newxid(ifp, state->send);
891 #define COPYIN1(_code, _len) { \
892 o.code = htons((_code)); \
893 o.len = htons((_len)); \
894 memcpy(p, &o, sizeof(o)); \
895 p += sizeof(o); \
897 #define COPYIN(_code, _data, _len) { \
898 COPYIN1((_code), (_len)); \
899 if ((_len) != 0) { \
900 memcpy(p, (_data), (_len)); \
901 p += (_len); \
904 #define NEXTLEN (p + offsetof(struct dhcp6_option, len))
906 p = (uint8_t *)state->send + sizeof(*state->send);
907 COPYIN(D6_OPTION_CLIENTID, ifp->ctx->duid,
908 (uint16_t)ifp->ctx->duid_len);
910 if (si != NULL)
911 COPYIN(D6_OPTION_SERVERID, si, si_len);
913 si_len = 0;
914 COPYIN(D6_OPTION_ELAPSED, &si_len, sizeof(si_len));
916 if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
917 p += dhcp6_makeuser(p, ifp);
918 if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
919 p += dhcp6_makevendor(p, ifp);
921 if (state->state == DH6S_DISCOVER &&
922 !(ifp->ctx->options & DHCPCD_TEST) &&
923 has_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT))
924 COPYIN1(D6_OPTION_RAPID_COMMIT, 0);
926 for (l = 0; IA && l < ifo->ia_len; l++) {
927 ifia = &ifo->ia[l];
928 o_lenp = NEXTLEN;
929 /* TA structure is the same as the others,
930 * it just lacks the T1 and T2 timers.
931 * These happen to be at the end of the struct,
932 * so we just don't copy them in. */
933 if (ifia->ia_type == D6_OPTION_IA_TA)
934 ia_na_len = sizeof(struct dhcp6_ia_ta);
935 else
936 ia_na_len = sizeof(ia_na);
937 memcpy(ia_na.iaid, ifia->iaid, sizeof(ia_na.iaid));
938 ia_na.t1 = 0;
939 ia_na.t2 = 0;
940 COPYIN(ifia->ia_type, &ia_na, ia_na_len);
941 TAILQ_FOREACH(ap, &state->addrs, next) {
942 if (ap->flags & IPV6_AF_STALE)
943 continue;
944 if (ap->prefix_vltime == 0 &&
945 !(ap->flags & IPV6_AF_REQUEST))
946 continue;
947 if (ap->ia_type != ifia->ia_type)
948 continue;
949 if (memcmp(ap->iaid, ifia->iaid, sizeof(ap->iaid)))
950 continue;
951 if (ap->ia_type == D6_OPTION_IA_PD) {
952 #ifndef SMALL
953 struct dhcp6_pd_addr pdp;
955 pdp.pltime = htonl(ap->prefix_pltime);
956 pdp.vltime = htonl(ap->prefix_vltime);
957 pdp.prefix_len = ap->prefix_len;
958 /* pdp.prefix is not aligned, so copy it in. */
959 memcpy(&pdp.prefix, &ap->prefix, sizeof(pdp.prefix));
960 COPYIN(D6_OPTION_IAPREFIX, &pdp, sizeof(pdp));
961 ia_na_len = (uint16_t)
962 (ia_na_len + sizeof(o) + sizeof(pdp));
964 /* RFC6603 Section 4.2 */
965 if (ap->prefix_exclude_len) {
966 uint8_t exb[16], *ep, u8;
967 const uint8_t *pp;
969 n = (size_t)((ap->prefix_exclude_len -
970 ap->prefix_len - 1) / NBBY) + 1;
971 ep = exb;
972 *ep++ = (uint8_t)ap->prefix_exclude_len;
973 pp = ap->prefix_exclude.s6_addr;
974 pp += (size_t)
975 ((ap->prefix_len - 1) / NBBY) +
976 (n - 1);
977 u8 = ap->prefix_len % NBBY;
978 if (u8)
979 n--;
980 while (n-- > 0)
981 *ep++ = *pp--;
982 if (u8)
983 *ep = (uint8_t)(*pp << u8);
984 n++;
985 COPYIN(D6_OPTION_PD_EXCLUDE, exb,
986 (uint16_t)n);
987 ia_na_len = (uint16_t)
988 (ia_na_len + sizeof(o) + n);
990 #endif
991 } else {
992 struct dhcp6_ia_addr ia;
994 ia.addr = ap->addr;
995 ia.pltime = htonl(ap->prefix_pltime);
996 ia.vltime = htonl(ap->prefix_vltime);
997 COPYIN(D6_OPTION_IA_ADDR, &ia, sizeof(ia));
998 ia_na_len = (uint16_t)
999 (ia_na_len + sizeof(o) + sizeof(ia));
1003 /* Update the total option lenth. */
1004 ia_na_len = htons(ia_na_len);
1005 memcpy(o_lenp, &ia_na_len, sizeof(ia_na_len));
1008 if (state->send->type != DHCP6_RELEASE) {
1009 if (fqdn != FQDN_DISABLE) {
1010 o_lenp = NEXTLEN;
1011 COPYIN1(D6_OPTION_FQDN, 0);
1012 if (hl == 0)
1013 *p = D6_FQDN_NONE;
1014 else {
1015 switch (fqdn) {
1016 case FQDN_BOTH:
1017 *p = D6_FQDN_BOTH;
1018 break;
1019 case FQDN_PTR:
1020 *p = D6_FQDN_PTR;
1021 break;
1022 default:
1023 *p = D6_FQDN_NONE;
1024 break;
1027 p++;
1028 encode_rfc1035(hostname, p);
1029 p += hl;
1030 o.len = htons((uint16_t)(hl + 1));
1031 memcpy(o_lenp, &o.len, sizeof(o.len));
1034 if (ifo->mudurl[0])
1035 COPYIN(D6_OPTION_MUDURL,
1036 ifo->mudurl + 1, ifo->mudurl[0]);
1038 #ifdef AUTH
1039 if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
1040 DHCPCD_AUTH_SENDREQUIRE)
1041 COPYIN1(D6_OPTION_RECONF_ACCEPT, 0);
1042 #endif
1044 if (n_options) {
1045 o_lenp = NEXTLEN;
1046 o.len = 0;
1047 COPYIN1(D6_OPTION_ORO, 0);
1048 for (l = 0, opt = ifp->ctx->dhcp6_opts;
1049 l < ifp->ctx->dhcp6_opts_len;
1050 l++, opt++)
1052 #ifndef SMALL
1053 for (n = 0, opt2 = ifo->dhcp6_override;
1054 n < ifo->dhcp6_override_len;
1055 n++, opt2++)
1057 if (opt->option == opt2->option)
1058 break;
1060 if (n < ifo->dhcp6_override_len)
1061 continue;
1062 #endif
1063 if (!(opt->type & OT_NOREQ) &&
1064 (opt->type & OT_REQUEST ||
1065 has_option_mask(ifo->requestmask6,
1066 opt->option)))
1068 o.code = htons((uint16_t)opt->option);
1069 memcpy(p, &o.code, sizeof(o.code));
1070 p += sizeof(o.code);
1071 o.len = (uint16_t)
1072 (o.len + sizeof(o.code));
1075 #ifndef SMALL
1076 for (l = 0, opt = ifo->dhcp6_override;
1077 l < ifo->dhcp6_override_len;
1078 l++, opt++)
1080 if (!(opt->type & OT_NOREQ) &&
1081 (opt->type & OT_REQUEST ||
1082 has_option_mask(ifo->requestmask6,
1083 opt->option)))
1085 o.code = htons((uint16_t)opt->option);
1086 memcpy(p, &o.code, sizeof(o.code));
1087 p += sizeof(o.code);
1088 o.len = (uint16_t)
1089 (o.len + sizeof(o.code));
1092 if (dhcp6_findselfsla(ifp)) {
1093 o.code = htons(D6_OPTION_PD_EXCLUDE);
1094 memcpy(p, &o.code, sizeof(o.code));
1095 p += sizeof(o.code);
1096 o.len = (uint16_t)(o.len + sizeof(o.code));
1098 #endif
1099 o.len = htons(o.len);
1100 memcpy(o_lenp, &o.len, sizeof(o.len));
1104 #ifdef AUTH
1105 /* This has to be the last option */
1106 if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0) {
1107 COPYIN1(D6_OPTION_AUTH, auth_len);
1108 /* data will be filled at send message time */
1110 #endif
1112 return 0;
1115 static const char *
1116 dhcp6_get_op(uint16_t type)
1118 const struct dhcp6_op *d;
1120 for (d = dhcp6_ops; d->name; d++)
1121 if (d->type == type)
1122 return d->name;
1123 return NULL;
1126 static void
1127 dhcp6_freedrop_addrs(struct interface *ifp, int drop,
1128 const struct interface *ifd)
1130 struct dhcp6_state *state;
1132 state = D6_STATE(ifp);
1133 if (state) {
1134 ipv6_freedrop_addrs(&state->addrs, drop, ifd);
1135 if (drop)
1136 rt_build(ifp->ctx, AF_INET6);
1140 #ifndef SMALL
1141 static void dhcp6_delete_delegates(struct interface *ifp)
1143 struct interface *ifp0;
1145 if (ifp->ctx->ifaces) {
1146 TAILQ_FOREACH(ifp0, ifp->ctx->ifaces, next) {
1147 if (ifp0 != ifp)
1148 dhcp6_freedrop_addrs(ifp0, 1, ifp);
1152 #endif
1154 #ifdef AUTH
1155 static ssize_t
1156 dhcp6_update_auth(struct interface *ifp, struct dhcp6_message *m, size_t len)
1158 struct dhcp6_state *state;
1159 uint8_t *opt;
1160 uint16_t opt_len;
1162 opt = dhcp6_findmoption(m, len, D6_OPTION_AUTH, &opt_len);
1163 if (opt == NULL)
1164 return -1;
1166 state = D6_STATE(ifp);
1167 return dhcp_auth_encode(&ifp->options->auth, state->auth.token,
1168 (uint8_t *)state->send, state->send_len,
1169 6, state->send->type, opt, opt_len);
1171 #endif
1173 static int
1174 dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *))
1176 struct dhcp6_state *state = D6_STATE(ifp);
1177 struct dhcpcd_ctx *ctx = ifp->ctx;
1178 struct sockaddr_in6 dst = {
1179 .sin6_family = AF_INET6,
1180 .sin6_port = htons(DHCP6_SERVER_PORT),
1182 struct timespec RTprev;
1183 double rnd;
1184 time_t ms;
1185 uint8_t neg;
1186 const char *broad_uni;
1187 const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT;
1188 struct ipv6_addr *lla;
1189 int s;
1190 struct iovec iov = {
1191 .iov_base = state->send, .iov_len = state->send_len,
1193 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
1194 struct msghdr msg = {
1195 .msg_name = &dst, .msg_namelen = sizeof(dst),
1196 .msg_iov = &iov, .msg_iovlen = 1,
1199 if (!callback && ifp->carrier <= LINK_DOWN)
1200 return 0;
1202 #ifdef HAVE_SA_LEN
1203 dst.sin6_len = sizeof(dst);
1204 #endif
1206 lla = ipv6_linklocal(ifp);
1207 /* We need to ensure we have sufficient scope to unicast the address */
1208 /* XXX FIXME: We should check any added addresses we have like from
1209 * a Router Advertisement */
1210 if (IN6_IS_ADDR_UNSPECIFIED(&state->unicast) ||
1211 (state->state == DH6S_REQUEST &&
1212 (!IN6_IS_ADDR_LINKLOCAL(&state->unicast) || lla == NULL)))
1214 dst.sin6_addr = alldhcp;
1215 broad_uni = "broadcasting";
1216 } else {
1217 dst.sin6_addr = state->unicast;
1218 broad_uni = "unicasting";
1221 if (!callback)
1222 logdebugx("%s: %s %s with xid 0x%02x%02x%02x",
1223 ifp->name,
1224 broad_uni,
1225 dhcp6_get_op(state->send->type),
1226 state->send->xid[0],
1227 state->send->xid[1],
1228 state->send->xid[2]);
1229 else {
1230 if (state->IMD &&
1231 !(ifp->options->options & DHCPCD_INITIAL_DELAY))
1232 state->IMD = 0;
1233 if (state->IMD) {
1234 /* Some buggy PPP servers close the link too early
1235 * after sending an invalid status in their reply
1236 * which means this host won't see it.
1237 * 1 second grace seems to be the sweet spot. */
1238 if (ifp->flags & IFF_POINTOPOINT)
1239 state->RT.tv_sec = 1;
1240 else
1241 state->RT.tv_sec = 0;
1242 state->RT.tv_nsec = (suseconds_t)arc4random_uniform(
1243 (uint32_t)(state->IMD * NSEC_PER_SEC));
1244 timespecnorm(&state->RT);
1245 broad_uni = "delaying";
1246 goto logsend;
1248 if (state->RTC == 0) {
1249 RTprev.tv_sec = state->IRT;
1250 RTprev.tv_nsec = 0;
1251 state->RT.tv_sec = RTprev.tv_sec;
1252 state->RT.tv_nsec = 0;
1253 } else {
1254 RTprev = state->RT;
1255 timespecadd(&state->RT, &state->RT, &state->RT);
1258 rnd = DHCP6_RAND_MIN;
1259 rnd += (suseconds_t)arc4random_uniform(
1260 DHCP6_RAND_MAX - DHCP6_RAND_MIN);
1261 rnd /= MSEC_PER_SEC;
1262 neg = (rnd < 0.0);
1263 if (neg)
1264 rnd = -rnd;
1265 ts_to_ms(ms, &RTprev);
1266 ms = (time_t)((double)ms * rnd);
1267 ms_to_ts(&RTprev, ms);
1268 if (neg)
1269 timespecsub(&state->RT, &RTprev, &state->RT);
1270 else
1271 timespecadd(&state->RT, &RTprev, &state->RT);
1273 if (state->MRT != 0 && state->RT.tv_sec > state->MRT) {
1274 RTprev.tv_sec = state->MRT;
1275 RTprev.tv_nsec = 0;
1276 state->RT.tv_sec = state->MRT;
1277 state->RT.tv_nsec = 0;
1278 ts_to_ms(ms, &RTprev);
1279 ms = (time_t)((double)ms * rnd);
1280 ms_to_ts(&RTprev, ms);
1281 if (neg)
1282 timespecsub(&state->RT, &RTprev, &state->RT);
1283 else
1284 timespecadd(&state->RT, &RTprev, &state->RT);
1287 logsend:
1288 if (ifp->carrier > LINK_DOWN)
1289 logdebugx("%s: %s %s (xid 0x%02x%02x%02x),"
1290 " next in %0.1f seconds",
1291 ifp->name,
1292 broad_uni,
1293 dhcp6_get_op(state->send->type),
1294 state->send->xid[0],
1295 state->send->xid[1],
1296 state->send->xid[2],
1297 timespec_to_double(&state->RT));
1299 /* This sometimes happens when we delegate to this interface
1300 * AND run DHCPv6 on it normally. */
1301 assert(timespec_to_double(&state->RT) != 0);
1303 /* Wait the initial delay */
1304 if (state->IMD != 0) {
1305 state->IMD = 0;
1306 eloop_timeout_add_tv(ctx->eloop,
1307 &state->RT, callback, ifp);
1308 return 0;
1312 if (ifp->carrier <= LINK_DOWN)
1313 return 0;
1315 /* Update the elapsed time */
1316 dhcp6_updateelapsed(ifp, state->send, state->send_len);
1317 #ifdef AUTH
1318 if (ifp->options->auth.options & DHCPCD_AUTH_SEND &&
1319 dhcp6_update_auth(ifp, state->send, state->send_len) == -1)
1321 logerr("%s: %s: dhcp6_updateauth", __func__, ifp->name);
1322 if (errno != ESRCH)
1323 return -1;
1325 #endif
1327 /* Set the outbound interface */
1328 if (IN6_ARE_ADDR_EQUAL(&dst.sin6_addr, &alldhcp)) {
1329 struct cmsghdr *cm;
1330 struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
1332 dst.sin6_scope_id = ifp->index;
1333 msg.msg_control = ctl;
1334 msg.msg_controllen = sizeof(ctl);
1335 cm = CMSG_FIRSTHDR(&msg);
1336 if (cm == NULL) /* unlikely */
1337 return -1;
1338 cm->cmsg_level = IPPROTO_IPV6;
1339 cm->cmsg_type = IPV6_PKTINFO;
1340 cm->cmsg_len = CMSG_LEN(sizeof(pi));
1341 memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
1344 if (ctx->dhcp6_fd != -1)
1345 s = ctx->dhcp6_fd;
1346 else if (lla != NULL && lla->dhcp6_fd != -1)
1347 s = lla->dhcp6_fd;
1348 else {
1349 logerrx("%s: no socket to send from", ifp->name);
1350 return -1;
1353 if (sendmsg(s, &msg, 0) == -1) {
1354 logerr("%s: %s: sendmsg", __func__, ifp->name);
1355 /* Allow DHCPv6 to continue .... the errors
1356 * would be rate limited by the protocol.
1357 * Generally the error is ENOBUFS when struggling to
1358 * associate with an access point. */
1361 state->RTC++;
1362 if (callback) {
1363 if (state->MRC == 0 || state->RTC < state->MRC)
1364 eloop_timeout_add_tv(ctx->eloop,
1365 &state->RT, callback, ifp);
1366 else if (state->MRC != 0 && state->MRCcallback)
1367 eloop_timeout_add_tv(ctx->eloop,
1368 &state->RT, state->MRCcallback, ifp);
1369 else
1370 logwarnx("%s: sent %d times with no reply",
1371 ifp->name, state->RTC);
1373 return 0;
1376 static void
1377 dhcp6_sendinform(void *arg)
1380 dhcp6_sendmessage(arg, dhcp6_sendinform);
1383 static void
1384 dhcp6_senddiscover(void *arg)
1387 dhcp6_sendmessage(arg, dhcp6_senddiscover);
1390 static void
1391 dhcp6_sendrequest(void *arg)
1394 dhcp6_sendmessage(arg, dhcp6_sendrequest);
1397 static void
1398 dhcp6_sendrebind(void *arg)
1401 dhcp6_sendmessage(arg, dhcp6_sendrebind);
1404 static void
1405 dhcp6_sendrenew(void *arg)
1408 dhcp6_sendmessage(arg, dhcp6_sendrenew);
1411 static void
1412 dhcp6_sendconfirm(void *arg)
1415 dhcp6_sendmessage(arg, dhcp6_sendconfirm);
1418 static void
1419 dhcp6_sendrelease(void *arg)
1422 dhcp6_sendmessage(arg, dhcp6_sendrelease);
1425 static void
1426 dhcp6_startrenew(void *arg)
1428 struct interface *ifp;
1429 struct dhcp6_state *state;
1431 ifp = arg;
1432 if ((state = D6_STATE(ifp)) == NULL)
1433 return;
1435 /* Only renew in the bound or renew states */
1436 if (state->state != DH6S_BOUND &&
1437 state->state != DH6S_RENEW)
1438 return;
1440 /* Remove the timeout as the renew may have been forced. */
1441 eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startrenew, ifp);
1443 state->state = DH6S_RENEW;
1444 state->RTC = 0;
1445 state->IMD = REN_MAX_DELAY;
1446 state->IRT = REN_TIMEOUT;
1447 state->MRT = REN_MAX_RT;
1448 state->MRC = 0;
1450 if (dhcp6_makemessage(ifp) == -1)
1451 logerr("%s: %s", __func__, ifp->name);
1452 else
1453 dhcp6_sendrenew(ifp);
1456 void dhcp6_renew(struct interface *ifp)
1459 dhcp6_startrenew(ifp);
1463 dhcp6_dadcompleted(const struct interface *ifp)
1465 const struct dhcp6_state *state;
1466 const struct ipv6_addr *ap;
1468 state = D6_CSTATE(ifp);
1469 TAILQ_FOREACH(ap, &state->addrs, next) {
1470 if (ap->flags & IPV6_AF_ADDED &&
1471 !(ap->flags & IPV6_AF_DADCOMPLETED))
1472 return 0;
1474 return 1;
1477 static void
1478 dhcp6_dadcallback(void *arg)
1480 struct ipv6_addr *ia = arg;
1481 struct interface *ifp;
1482 struct dhcp6_state *state;
1483 int wascompleted, valid;
1485 wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
1486 ia->flags |= IPV6_AF_DADCOMPLETED;
1487 if (ia->flags & IPV6_AF_DUPLICATED) {
1488 /* XXX FIXME
1489 * We should decline the address */
1490 logwarnx("%s: DAD detected %s", ia->iface->name, ia->saddr);
1493 if (!wascompleted) {
1494 ifp = ia->iface;
1496 state = D6_STATE(ifp);
1497 if (state->state == DH6S_BOUND ||
1498 state->state == DH6S_DELEGATED)
1500 struct ipv6_addr *ia2;
1502 #ifdef SMALL
1503 valid = true;
1504 #else
1505 valid = (ia->delegating_prefix == NULL);
1506 #endif
1507 TAILQ_FOREACH(ia2, &state->addrs, next) {
1508 if (ia2->flags & IPV6_AF_ADDED &&
1509 !(ia2->flags & IPV6_AF_DADCOMPLETED))
1511 wascompleted = 1;
1512 break;
1515 if (!wascompleted) {
1516 logdebugx("%s: DHCPv6 DAD completed",
1517 ifp->name);
1518 script_runreason(ifp,
1519 #ifndef SMALL
1520 ia->delegating_prefix ? "DELEGATED6" :
1521 #endif
1522 state->reason);
1523 if (valid)
1524 dhcpcd_daemonise(ifp->ctx);
1526 #ifdef ND6_ADVERTISE
1527 ipv6nd_advertise(ia);
1528 #endif
1533 static void
1534 dhcp6_addrequestedaddrs(struct interface *ifp)
1536 struct dhcp6_state *state;
1537 size_t i;
1538 struct if_ia *ia;
1539 struct ipv6_addr *a;
1541 state = D6_STATE(ifp);
1542 /* Add any requested prefixes / addresses */
1543 for (i = 0; i < ifp->options->ia_len; i++) {
1544 ia = &ifp->options->ia[i];
1545 if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) ||
1546 !IN6_IS_ADDR_UNSPECIFIED(&ia->addr)))
1547 continue;
1548 a = ipv6_newaddr(ifp, &ia->addr,
1550 * RFC 5942 Section 5
1551 * We cannot assume any prefix length, nor tie the
1552 * address to an existing one as it could expire
1553 * before the address.
1554 * As such we just give it a 128 prefix.
1556 ia->ia_type == D6_OPTION_IA_PD ? ia->prefix_len : 128,
1557 IPV6_AF_REQUEST);
1558 if (a == NULL)
1559 continue;
1560 a->dadcallback = dhcp6_dadcallback;
1561 memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
1562 a->ia_type = ia->ia_type;
1563 TAILQ_INSERT_TAIL(&state->addrs, a, next);
1567 static void
1568 dhcp6_startdiscover(void *arg)
1570 struct interface *ifp;
1571 struct dhcp6_state *state;
1573 ifp = arg;
1574 #ifndef SMALL
1575 dhcp6_delete_delegates(ifp);
1576 #endif
1577 loginfox("%s: soliciting a DHCPv6 lease", ifp->name);
1578 state = D6_STATE(ifp);
1579 state->state = DH6S_DISCOVER;
1580 state->RTC = 0;
1581 state->IMD = SOL_MAX_DELAY;
1582 state->IRT = SOL_TIMEOUT;
1583 state->MRT = state->sol_max_rt;
1584 state->MRC = SOL_MAX_RC;
1586 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1587 free(state->new);
1588 state->new = NULL;
1589 state->new_len = 0;
1591 if (dhcp6_makemessage(ifp) == -1)
1592 logerr("%s: %s", __func__, ifp->name);
1593 else
1594 dhcp6_senddiscover(ifp);
1597 static void
1598 dhcp6_startinform(void *arg)
1600 struct interface *ifp;
1601 struct dhcp6_state *state;
1603 ifp = arg;
1604 state = D6_STATE(ifp);
1605 if (state->new == NULL || ifp->options->options & DHCPCD_DEBUG)
1606 loginfox("%s: requesting DHCPv6 information", ifp->name);
1607 state->state = DH6S_INFORM;
1608 state->RTC = 0;
1609 state->IMD = INF_MAX_DELAY;
1610 state->IRT = INF_TIMEOUT;
1611 state->MRT = state->inf_max_rt;
1612 state->MRC = 0;
1614 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
1615 if (dhcp6_makemessage(ifp) == -1) {
1616 logerr("%s: %s", __func__, ifp->name);
1617 return;
1619 dhcp6_sendinform(ifp);
1620 /* RFC3315 18.1.2 says that if CONFIRM failed then the prior addresses
1621 * SHOULD be used. The wording here is poor, because the addresses are
1622 * merely one facet of the lease as a whole.
1623 * This poor wording might explain the lack of similar text for INFORM
1624 * in 18.1.5 because there are no addresses in the INFORM message. */
1625 eloop_timeout_add_sec(ifp->ctx->eloop,
1626 INF_MAX_RD, dhcp6_failinform, ifp);
1629 static void
1630 dhcp6_fail(struct interface *ifp)
1632 struct dhcp6_state *state = D6_STATE(ifp);
1634 /* RFC3315 18.1.2 says that prior addresses SHOULD be used on failure.
1635 * RFC2131 3.2.3 says that MAY chose to use the prior address.
1636 * Because dhcpcd was written first for RFC2131, we have the LASTLEASE
1637 * option which defaults to off as that makes the most sense for
1638 * mobile clients.
1639 * dhcpcd also has LASTLEASE_EXTEND to extend this lease past it's
1640 * expiry, but this is strictly not RFC compliant in any way or form. */
1641 if (state->new == NULL ||
1642 !(ifp->options->options & DHCPCD_LASTLEASE))
1644 #ifndef SMALL
1645 dhcp6_delete_delegates(ifp);
1646 #endif
1647 if (state->state != DH6S_INFORM)
1648 dhcp6_startdiscover(ifp);
1649 return;
1652 switch (state->state) {
1653 case DH6S_INFORM:
1654 case DH6S_INFORMED:
1655 state->state = DH6S_ITIMEDOUT;
1656 break;
1657 default:
1658 state->state = DH6S_TIMEDOUT;
1659 break;
1662 dhcp6_bind(ifp, NULL, NULL);
1664 switch (state->state) {
1665 case DH6S_BOUND:
1666 case DH6S_INFORMED:
1667 break;
1668 default:
1669 dhcp6_startdiscover(ifp);
1670 break;
1674 static void
1675 dhcp6_failconfirm(void *arg)
1677 struct interface *ifp;
1679 ifp = arg;
1680 logerrx("%s: failed to confirm prior address", ifp->name);
1681 dhcp6_fail(ifp);
1684 static void
1685 dhcp6_failrequest(void *arg)
1687 struct interface *ifp;
1689 ifp = arg;
1690 logerrx("%s: failed to request address", ifp->name);
1691 dhcp6_fail(ifp);
1694 static void
1695 dhcp6_failinform(void *arg)
1697 struct interface *ifp;
1699 ifp = arg;
1700 logerrx("%s: failed to request information", ifp->name);
1701 dhcp6_fail(ifp);
1704 #ifdef SMALL
1705 #define dhcp6_hasprefixdelegation(a) (0)
1706 #else
1707 static void
1708 dhcp6_failrebind(void *arg)
1710 struct interface *ifp;
1712 ifp = arg;
1713 logerrx("%s: failed to rebind prior delegation", ifp->name);
1714 dhcp6_fail(ifp);
1717 static int
1718 dhcp6_hasprefixdelegation(struct interface *ifp)
1720 size_t i;
1721 uint16_t t;
1723 t = 0;
1724 for (i = 0; i < ifp->options->ia_len; i++) {
1725 if (t && t != ifp->options->ia[i].ia_type) {
1726 if (t == D6_OPTION_IA_PD ||
1727 ifp->options->ia[i].ia_type == D6_OPTION_IA_PD)
1728 return 2;
1730 t = ifp->options->ia[i].ia_type;
1732 return t == D6_OPTION_IA_PD ? 1 : 0;
1734 #endif
1736 static void
1737 dhcp6_startrebind(void *arg)
1739 struct interface *ifp;
1740 struct dhcp6_state *state;
1741 #ifndef SMALL
1742 int pd;
1743 #endif
1745 ifp = arg;
1746 eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrenew, ifp);
1747 state = D6_STATE(ifp);
1748 if (state->state == DH6S_RENEW)
1749 logwarnx("%s: failed to renew DHCPv6, rebinding", ifp->name);
1750 else
1751 loginfox("%s: rebinding prior DHCPv6 lease", ifp->name);
1752 state->state = DH6S_REBIND;
1753 state->RTC = 0;
1754 state->MRC = 0;
1756 #ifndef SMALL
1757 /* RFC 3633 section 12.1 */
1758 pd = dhcp6_hasprefixdelegation(ifp);
1759 if (pd) {
1760 state->IMD = CNF_MAX_DELAY;
1761 state->IRT = CNF_TIMEOUT;
1762 state->MRT = CNF_MAX_RT;
1763 } else
1764 #endif
1766 state->IMD = REB_MAX_DELAY;
1767 state->IRT = REB_TIMEOUT;
1768 state->MRT = REB_MAX_RT;
1771 if (dhcp6_makemessage(ifp) == -1)
1772 logerr("%s: %s", __func__, ifp->name);
1773 else
1774 dhcp6_sendrebind(ifp);
1776 #ifndef SMALL
1777 /* RFC 3633 section 12.1 */
1778 if (pd)
1779 eloop_timeout_add_sec(ifp->ctx->eloop,
1780 CNF_MAX_RD, dhcp6_failrebind, ifp);
1781 #endif
1785 static void
1786 dhcp6_startrequest(struct interface *ifp)
1788 struct dhcp6_state *state;
1790 eloop_timeout_delete(ifp->ctx->eloop, dhcp6_senddiscover, ifp);
1791 state = D6_STATE(ifp);
1792 state->state = DH6S_REQUEST;
1793 state->RTC = 0;
1794 state->IMD = 0;
1795 state->IRT = REQ_TIMEOUT;
1796 state->MRT = REQ_MAX_RT;
1797 state->MRC = REQ_MAX_RC;
1798 state->MRCcallback = dhcp6_failrequest;
1800 if (dhcp6_makemessage(ifp) == -1) {
1801 logerr("%s: %s", __func__, ifp->name);
1802 return;
1805 dhcp6_sendrequest(ifp);
1808 static void
1809 dhcp6_startconfirm(struct interface *ifp)
1811 struct dhcp6_state *state;
1813 state = D6_STATE(ifp);
1814 state->state = DH6S_CONFIRM;
1815 state->RTC = 0;
1816 state->IMD = CNF_MAX_DELAY;
1817 state->IRT = CNF_TIMEOUT;
1818 state->MRT = CNF_MAX_RT;
1819 state->MRC = CNF_MAX_RC;
1821 loginfox("%s: confirming prior DHCPv6 lease", ifp->name);
1822 if (dhcp6_makemessage(ifp) == -1) {
1823 logerr("%s: %s", __func__, ifp->name);
1824 return;
1826 dhcp6_sendconfirm(ifp);
1827 eloop_timeout_add_sec(ifp->ctx->eloop,
1828 CNF_MAX_RD, dhcp6_failconfirm, ifp);
1831 static void
1832 dhcp6_leaseextend(struct interface *ifp)
1834 struct dhcp6_state *state = D6_STATE(ifp);
1835 struct ipv6_addr *ia;
1837 logwarnx("%s: extending DHCPv6 lease", ifp->name);
1838 TAILQ_FOREACH(ia, &state->addrs, next) {
1839 ia->flags |= IPV6_AF_EXTENDED;
1840 /* Set infinite lifetimes. */
1841 ia->prefix_pltime = ND6_INFINITE_LIFETIME;
1842 ia->prefix_vltime = ND6_INFINITE_LIFETIME;
1846 static void
1847 dhcp6_startexpire(void *arg)
1849 struct interface *ifp;
1851 ifp = arg;
1852 eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrebind, ifp);
1854 logerrx("%s: DHCPv6 lease expired", ifp->name);
1855 if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND) {
1856 struct dhcp6_state *state = D6_STATE(ifp);
1858 dhcp6_leaseextend(ifp);
1859 ipv6_addaddrs(&state->addrs);
1860 } else {
1861 dhcp6_freedrop_addrs(ifp, 1, NULL);
1862 #ifndef SMALL
1863 dhcp6_delete_delegates(ifp);
1864 #endif
1865 script_runreason(ifp, "EXPIRE6");
1867 if (!(ifp->options->options & DHCPCD_IPV6RS) ||
1868 ipv6nd_hasradhcp(ifp) ||
1869 dhcp6_hasprefixdelegation(ifp))
1870 dhcp6_startdiscover(ifp);
1871 else
1872 logwarnx("%s: no advertising IPv6 router wants DHCP",ifp->name);
1875 static void
1876 dhcp6_finishrelease(void *arg)
1878 struct interface *ifp;
1879 struct dhcp6_state *state;
1881 ifp = (struct interface *)arg;
1882 if ((state = D6_STATE(ifp)) != NULL) {
1883 state->state = DH6S_RELEASED;
1884 dhcp6_drop(ifp, "RELEASE6");
1888 static void
1889 dhcp6_startrelease(struct interface *ifp)
1891 struct dhcp6_state *state;
1893 state = D6_STATE(ifp);
1894 if (state->state != DH6S_BOUND)
1895 return;
1897 state->state = DH6S_RELEASE;
1898 state->RTC = 0;
1899 state->IMD = REL_MAX_DELAY;
1900 state->IRT = REL_TIMEOUT;
1901 state->MRT = REL_MAX_RT;
1902 /* MRC of REL_MAX_RC is optional in RFC 3315 18.1.6 */
1903 #if 0
1904 state->MRC = REL_MAX_RC;
1905 state->MRCcallback = dhcp6_finishrelease;
1906 #else
1907 state->MRC = 0;
1908 state->MRCcallback = NULL;
1909 #endif
1911 if (dhcp6_makemessage(ifp) == -1)
1912 logerr("%s: %s", __func__, ifp->name);
1913 else {
1914 dhcp6_sendrelease(ifp);
1915 dhcp6_finishrelease(ifp);
1919 static int
1920 dhcp6_checkstatusok(const struct interface *ifp,
1921 struct dhcp6_message *m, uint8_t *p, size_t len)
1923 struct dhcp6_state *state;
1924 uint8_t *opt;
1925 uint16_t opt_len, code;
1926 size_t mlen;
1927 void * (*f)(void *, size_t, uint16_t, uint16_t *), *farg;
1928 char buf[32], *sbuf;
1929 const char *status;
1930 logfunc_t *logfunc;
1932 state = D6_STATE(ifp);
1933 f = p ? dhcp6_findoption : dhcp6_findmoption;
1934 if (p)
1935 farg = p;
1936 else
1937 farg = m;
1938 if ((opt = f(farg, len, D6_OPTION_STATUS_CODE, &opt_len)) == NULL) {
1939 //logdebugx("%s: no status", ifp->name);
1940 state->lerror = 0;
1941 errno = ESRCH;
1942 return 0;
1945 if (opt_len < sizeof(code)) {
1946 logerrx("%s: status truncated", ifp->name);
1947 return -1;
1949 memcpy(&code, opt, sizeof(code));
1950 code = ntohs(code);
1951 if (code == D6_STATUS_OK) {
1952 state->lerror = 0;
1953 errno = 0;
1954 return 0;
1957 /* Anything after the code is a message. */
1958 opt += sizeof(code);
1959 mlen = opt_len - sizeof(code);
1960 if (mlen == 0) {
1961 sbuf = NULL;
1962 if (code < sizeof(dhcp6_statuses) / sizeof(char *))
1963 status = dhcp6_statuses[code];
1964 else {
1965 snprintf(buf, sizeof(buf), "Unknown Status (%d)", code);
1966 status = buf;
1968 } else {
1969 if ((sbuf = malloc(mlen + 1)) == NULL) {
1970 logerr(__func__);
1971 return -1;
1973 memcpy(sbuf, opt, mlen);
1974 sbuf[mlen] = '\0';
1975 status = sbuf;
1978 if (state->lerror == code || state->state == DH6S_INIT)
1979 logfunc = logdebugx;
1980 else
1981 logfunc = logerrx;
1982 logfunc("%s: DHCPv6 REPLY: %s", ifp->name, status);
1983 free(sbuf);
1984 state->lerror = code;
1985 errno = 0;
1986 return (int)code;
1989 const struct ipv6_addr *
1990 dhcp6_iffindaddr(const struct interface *ifp, const struct in6_addr *addr,
1991 unsigned int flags)
1993 const struct dhcp6_state *state;
1994 const struct ipv6_addr *ap;
1996 if ((state = D6_STATE(ifp)) != NULL) {
1997 TAILQ_FOREACH(ap, &state->addrs, next) {
1998 if (ipv6_findaddrmatch(ap, addr, flags))
1999 return ap;
2002 return NULL;
2005 struct ipv6_addr *
2006 dhcp6_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
2007 unsigned int flags)
2009 struct interface *ifp;
2010 struct ipv6_addr *ap;
2011 struct dhcp6_state *state;
2013 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
2014 if ((state = D6_STATE(ifp)) != NULL) {
2015 TAILQ_FOREACH(ap, &state->addrs, next) {
2016 if (ipv6_findaddrmatch(ap, addr, flags))
2017 return ap;
2021 return NULL;
2024 static int
2025 dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
2026 uint8_t *d, size_t l, const struct timespec *acquired)
2028 struct dhcp6_state *state;
2029 uint8_t *o, *nd;
2030 uint16_t ol;
2031 struct ipv6_addr *a;
2032 int i;
2033 struct dhcp6_ia_addr ia;
2035 i = 0;
2036 state = D6_STATE(ifp);
2037 while ((o = dhcp6_findoption(d, l, D6_OPTION_IA_ADDR, &ol))) {
2038 /* Set d and l first to ensure we find the next option. */
2039 nd = o + ol;
2040 l -= (size_t)(nd - d);
2041 d = nd;
2042 if (ol < sizeof(ia)) {
2043 errno = EINVAL;
2044 logerrx("%s: IA Address option truncated", ifp->name);
2045 continue;
2047 memcpy(&ia, o, sizeof(ia));
2048 ia.pltime = ntohl(ia.pltime);
2049 ia.vltime = ntohl(ia.vltime);
2050 /* RFC 3315 22.6 */
2051 if (ia.pltime > ia.vltime) {
2052 errno = EINVAL;
2053 logerr("%s: IA Address pltime %"PRIu32
2054 " > vltime %"PRIu32,
2055 ifp->name, ia.pltime, ia.vltime);
2056 continue;
2058 TAILQ_FOREACH(a, &state->addrs, next) {
2059 if (ipv6_findaddrmatch(a, &ia.addr, 0))
2060 break;
2062 if (a == NULL) {
2064 * RFC 5942 Section 5
2065 * We cannot assume any prefix length, nor tie the
2066 * address to an existing one as it could expire
2067 * before the address.
2068 * As such we just give it a 128 prefix.
2070 a = ipv6_newaddr(ifp, &ia.addr, 128, IPV6_AF_ONLINK);
2071 a->dadcallback = dhcp6_dadcallback;
2072 a->ia_type = ot;
2073 memcpy(a->iaid, iaid, sizeof(a->iaid));
2074 a->created = *acquired;
2076 TAILQ_INSERT_TAIL(&state->addrs, a, next);
2077 } else {
2078 if (!(a->flags & IPV6_AF_ONLINK))
2079 a->flags |= IPV6_AF_ONLINK | IPV6_AF_NEW;
2080 a->flags &= ~(IPV6_AF_STALE | IPV6_AF_EXTENDED);
2082 a->acquired = *acquired;
2083 a->prefix_pltime = ia.pltime;
2084 if (a->prefix_vltime != ia.vltime) {
2085 a->flags |= IPV6_AF_NEW;
2086 a->prefix_vltime = ia.vltime;
2088 if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
2089 state->lowpl = a->prefix_pltime;
2090 if (a->prefix_vltime && a->prefix_vltime > state->expire)
2091 state->expire = a->prefix_vltime;
2092 i++;
2094 return i;
2097 #ifndef SMALL
2098 static int
2099 dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
2100 uint8_t *d, size_t l, const struct timespec *acquired)
2102 struct dhcp6_state *state;
2103 uint8_t *o, *nd;
2104 struct ipv6_addr *a;
2105 int i;
2106 uint8_t nb, *pw;
2107 uint16_t ol;
2108 struct dhcp6_pd_addr pdp;
2109 struct in6_addr pdp_prefix;
2111 i = 0;
2112 state = D6_STATE(ifp);
2113 while ((o = dhcp6_findoption(d, l, D6_OPTION_IAPREFIX, &ol))) {
2114 /* Set d and l first to ensure we find the next option. */
2115 nd = o + ol;
2116 l -= (size_t)(nd - d);
2117 d = nd;
2118 if (ol < sizeof(pdp)) {
2119 errno = EINVAL;
2120 logerrx("%s: IA Prefix option truncated", ifp->name);
2121 continue;
2124 memcpy(&pdp, o, sizeof(pdp));
2125 pdp.pltime = ntohl(pdp.pltime);
2126 pdp.vltime = ntohl(pdp.vltime);
2127 /* RFC 3315 22.6 */
2128 if (pdp.pltime > pdp.vltime) {
2129 errno = EINVAL;
2130 logerrx("%s: IA Prefix pltime %"PRIu32
2131 " > vltime %"PRIu32,
2132 ifp->name, pdp.pltime, pdp.vltime);
2133 continue;
2136 o += sizeof(pdp);
2137 ol = (uint16_t)(ol - sizeof(pdp));
2139 /* pdp.prefix is not aligned so copy it out. */
2140 memcpy(&pdp_prefix, &pdp.prefix, sizeof(pdp_prefix));
2141 TAILQ_FOREACH(a, &state->addrs, next) {
2142 if (IN6_ARE_ADDR_EQUAL(&a->prefix, &pdp_prefix))
2143 break;
2146 if (a == NULL) {
2147 a = ipv6_newaddr(ifp, &pdp_prefix, pdp.prefix_len,
2148 IPV6_AF_DELEGATEDPFX);
2149 if (a == NULL)
2150 break;
2151 a->created = *acquired;
2152 a->dadcallback = dhcp6_dadcallback;
2153 a->ia_type = D6_OPTION_IA_PD;
2154 memcpy(a->iaid, iaid, sizeof(a->iaid));
2155 TAILQ_INIT(&a->pd_pfxs);
2156 TAILQ_INSERT_TAIL(&state->addrs, a, next);
2157 } else {
2158 if (!(a->flags & IPV6_AF_DELEGATEDPFX)) {
2159 a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
2160 TAILQ_INIT(&a->pd_pfxs);
2162 a->flags &= ~(IPV6_AF_STALE |
2163 IPV6_AF_EXTENDED |
2164 IPV6_AF_REQUEST);
2165 if (a->prefix_vltime != pdp.vltime)
2166 a->flags |= IPV6_AF_NEW;
2169 a->acquired = *acquired;
2170 a->prefix_pltime = pdp.pltime;
2171 a->prefix_vltime = pdp.vltime;
2173 if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
2174 state->lowpl = a->prefix_pltime;
2175 if (a->prefix_vltime && a->prefix_vltime > state->expire)
2176 state->expire = a->prefix_vltime;
2177 i++;
2179 a->prefix_exclude_len = 0;
2180 memset(&a->prefix_exclude, 0, sizeof(a->prefix_exclude));
2181 o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol);
2182 if (o == NULL)
2183 continue;
2185 /* RFC 6603 4.2 says option length MUST be between 2 and 17.
2186 * This allows 1 octet for prefix length and 16 for the
2187 * subnet ID. */
2188 if (ol < 2 || ol > 17) {
2189 logerrx("%s: invalid PD Exclude option", ifp->name);
2190 continue;
2193 /* RFC 6603 4.2 says prefix length MUST be between the
2194 * length of the IAPREFIX prefix length + 1 and 128. */
2195 if (*o < a->prefix_len + 1 || *o > 128) {
2196 logerrx("%s: invalid PD Exclude length", ifp->name);
2197 continue;
2200 ol--;
2201 /* Check option length matches prefix length. */
2202 if (((*o - a->prefix_len - 1) / NBBY) + 1 != ol) {
2203 logerrx("%s: PD Exclude length mismatch", ifp->name);
2204 continue;
2206 a->prefix_exclude_len = *o++;
2208 memcpy(&a->prefix_exclude, &a->prefix,
2209 sizeof(a->prefix_exclude));
2210 nb = a->prefix_len % NBBY;
2211 if (nb)
2212 ol--;
2213 pw = a->prefix_exclude.s6_addr +
2214 (a->prefix_exclude_len / NBBY) - 1;
2215 while (ol-- > 0)
2216 *pw-- = *o++;
2217 if (nb)
2218 *pw = (uint8_t)(*pw | (*o >> nb));
2220 return i;
2222 #endif
2224 static int
2225 dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
2226 const char *sfrom, const struct timespec *acquired)
2228 struct dhcp6_state *state;
2229 const struct if_options *ifo;
2230 struct dhcp6_option o;
2231 uint8_t *d, *p;
2232 struct dhcp6_ia_na ia;
2233 int i, e, error;
2234 size_t j;
2235 uint16_t nl;
2236 uint8_t iaid[4];
2237 char buf[sizeof(iaid) * 3];
2238 struct ipv6_addr *ap;
2239 struct if_ia *ifia;
2241 if (l < sizeof(*m)) {
2242 /* Should be impossible with guards at packet in
2243 * and reading leases */
2244 errno = EINVAL;
2245 return -1;
2248 ifo = ifp->options;
2249 i = e = 0;
2250 state = D6_STATE(ifp);
2251 TAILQ_FOREACH(ap, &state->addrs, next) {
2252 if (!(ap->flags & IPV6_AF_DELEGATED))
2253 ap->flags |= IPV6_AF_STALE;
2256 d = (uint8_t *)m + sizeof(*m);
2257 l -= sizeof(*m);
2258 while (l > sizeof(o)) {
2259 memcpy(&o, d, sizeof(o));
2260 o.len = ntohs(o.len);
2261 if (o.len > l || sizeof(o) + o.len > l) {
2262 errno = EINVAL;
2263 logerrx("%s: option overflow", ifp->name);
2264 break;
2266 p = d + sizeof(o);
2267 d = p + o.len;
2268 l -= sizeof(o) + o.len;
2270 o.code = ntohs(o.code);
2271 switch(o.code) {
2272 case D6_OPTION_IA_TA:
2273 nl = 4;
2274 break;
2275 case D6_OPTION_IA_NA:
2276 case D6_OPTION_IA_PD:
2277 nl = 12;
2278 break;
2279 default:
2280 continue;
2282 if (o.len < nl) {
2283 errno = EINVAL;
2284 logerrx("%s: IA option truncated", ifp->name);
2285 continue;
2288 memcpy(&ia, p, nl);
2289 p += nl;
2290 o.len = (uint16_t)(o.len - nl);
2292 for (j = 0; j < ifo->ia_len; j++) {
2293 ifia = &ifo->ia[j];
2294 if (ifia->ia_type == o.code &&
2295 memcmp(ifia->iaid, ia.iaid, sizeof(ia.iaid)) == 0)
2296 break;
2298 if (j == ifo->ia_len &&
2299 !(ifo->ia_len == 0 && ifp->ctx->options & DHCPCD_DUMPLEASE))
2301 logdebugx("%s: ignoring unrequested IAID %s",
2302 ifp->name,
2303 hwaddr_ntoa(ia.iaid, sizeof(ia.iaid),
2304 buf, sizeof(buf)));
2305 continue;
2308 if (o.code != D6_OPTION_IA_TA) {
2309 ia.t1 = ntohl(ia.t1);
2310 ia.t2 = ntohl(ia.t2);
2311 /* RFC 3315 22.4 */
2312 if (ia.t2 > 0 && ia.t1 > ia.t2) {
2313 logwarnx("%s: IAID %s T1(%d) > T2(%d) from %s",
2314 ifp->name,
2315 hwaddr_ntoa(iaid, sizeof(iaid), buf,
2316 sizeof(buf)),
2317 ia.t1, ia.t2, sfrom);
2318 continue;
2320 } else
2321 ia.t1 = ia.t2 = 0; /* appease gcc */
2322 if ((error = dhcp6_checkstatusok(ifp, NULL, p, o.len)) != 0) {
2323 if (error == D6_STATUS_NOBINDING)
2324 state->has_no_binding = true;
2325 e = 1;
2326 continue;
2328 if (o.code == D6_OPTION_IA_PD) {
2329 #ifndef SMALL
2330 if (dhcp6_findpd(ifp, ia.iaid, p, o.len,
2331 acquired) == 0)
2333 logwarnx("%s: %s: DHCPv6 REPLY missing Prefix",
2334 ifp->name, sfrom);
2335 continue;
2337 #endif
2338 } else {
2339 if (dhcp6_findna(ifp, o.code, ia.iaid, p, o.len,
2340 acquired) == 0)
2342 logwarnx("%s: %s: DHCPv6 REPLY missing "
2343 "IA Address",
2344 ifp->name, sfrom);
2345 continue;
2348 if (o.code != D6_OPTION_IA_TA) {
2349 if (ia.t1 != 0 &&
2350 (ia.t1 < state->renew || state->renew == 0))
2351 state->renew = ia.t1;
2352 if (ia.t2 != 0 &&
2353 (ia.t2 < state->rebind || state->rebind == 0))
2354 state->rebind = ia.t2;
2356 i++;
2359 if (i == 0 && e)
2360 return -1;
2361 return i;
2364 static void
2365 dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
2367 struct ipv6_addr *ia, *ian;
2369 TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
2370 if (ia->flags & IPV6_AF_EXTENDED)
2372 else if (ia->flags & IPV6_AF_STALE) {
2373 if (ia->prefix_vltime != 0)
2374 logdebugx("%s: %s: became stale",
2375 ia->iface->name, ia->saddr);
2376 ia->prefix_pltime = 0;
2377 } else if (ia->prefix_vltime == 0)
2378 loginfox("%s: %s: no valid lifetime",
2379 ia->iface->name, ia->saddr);
2380 else
2381 continue;
2383 #ifndef SMALL
2384 /* If we delegated from this prefix, deprecate or remove
2385 * the delegations. */
2386 if (ia->flags & IPV6_AF_DELEGATEDPFX) {
2387 struct ipv6_addr *da;
2388 bool touched = false;
2390 TAILQ_FOREACH(da, &ia->pd_pfxs, pd_next) {
2391 if (ia->prefix_vltime == 0) {
2392 if (da->prefix_vltime != 0) {
2393 da->prefix_vltime = 0;
2394 touched = true;
2396 } else if (da->prefix_pltime != 0) {
2397 da->prefix_pltime = 0;
2398 touched = true;
2401 if (touched)
2402 ipv6_addaddrs(&ia->pd_pfxs);
2404 #endif
2406 if (ia->flags & IPV6_AF_REQUEST) {
2407 ia->prefix_vltime = ia->prefix_pltime = 0;
2408 eloop_q_timeout_delete(ia->iface->ctx->eloop,
2409 0, NULL, ia);
2410 continue;
2412 TAILQ_REMOVE(addrs, ia, next);
2413 if (ia->flags & IPV6_AF_EXTENDED)
2414 ipv6_deleteaddr(ia);
2415 ipv6_freeaddr(ia);
2419 static int
2420 dhcp6_validatelease(struct interface *ifp,
2421 struct dhcp6_message *m, size_t len,
2422 const char *sfrom, const struct timespec *acquired)
2424 struct dhcp6_state *state;
2425 int nia, ok_errno;
2426 struct timespec aq;
2428 if (len <= sizeof(*m)) {
2429 logerrx("%s: DHCPv6 lease truncated", ifp->name);
2430 return -1;
2433 state = D6_STATE(ifp);
2434 errno = 0;
2435 if (dhcp6_checkstatusok(ifp, m, NULL, len) != 0)
2436 return -1;
2437 ok_errno = errno;
2439 state->renew = state->rebind = state->expire = 0;
2440 state->lowpl = ND6_INFINITE_LIFETIME;
2441 if (!acquired) {
2442 clock_gettime(CLOCK_MONOTONIC, &aq);
2443 acquired = &aq;
2445 state->has_no_binding = false;
2446 nia = dhcp6_findia(ifp, m, len, sfrom, acquired);
2447 if (nia == 0) {
2448 if (state->state != DH6S_CONFIRM && ok_errno != 0) {
2449 logerrx("%s: no useable IA found in lease", ifp->name);
2450 return -1;
2453 /* We are confirming and have an OK,
2454 * so look for ia's in our old lease.
2455 * IA's must have existed here otherwise we would
2456 * have rejected it earlier. */
2457 assert(state->new != NULL && state->new_len != 0);
2458 state->has_no_binding = false;
2459 nia = dhcp6_findia(ifp, state->new, state->new_len,
2460 sfrom, acquired);
2462 return nia;
2465 static ssize_t
2466 dhcp6_writelease(const struct interface *ifp)
2468 const struct dhcp6_state *state;
2469 int fd;
2470 ssize_t bytes;
2472 state = D6_CSTATE(ifp);
2473 logdebugx("%s: writing lease `%s'", ifp->name, state->leasefile);
2475 fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
2476 if (fd == -1) {
2477 logerr(__func__);
2478 return -1;
2480 bytes = write(fd, state->new, state->new_len);
2481 close(fd);
2482 return bytes;
2485 static int
2486 dhcp6_readlease(struct interface *ifp, int validate)
2488 struct dhcp6_state *state;
2489 struct stat st;
2490 int fd;
2491 time_t now;
2492 int retval;
2493 bool read_stdin, fd_opened;
2494 #ifdef AUTH
2495 uint8_t *o;
2496 uint16_t ol;
2497 #endif
2499 state = D6_STATE(ifp);
2500 read_stdin = state->leasefile[0] == '\0';
2501 if (read_stdin) {
2502 logdebugx("reading standard input");
2503 fd = fileno(stdin);
2504 fd_opened = false;
2505 } else {
2506 logdebugx("%s: reading lease `%s'", ifp->name,state->leasefile);
2507 fd = open(state->leasefile, O_RDONLY);
2508 if (fd != -1 && fstat(fd, &st) == -1) {
2509 close(fd);
2510 fd = -1;
2512 fd_opened = true;
2514 if (fd == -1)
2515 return -1;
2516 retval = -1;
2517 free(state->new);
2518 state->new_len = dhcp_read_lease_fd(fd, (void **)&state->new);
2519 if (fd_opened)
2520 close(fd);
2522 if (ifp->ctx->options & DHCPCD_DUMPLEASE || read_stdin)
2523 return 0;
2525 if (state->new_len == 0) {
2526 retval = 0;
2527 goto ex;
2530 /* If not validating IA's and if they have expired,
2531 * skip to the auth check. */
2532 if (!validate) {
2533 fd = 0;
2534 goto auth;
2537 clock_gettime(CLOCK_MONOTONIC, &state->acquired);
2538 if ((now = time(NULL)) == -1)
2539 goto ex;
2540 state->acquired.tv_sec -= now - st.st_mtime;
2542 /* Check to see if the lease is still valid */
2543 fd = dhcp6_validatelease(ifp, state->new, state->new_len, NULL,
2544 &state->acquired);
2545 if (fd == -1)
2546 goto ex;
2548 if (state->expire != ND6_INFINITE_LIFETIME &&
2549 (time_t)state->expire < now - st.st_mtime &&
2550 !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND))
2552 logdebugx("%s: discarding expired lease", ifp->name);
2553 retval = 0;
2554 goto ex;
2557 auth:
2558 retval = 0;
2559 #ifdef AUTH
2560 /* Authenticate the message */
2561 o = dhcp6_findmoption(state->new, state->new_len, D6_OPTION_AUTH, &ol);
2562 if (o) {
2563 if (dhcp_auth_validate(&state->auth, &ifp->options->auth,
2564 (uint8_t *)state->new, state->new_len, 6, state->new->type,
2565 o, ol) == NULL)
2567 logerr("%s: authentication failed", ifp->name);
2568 goto ex;
2570 if (state->auth.token)
2571 logdebugx("%s: validated using 0x%08" PRIu32,
2572 ifp->name, state->auth.token->secretid);
2573 else
2574 loginfox("%s: accepted reconfigure key", ifp->name);
2575 } else if ((ifp->options->auth.options & DHCPCD_AUTH_SENDREQUIRE) ==
2576 DHCPCD_AUTH_SENDREQUIRE)
2578 logerrx("%s: authentication now required", ifp->name);
2579 goto ex;
2581 #endif
2583 return fd;
2586 dhcp6_freedrop_addrs(ifp, 0, NULL);
2587 unlink(state->leasefile);
2588 free(state->new);
2589 state->new = NULL;
2590 state->new_len = 0;
2591 return retval;
2594 static void
2595 dhcp6_startinit(struct interface *ifp)
2597 struct dhcp6_state *state;
2598 int r;
2599 uint8_t has_ta, has_non_ta;
2600 size_t i;
2602 state = D6_STATE(ifp);
2603 state->state = DH6S_INIT;
2604 state->expire = ND6_INFINITE_LIFETIME;
2605 state->lowpl = ND6_INFINITE_LIFETIME;
2607 dhcp6_addrequestedaddrs(ifp);
2608 has_ta = has_non_ta = 0;
2609 for (i = 0; i < ifp->options->ia_len; i++) {
2610 switch (ifp->options->ia[i].ia_type) {
2611 case D6_OPTION_IA_TA:
2612 has_ta = 1;
2613 break;
2614 default:
2615 has_non_ta = 1;
2619 if (!(ifp->ctx->options & DHCPCD_TEST) &&
2620 !(has_ta && !has_non_ta) &&
2621 ifp->options->reboot != 0)
2623 r = dhcp6_readlease(ifp, 1);
2624 if (r == -1) {
2625 if (errno != ENOENT)
2626 logerr("%s: %s", __func__, state->leasefile);
2627 } else if (r != 0) {
2628 /* RFC 3633 section 12.1 */
2629 #ifndef SMALL
2630 if (dhcp6_hasprefixdelegation(ifp))
2631 dhcp6_startrebind(ifp);
2632 else
2633 #endif
2634 dhcp6_startconfirm(ifp);
2635 return;
2638 dhcp6_startdiscover(ifp);
2641 #ifndef SMALL
2642 static struct ipv6_addr *
2643 dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
2644 const struct if_sla *sla, struct if_ia *if_ia)
2646 struct dhcp6_state *state;
2647 struct in6_addr addr, daddr;
2648 struct ipv6_addr *ia;
2649 int pfxlen, dadcounter;
2650 uint64_t vl;
2652 /* RFC6603 Section 4.2 */
2653 if (strcmp(ifp->name, prefix->iface->name) == 0) {
2654 if (prefix->prefix_exclude_len == 0) {
2655 /* Don't spam the log automatically */
2656 if (sla != NULL)
2657 logwarnx("%s: DHCPv6 server does not support "
2658 "OPTION_PD_EXCLUDE",
2659 ifp->name);
2660 return NULL;
2662 pfxlen = prefix->prefix_exclude_len;
2663 memcpy(&addr, &prefix->prefix_exclude, sizeof(addr));
2664 } else if ((pfxlen = dhcp6_delegateaddr(&addr, ifp, prefix,
2665 sla, if_ia)) == -1)
2666 return NULL;
2668 if (sla != NULL && fls64(sla->suffix) > 128 - pfxlen) {
2669 logerrx("%s: suffix %" PRIu64 " + prefix_len %d > 128",
2670 ifp->name, sla->suffix, pfxlen);
2671 return NULL;
2674 /* Add our suffix */
2675 if (sla != NULL && sla->suffix != 0) {
2676 daddr = addr;
2677 vl = be64dec(addr.s6_addr + 8);
2678 vl |= sla->suffix;
2679 be64enc(daddr.s6_addr + 8, vl);
2680 } else {
2681 dadcounter = ipv6_makeaddr(&daddr, ifp, &addr, pfxlen);
2682 if (dadcounter == -1) {
2683 logerrx("%s: error adding slaac to prefix_len %d",
2684 ifp->name, pfxlen);
2685 return NULL;
2689 /* Find an existing address */
2690 state = D6_STATE(ifp);
2691 TAILQ_FOREACH(ia, &state->addrs, next) {
2692 if (IN6_ARE_ADDR_EQUAL(&ia->addr, &daddr))
2693 break;
2695 if (ia == NULL) {
2696 ia = ipv6_newaddr(ifp, &daddr, (uint8_t)pfxlen, IPV6_AF_ONLINK);
2697 if (ia == NULL)
2698 return NULL;
2699 ia->dadcallback = dhcp6_dadcallback;
2700 memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid));
2701 ia->created = prefix->acquired;
2703 TAILQ_INSERT_TAIL(&state->addrs, ia, next);
2704 TAILQ_INSERT_TAIL(&prefix->pd_pfxs, ia, pd_next);
2706 ia->delegating_prefix = prefix;
2707 ia->prefix = addr;
2708 ia->prefix_len = (uint8_t)pfxlen;
2709 ia->acquired = prefix->acquired;
2710 ia->prefix_pltime = prefix->prefix_pltime;
2711 ia->prefix_vltime = prefix->prefix_vltime;
2713 /* If the prefix length hasn't changed,
2714 * don't install a reject route. */
2715 if (prefix->prefix_len == pfxlen)
2716 prefix->flags |= IPV6_AF_NOREJECT;
2717 else
2718 prefix->flags &= ~IPV6_AF_NOREJECT;
2720 return ia;
2722 #endif
2724 static void
2725 dhcp6_script_try_run(struct interface *ifp, int delegated)
2727 struct dhcp6_state *state;
2728 struct ipv6_addr *ap;
2729 int completed;
2731 state = D6_STATE(ifp);
2732 completed = 1;
2733 /* If all addresses have completed DAD run the script */
2734 TAILQ_FOREACH(ap, &state->addrs, next) {
2735 if (!(ap->flags & IPV6_AF_ADDED))
2736 continue;
2737 if (ap->flags & IPV6_AF_ONLINK) {
2738 if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
2739 ipv6_iffindaddr(ap->iface, &ap->addr,
2740 IN6_IFF_TENTATIVE))
2741 ap->flags |= IPV6_AF_DADCOMPLETED;
2742 if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0
2743 #ifndef SMALL
2744 && ((delegated && ap->delegating_prefix) ||
2745 (!delegated && !ap->delegating_prefix))
2746 #endif
2749 completed = 0;
2750 break;
2754 if (completed) {
2755 script_runreason(ifp, delegated ? "DELEGATED6" : state->reason);
2756 if (!delegated)
2757 dhcpcd_daemonise(ifp->ctx);
2758 } else
2759 logdebugx("%s: waiting for DHCPv6 DAD to complete", ifp->name);
2762 #ifdef SMALL
2763 size_t
2764 dhcp6_find_delegates(__unused struct interface *ifp)
2767 return 0;
2769 #else
2770 static void
2771 dhcp6_delegate_prefix(struct interface *ifp)
2773 struct if_options *ifo;
2774 struct dhcp6_state *state;
2775 struct ipv6_addr *ap;
2776 size_t i, j, k;
2777 struct if_ia *ia;
2778 struct if_sla *sla;
2779 struct interface *ifd;
2780 bool carrier_warned;
2782 ifo = ifp->options;
2783 state = D6_STATE(ifp);
2785 /* Clear the logged flag. */
2786 TAILQ_FOREACH(ap, &state->addrs, next) {
2787 ap->flags &= ~IPV6_AF_DELEGATEDLOG;
2790 TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
2791 if (!ifd->active)
2792 continue;
2793 k = 0;
2794 carrier_warned = false;
2795 TAILQ_FOREACH(ap, &state->addrs, next) {
2796 if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
2797 continue;
2798 if (!(ap->flags & IPV6_AF_DELEGATEDLOG)) {
2799 logfunc_t *logfunc;
2801 if (ap->flags & IPV6_AF_NEW)
2802 logfunc = loginfox;
2803 else
2804 logfunc = logdebugx;
2805 /* We only want to log this the once as we loop
2806 * through many interfaces first. */
2807 ap->flags |= IPV6_AF_DELEGATEDLOG;
2808 logfunc("%s: delegated prefix %s",
2809 ifp->name, ap->saddr);
2810 ap->flags &= ~IPV6_AF_NEW;
2812 for (i = 0; i < ifo->ia_len; i++) {
2813 ia = &ifo->ia[i];
2814 if (ia->ia_type != D6_OPTION_IA_PD)
2815 continue;
2816 if (memcmp(ia->iaid, ap->iaid,
2817 sizeof(ia->iaid)))
2818 continue;
2819 if (ia->sla_len == 0) {
2820 /* no SLA configured, so lets
2821 * automate it */
2822 if (ifd->carrier != LINK_UP) {
2823 logdebugx(
2824 "%s: has no carrier, cannot"
2825 " delegate addresses",
2826 ifd->name);
2827 carrier_warned = true;
2828 break;
2830 if (dhcp6_ifdelegateaddr(ifd, ap,
2831 NULL, ia))
2832 k++;
2834 for (j = 0; j < ia->sla_len; j++) {
2835 sla = &ia->sla[j];
2836 if (strcmp(ifd->name, sla->ifname))
2837 continue;
2838 if (ifd->carrier != LINK_UP) {
2839 logdebugx(
2840 "%s: has no carrier, cannot"
2841 " delegate addresses",
2842 ifd->name);
2843 carrier_warned = true;
2844 break;
2846 if (dhcp6_ifdelegateaddr(ifd, ap,
2847 sla, ia))
2848 k++;
2850 if (carrier_warned)
2851 break;
2853 if (carrier_warned)
2854 break;
2856 if (k && !carrier_warned) {
2857 struct dhcp6_state *s = D6_STATE(ifd);
2859 ipv6_addaddrs(&s->addrs);
2860 dhcp6_script_try_run(ifd, 1);
2864 /* Now all addresses have been added, rebuild the routing table. */
2865 rt_build(ifp->ctx, AF_INET6);
2868 static void
2869 dhcp6_find_delegates1(void *arg)
2872 dhcp6_find_delegates(arg);
2875 size_t
2876 dhcp6_find_delegates(struct interface *ifp)
2878 struct if_options *ifo;
2879 struct dhcp6_state *state;
2880 struct ipv6_addr *ap;
2881 size_t i, j, k;
2882 struct if_ia *ia;
2883 struct if_sla *sla;
2884 struct interface *ifd;
2886 k = 0;
2887 TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
2888 ifo = ifd->options;
2889 state = D6_STATE(ifd);
2890 if (state == NULL || state->state != DH6S_BOUND)
2891 continue;
2892 TAILQ_FOREACH(ap, &state->addrs, next) {
2893 if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
2894 continue;
2895 for (i = 0; i < ifo->ia_len; i++) {
2896 ia = &ifo->ia[i];
2897 if (ia->ia_type != D6_OPTION_IA_PD)
2898 continue;
2899 if (memcmp(ia->iaid, ap->iaid,
2900 sizeof(ia->iaid)))
2901 continue;
2902 for (j = 0; j < ia->sla_len; j++) {
2903 sla = &ia->sla[j];
2904 if (strcmp(ifp->name, sla->ifname))
2905 continue;
2906 if (ipv6_linklocal(ifp) == NULL) {
2907 logdebugx(
2908 "%s: delaying adding"
2909 " delegated addresses for"
2910 " LL address",
2911 ifp->name);
2912 ipv6_addlinklocalcallback(ifp,
2913 dhcp6_find_delegates1, ifp);
2914 return 1;
2916 if (dhcp6_ifdelegateaddr(ifp, ap,
2917 sla, ia))
2918 k++;
2924 if (k) {
2925 loginfox("%s: adding delegated prefixes", ifp->name);
2926 state = D6_STATE(ifp);
2927 state->state = DH6S_DELEGATED;
2928 ipv6_addaddrs(&state->addrs);
2929 rt_build(ifp->ctx, AF_INET6);
2930 dhcp6_script_try_run(ifp, 1);
2932 return k;
2934 #endif
2936 static void
2937 dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
2939 struct dhcp6_state *state = D6_STATE(ifp);
2940 bool has_new = false;
2941 struct ipv6_addr *ia;
2942 logfunc_t *lognewinfo;
2943 struct timespec now;
2945 TAILQ_FOREACH(ia, &state->addrs, next) {
2946 if (ia->flags & IPV6_AF_NEW) {
2947 has_new = true;
2948 break;
2951 lognewinfo = has_new ? loginfox : logdebugx;
2952 if (op != NULL)
2953 lognewinfo("%s: %s received from %s", ifp->name, op, sfrom);
2955 state->reason = NULL;
2956 if (state->state != DH6S_ITIMEDOUT)
2957 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
2958 switch(state->state) {
2959 case DH6S_INFORM:
2960 if (state->reason == NULL)
2961 state->reason = "INFORM6";
2962 /* FALLTHROUGH */
2963 case DH6S_ITIMEDOUT:
2965 struct dhcp6_option *o;
2966 uint16_t ol;
2968 if (state->reason == NULL)
2969 state->reason = "ITIMEDOUT";
2970 o = dhcp6_findmoption(state->new, state->new_len,
2971 D6_OPTION_INFO_REFRESH_TIME, &ol);
2972 if (o == NULL || ol != sizeof(uint32_t))
2973 state->renew = IRT_DEFAULT;
2974 else {
2975 memcpy(&state->renew, o, ol);
2976 state->renew = ntohl(state->renew);
2977 if (state->renew < IRT_MINIMUM)
2978 state->renew = IRT_MINIMUM;
2980 state->rebind = 0;
2981 state->expire = ND6_INFINITE_LIFETIME;
2982 state->lowpl = ND6_INFINITE_LIFETIME;
2984 break;
2986 case DH6S_REQUEST:
2987 if (state->reason == NULL)
2988 state->reason = "BOUND6";
2989 /* FALLTHROUGH */
2990 case DH6S_RENEW:
2991 if (state->reason == NULL)
2992 state->reason = "RENEW6";
2993 /* FALLTHROUGH */
2994 case DH6S_REBIND:
2995 if (state->reason == NULL)
2996 state->reason = "REBIND6";
2997 /* FALLTHROUGH */
2998 case DH6S_CONFIRM:
2999 if (state->reason == NULL)
3000 state->reason = "REBOOT6";
3001 /* FALLTHROUGH */
3002 case DH6S_TIMEDOUT:
3003 if (state->reason == NULL)
3004 state->reason = "TIMEOUT6";
3005 if (state->renew != 0) {
3006 bool all_expired = true;
3008 TAILQ_FOREACH(ia, &state->addrs, next) {
3009 if (ia->flags & IPV6_AF_STALE)
3010 continue;
3011 if (ia->prefix_vltime <= state->renew)
3012 logwarnx(
3013 "%s: %s will expire before renewal",
3014 ifp->name, ia->saddr);
3015 else
3016 all_expired = false;
3018 if (all_expired) {
3019 /* All address's vltime happens at or before
3020 * the configured T1 in the IA.
3021 * This is a badly configured server and we
3022 * have to use our own notion of what
3023 * T1 and T2 should be as a result.
3025 * Doing this violates RFC 3315 22.4:
3026 * In a message sent by a server to a client,
3027 * the client MUST use the values in the T1
3028 * and T2 fields for the T1 and T2 parameters,
3029 * unless those values in those fields are 0.
3031 logwarnx("%s: ignoring T1 %"PRIu32
3032 " due to address expiry",
3033 ifp->name, state->renew);
3034 state->renew = state->rebind = 0;
3037 if (state->renew == 0 && state->lowpl != ND6_INFINITE_LIFETIME)
3038 state->renew = (uint32_t)(state->lowpl * 0.5);
3039 if (state->rebind == 0 && state->lowpl != ND6_INFINITE_LIFETIME)
3040 state->rebind = (uint32_t)(state->lowpl * 0.8);
3041 break;
3042 default:
3043 state->reason = "UNKNOWN6";
3044 break;
3047 clock_gettime(CLOCK_MONOTONIC, &now);
3048 if (state->state == DH6S_TIMEDOUT || state->state == DH6S_ITIMEDOUT) {
3049 struct timespec diff;
3050 uint32_t diffsec;
3052 /* Reduce timers */
3053 timespecsub(&now, &state->acquired, &diff);
3054 diffsec = (uint32_t)diff.tv_sec;
3055 if (state->renew && state->renew != ND6_INFINITE_LIFETIME) {
3056 if (state->renew > diffsec)
3057 state->renew -= diffsec;
3058 else
3059 state->renew = 0;
3061 if (state->rebind && state->rebind != ND6_INFINITE_LIFETIME) {
3062 if (state->rebind > diffsec)
3063 state->rebind -= diffsec;
3064 else
3065 state->rebind = 0;
3067 if (state->expire && state->expire != ND6_INFINITE_LIFETIME) {
3068 if (state->expire > diffsec)
3069 state->expire -= diffsec;
3070 else {
3071 if (!(ifp->options->options &
3072 DHCPCD_LASTLEASE_EXTEND))
3073 return;
3074 state->expire = ND6_INFINITE_LIFETIME;
3077 if (state->expire == ND6_INFINITE_LIFETIME &&
3078 ifp->options->options & DHCPCD_LASTLEASE_EXTEND)
3079 dhcp6_leaseextend(ifp);
3081 /* Restart rebind or renew phases in a second. */
3082 if (state->expire != ND6_INFINITE_LIFETIME) {
3083 if (state->rebind == 0 &&
3084 state->rebind != ND6_INFINITE_LIFETIME)
3085 state->rebind = 1;
3086 else if (state->renew == 0 &&
3087 state->renew != ND6_INFINITE_LIFETIME)
3088 state->renew = 1;
3090 } else
3091 state->acquired = now;
3093 switch (state->state) {
3094 case DH6S_CONFIRM:
3095 case DH6S_TIMEDOUT:
3096 case DH6S_ITIMEDOUT:
3097 break;
3098 default:
3099 free(state->old);
3100 state->old = state->new;
3101 state->old_len = state->new_len;
3102 state->new = state->recv;
3103 state->new_len = state->recv_len;
3104 state->recv = NULL;
3105 state->recv_len = 0;
3106 break;
3109 if (ifp->ctx->options & DHCPCD_TEST)
3110 script_runreason(ifp, "TEST");
3111 else {
3112 bool timed_out;
3114 switch(state->state) {
3115 case DH6S_TIMEDOUT:
3116 case DH6S_ITIMEDOUT:
3117 timed_out = true;
3118 break;
3119 default:
3120 timed_out = false;
3121 break;
3124 switch(state->state) {
3125 case DH6S_INFORM:
3126 case DH6S_ITIMEDOUT:
3127 state->state = DH6S_INFORMED;
3128 break;
3129 default:
3130 state->state = DH6S_BOUND;
3131 break;
3134 if (state->renew && state->renew != ND6_INFINITE_LIFETIME)
3135 eloop_timeout_add_sec(ifp->ctx->eloop,
3136 (time_t)state->renew,
3137 state->state == DH6S_INFORMED ?
3138 dhcp6_startinform : dhcp6_startrenew, ifp);
3139 if (state->rebind && state->rebind != ND6_INFINITE_LIFETIME)
3140 eloop_timeout_add_sec(ifp->ctx->eloop,
3141 (time_t)state->rebind, dhcp6_startrebind, ifp);
3142 if (state->expire != ND6_INFINITE_LIFETIME)
3143 eloop_timeout_add_sec(ifp->ctx->eloop,
3144 (time_t)state->expire, dhcp6_startexpire, ifp);
3145 else if (timed_out)
3146 eloop_timeout_add_sec(ifp->ctx->eloop,
3147 (time_t)state->expire, dhcp6_startdiscover, ifp);
3149 ipv6_addaddrs(&state->addrs);
3150 dhcp6_deprecateaddrs(&state->addrs);
3152 if (state->state == DH6S_INFORMED)
3153 lognewinfo("%s: refresh in %"PRIu32" seconds",
3154 ifp->name, state->renew);
3155 else if (state->renew || state->rebind)
3156 lognewinfo("%s: renew in %"PRIu32", "
3157 "rebind in %"PRIu32", "
3158 "expire in %"PRIu32" seconds",
3159 ifp->name,
3160 state->renew, state->rebind, state->expire);
3161 else if (state->expire == 0)
3162 lognewinfo("%s: will expire", ifp->name);
3163 else
3164 lognewinfo("%s: expire in %"PRIu32" seconds",
3165 ifp->name, state->expire);
3166 rt_build(ifp->ctx, AF_INET6);
3167 if (!timed_out)
3168 dhcp6_writelease(ifp);
3169 #ifndef SMALL
3170 dhcp6_delegate_prefix(ifp);
3171 #endif
3172 dhcp6_script_try_run(ifp, 0);
3175 if (ifp->ctx->options & DHCPCD_TEST ||
3176 (ifp->options->options & DHCPCD_INFORM &&
3177 !(ifp->ctx->options & DHCPCD_MASTER)))
3179 eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
3183 static void
3184 dhcp6_recvif(struct interface *ifp, const char *sfrom,
3185 struct dhcp6_message *r, size_t len)
3187 struct dhcpcd_ctx *ctx;
3188 size_t i;
3189 const char *op;
3190 struct dhcp6_state *state;
3191 uint8_t *o;
3192 uint16_t ol;
3193 const struct dhcp_opt *opt;
3194 const struct if_options *ifo;
3195 bool valid_op;
3196 #ifdef AUTH
3197 uint8_t *auth;
3198 uint16_t auth_len;
3199 #endif
3201 ctx = ifp->ctx;
3202 state = D6_STATE(ifp);
3203 if (state == NULL || state->send == NULL) {
3204 logdebugx("%s: DHCPv6 reply received but not running",
3205 ifp->name);
3206 return;
3209 /* We're already bound and this message is for another machine */
3210 /* XXX DELEGATED? */
3211 if (r->type != DHCP6_RECONFIGURE &&
3212 (state->state == DH6S_BOUND || state->state == DH6S_INFORMED))
3214 logdebugx("%s: DHCPv6 reply received but already bound",
3215 ifp->name);
3216 return;
3219 if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
3220 logdebugx("%s: no DHCPv6 server ID from %s", ifp->name, sfrom);
3221 return;
3224 ifo = ifp->options;
3225 for (i = 0, opt = ctx->dhcp6_opts;
3226 i < ctx->dhcp6_opts_len;
3227 i++, opt++)
3229 if (has_option_mask(ifo->requiremask6, opt->option) &&
3230 !dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
3232 logwarnx("%s: reject DHCPv6 (no option %s) from %s",
3233 ifp->name, opt->var, sfrom);
3234 return;
3236 if (has_option_mask(ifo->rejectmask6, opt->option) &&
3237 dhcp6_findmoption(r, len, (uint16_t)opt->option, NULL))
3239 logwarnx("%s: reject DHCPv6 (option %s) from %s",
3240 ifp->name, opt->var, sfrom);
3241 return;
3245 #ifdef AUTH
3246 /* Authenticate the message */
3247 auth = dhcp6_findmoption(r, len, D6_OPTION_AUTH, &auth_len);
3248 if (auth != NULL) {
3249 if (dhcp_auth_validate(&state->auth, &ifo->auth,
3250 (uint8_t *)r, len, 6, r->type, auth, auth_len) == NULL)
3252 logerr("%s: authentication failed from %s",
3253 ifp->name, sfrom);
3254 return;
3256 if (state->auth.token)
3257 logdebugx("%s: validated using 0x%08" PRIu32,
3258 ifp->name, state->auth.token->secretid);
3259 else
3260 loginfox("%s: accepted reconfigure key", ifp->name);
3261 } else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
3262 if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
3263 logerr("%s: no authentication from %s",
3264 ifp->name, sfrom);
3265 return;
3267 logwarnx("%s: no authentication from %s", ifp->name, sfrom);
3269 #endif
3271 op = dhcp6_get_op(r->type);
3272 valid_op = op != NULL;
3273 switch(r->type) {
3274 case DHCP6_REPLY:
3275 switch(state->state) {
3276 case DH6S_INFORM:
3277 if (dhcp6_checkstatusok(ifp, r, NULL, len) != 0)
3278 return;
3279 break;
3280 case DH6S_CONFIRM:
3281 if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
3283 dhcp6_startdiscover(ifp);
3284 return;
3286 break;
3287 case DH6S_DISCOVER:
3288 /* Only accept REPLY in DISCOVER for RAPID_COMMIT.
3289 * Normally we get an ADVERTISE for a DISCOVER. */
3290 if (!has_option_mask(ifo->requestmask6,
3291 D6_OPTION_RAPID_COMMIT) ||
3292 !dhcp6_findmoption(r, len, D6_OPTION_RAPID_COMMIT,
3293 NULL))
3295 valid_op = false;
3296 break;
3298 /* Validate lease before setting state to REQUEST. */
3299 /* FALLTHROUGH */
3300 case DH6S_REQUEST: /* FALLTHROUGH */
3301 case DH6S_RENEW: /* FALLTHROUGH */
3302 case DH6S_REBIND:
3303 if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
3306 * If we can't use the lease, fallback to
3307 * DISCOVER and try and get a new one.
3309 * This is needed become some servers
3310 * renumber the prefix or address
3311 * and deny the current one before it expires
3312 * rather than sending it back with a zero
3313 * lifetime along with the new prefix or
3314 * address to use.
3315 * This behavior is wrong, but moving to the
3316 * DISCOVER phase works around it.
3318 * The currently held lease is still valid
3319 * until a new one is found.
3321 if (state->state != DH6S_DISCOVER)
3322 dhcp6_startdiscover(ifp);
3323 return;
3325 /* RFC8415 18.2.10.1 */
3326 if ((state->state == DH6S_RENEW ||
3327 state->state == DH6S_REBIND) &&
3328 state->has_no_binding)
3330 dhcp6_startrequest(ifp);
3331 return;
3333 if (state->state == DH6S_DISCOVER)
3334 state->state = DH6S_REQUEST;
3335 break;
3336 default:
3337 valid_op = false;
3338 break;
3340 break;
3341 case DHCP6_ADVERTISE:
3342 if (state->state != DH6S_DISCOVER) {
3343 valid_op = false;
3344 break;
3346 /* RFC7083 */
3347 o = dhcp6_findmoption(r, len, D6_OPTION_SOL_MAX_RT, &ol);
3348 if (o && ol == sizeof(uint32_t)) {
3349 uint32_t max_rt;
3351 memcpy(&max_rt, o, sizeof(max_rt));
3352 max_rt = ntohl(max_rt);
3353 if (max_rt >= 60 && max_rt <= 86400) {
3354 logdebugx("%s: SOL_MAX_RT %llu -> %u",
3355 ifp->name,
3356 (unsigned long long)state->sol_max_rt,
3357 max_rt);
3358 state->sol_max_rt = (time_t)max_rt;
3359 } else
3360 logerr("%s: invalid SOL_MAX_RT %u",
3361 ifp->name, max_rt);
3363 o = dhcp6_findmoption(r, len, D6_OPTION_INF_MAX_RT, &ol);
3364 if (o && ol == sizeof(uint32_t)) {
3365 uint32_t max_rt;
3367 memcpy(&max_rt, o, sizeof(max_rt));
3368 max_rt = ntohl(max_rt);
3369 if (max_rt >= 60 && max_rt <= 86400) {
3370 logdebugx("%s: INF_MAX_RT %llu -> %u",
3371 ifp->name,
3372 (unsigned long long)state->inf_max_rt,
3373 max_rt);
3374 state->inf_max_rt = (time_t)max_rt;
3375 } else
3376 logerrx("%s: invalid INF_MAX_RT %u",
3377 ifp->name, max_rt);
3379 if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
3380 return;
3381 break;
3382 case DHCP6_RECONFIGURE:
3383 #ifdef AUTH
3384 if (auth == NULL) {
3385 #endif
3386 logerrx("%s: unauthenticated %s from %s",
3387 ifp->name, op, sfrom);
3388 if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
3389 return;
3390 #ifdef AUTH
3392 loginfox("%s: %s from %s", ifp->name, op, sfrom);
3393 o = dhcp6_findmoption(r, len, D6_OPTION_RECONF_MSG, &ol);
3394 if (o == NULL) {
3395 logerrx("%s: missing Reconfigure Message option",
3396 ifp->name);
3397 return;
3399 if (ol != 1) {
3400 logerrx("%s: missing Reconfigure Message type",
3401 ifp->name);
3402 return;
3404 switch(*o) {
3405 case DHCP6_RENEW:
3406 if (state->state != DH6S_BOUND) {
3407 logerrx("%s: not bound, ignoring %s",
3408 ifp->name, op);
3409 return;
3411 dhcp6_startrenew(ifp);
3412 break;
3413 case DHCP6_INFORMATION_REQ:
3414 if (state->state != DH6S_INFORMED) {
3415 logerrx("%s: not informed, ignoring %s",
3416 ifp->name, op);
3417 return;
3419 eloop_timeout_delete(ifp->ctx->eloop,
3420 dhcp6_sendinform, ifp);
3421 dhcp6_startinform(ifp);
3422 break;
3423 default:
3424 logerr("%s: unsupported %s type %d",
3425 ifp->name, op, *o);
3426 break;
3428 return;
3429 #else
3430 break;
3431 #endif
3432 default:
3433 logerrx("%s: invalid DHCP6 type %s (%d)",
3434 ifp->name, op, r->type);
3435 return;
3437 if (!valid_op) {
3438 logwarnx("%s: invalid state for DHCP6 type %s (%d)",
3439 ifp->name, op, r->type);
3440 return;
3443 if (state->recv_len < (size_t)len) {
3444 free(state->recv);
3445 state->recv = malloc(len);
3446 if (state->recv == NULL) {
3447 logerr(__func__);
3448 return;
3451 memcpy(state->recv, r, len);
3452 state->recv_len = len;
3454 switch (r->type) {
3455 case DHCP6_ADVERTISE:
3457 struct ipv6_addr *ia;
3459 if (state->state == DH6S_REQUEST) /* rapid commit */
3460 break;
3461 TAILQ_FOREACH(ia, &state->addrs, next) {
3462 if (!(ia->flags & (IPV6_AF_STALE | IPV6_AF_REQUEST)))
3463 break;
3465 if (ia == NULL)
3466 ia = TAILQ_FIRST(&state->addrs);
3467 if (ia == NULL)
3468 loginfox("%s: ADV (no address) from %s",
3469 ifp->name, sfrom);
3470 else
3471 loginfox("%s: ADV %s from %s",
3472 ifp->name, ia->saddr, sfrom);
3473 if (ifp->ctx->options & DHCPCD_TEST)
3474 break;
3475 dhcp6_startrequest(ifp);
3476 return;
3480 dhcp6_bind(ifp, op, sfrom);
3483 static void
3484 dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
3486 struct sockaddr_in6 from;
3487 unsigned char buf[64 * 1024]; /* Maximum UDP message size */
3488 struct iovec iov = {
3489 .iov_base = buf,
3490 .iov_len = sizeof(buf),
3492 unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
3493 struct msghdr msg = {
3494 .msg_name = &from, .msg_namelen = sizeof(from),
3495 .msg_iov = &iov, .msg_iovlen = 1,
3496 .msg_control = ctl, .msg_controllen = sizeof(ctl),
3498 int s;
3499 size_t len;
3500 ssize_t bytes;
3501 char sfrom[INET6_ADDRSTRLEN];
3502 struct interface *ifp;
3503 struct dhcp6_message *r;
3504 const struct dhcp6_state *state;
3505 uint8_t *o;
3506 uint16_t ol;
3508 s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd;
3509 bytes = recvmsg(s, &msg, 0);
3510 if (bytes == -1) {
3511 logerr(__func__);
3512 return;
3514 len = (size_t)bytes;
3515 inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
3516 if (len < sizeof(struct dhcp6_message)) {
3517 logerrx("DHCPv6 packet too short from %s", sfrom);
3518 return;
3521 if (ia != NULL)
3522 ifp = ia->iface;
3523 else {
3524 ifp = if_findifpfromcmsg(ctx, &msg, NULL);
3525 if (ifp == NULL) {
3526 logerr(__func__);
3527 return;
3531 r = (struct dhcp6_message *)buf;
3532 o = dhcp6_findmoption(r, len, D6_OPTION_CLIENTID, &ol);
3533 if (o == NULL || ol != ctx->duid_len ||
3534 memcmp(o, ctx->duid, ol) != 0)
3536 logdebugx("%s: incorrect client ID from %s",
3537 ifp->name, sfrom);
3538 return;
3541 if (dhcp6_findmoption(r, len, D6_OPTION_SERVERID, NULL) == NULL) {
3542 logdebugx("%s: no DHCPv6 server ID from %s",
3543 ifp->name, sfrom);
3544 return;
3547 if (r->type == DHCP6_RECONFIGURE) {
3548 logdebugx("%s: RECONFIGURE6 recv from %s,"
3549 " sending to all interfaces",
3550 ifp->name, sfrom);
3551 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
3552 state = D6_CSTATE(ifp);
3553 if (state != NULL && state->send != NULL)
3554 dhcp6_recvif(ifp, sfrom, r, len);
3556 return;
3559 state = D6_CSTATE(ifp);
3560 if (state == NULL ||
3561 r->xid[0] != state->send->xid[0] ||
3562 r->xid[1] != state->send->xid[1] ||
3563 r->xid[2] != state->send->xid[2])
3565 struct interface *ifp1;
3566 const struct dhcp6_state *state1;
3568 /* Find an interface with a matching xid. */
3569 TAILQ_FOREACH(ifp1, ctx->ifaces, next) {
3570 state1 = D6_CSTATE(ifp1);
3571 if (state1 == NULL || state1->send == NULL)
3572 continue;
3573 if (r->xid[0] == state1->send->xid[0] &&
3574 r->xid[1] == state1->send->xid[1] &&
3575 r->xid[2] == state1->send->xid[2])
3576 break;
3579 if (ifp1 == NULL) {
3580 if (state != NULL)
3581 logdebugx("%s: wrong xid 0x%02x%02x%02x"
3582 " (expecting 0x%02x%02x%02x) from %s",
3583 ifp->name,
3584 r->xid[0], r->xid[1], r->xid[2],
3585 state->send->xid[0],
3586 state->send->xid[1],
3587 state->send->xid[2],
3588 sfrom);
3589 return;
3591 logdebugx("%s: redirecting DHCP6 message to %s",
3592 ifp->name, ifp1->name);
3593 ifp = ifp1;
3596 dhcp6_recvif(ifp, sfrom, r, len);
3599 static void
3600 dhcp6_recvaddr(void *arg)
3602 struct ipv6_addr *ia = arg;
3604 dhcp6_recv(ia->iface->ctx, ia);
3607 static void
3608 dhcp6_recvctx(void *arg)
3610 struct dhcpcd_ctx *ctx = arg;
3612 dhcp6_recv(ctx, NULL);
3615 static int
3616 dhcp6_listen(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
3618 struct sockaddr_in6 sa;
3619 int n, s;
3621 #define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
3622 s = xsocket(PF_INET6, SOCK_DGRAM | SOCK_FLAGS, IPPROTO_UDP);
3623 #undef SOCK_FLAGS
3624 if (s == -1)
3625 goto errexit;
3627 n = 1;
3628 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) == -1)
3629 goto errexit;
3631 memset(&sa, 0, sizeof(sa));
3632 sa.sin6_family = AF_INET6;
3633 sa.sin6_port = htons(DHCP6_CLIENT_PORT);
3634 #ifdef BSD
3635 sa.sin6_len = sizeof(sa);
3636 #endif
3638 if (ia != NULL) {
3639 memcpy(&sa.sin6_addr, &ia->addr, sizeof(sa.sin6_addr));
3640 sa.sin6_scope_id = ia->iface->index;
3643 if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1)
3644 goto errexit;
3646 n = 1;
3647 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &n, sizeof(n)) == -1)
3648 goto errexit;
3650 if (ia != NULL) {
3651 ia->dhcp6_fd = s;
3652 eloop_event_add(ctx->eloop, s, dhcp6_recvaddr, ia);
3655 return s;
3657 errexit:
3658 logerr(__func__);
3659 if (s != -1)
3660 close(s);
3661 return -1;
3664 #ifndef SMALL
3665 static void
3666 dhcp6_activateinterfaces(struct interface *ifp)
3668 struct interface *ifd;
3669 size_t i, j;
3670 struct if_ia *ia;
3671 struct if_sla *sla;
3673 for (i = 0; i < ifp->options->ia_len; i++) {
3674 ia = &ifp->options->ia[i];
3675 if (ia->ia_type != D6_OPTION_IA_PD)
3676 continue;
3677 for (j = 0; j < ia->sla_len; j++) {
3678 sla = &ia->sla[j];
3679 ifd = if_find(ifp->ctx->ifaces, sla->ifname);
3680 if (ifd == NULL) {
3681 logwarn("%s: cannot delegate to %s",
3682 ifp->name, sla->ifname);
3683 continue;
3685 if (!ifd->active) {
3686 loginfox("%s: activating for delegation",
3687 sla->ifname);
3688 dhcpcd_activateinterface(ifd,
3689 DHCPCD_IPV6 | DHCPCD_DHCP6);
3694 #endif
3696 static void
3697 dhcp6_start1(void *arg)
3699 struct interface *ifp = arg;
3700 struct dhcpcd_ctx *ctx = ifp->ctx;
3701 struct if_options *ifo = ifp->options;
3702 struct dhcp6_state *state;
3703 size_t i;
3704 const struct dhcp_compat *dhc;
3706 if (ctx->dhcp6_fd == -1 && ctx->options & DHCPCD_MASTER) {
3707 ctx->dhcp6_fd = dhcp6_listen(ctx, NULL);
3708 if (ctx->dhcp6_fd == -1)
3709 return;
3710 eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx);
3713 state = D6_STATE(ifp);
3714 /* If no DHCPv6 options are configured,
3715 match configured DHCPv4 options to DHCPv6 equivalents. */
3716 for (i = 0; i < sizeof(ifo->requestmask6); i++) {
3717 if (ifo->requestmask6[i] != '\0')
3718 break;
3720 if (i == sizeof(ifo->requestmask6)) {
3721 for (dhc = dhcp_compats; dhc->dhcp_opt; dhc++) {
3722 if (has_option_mask(ifo->requestmask, dhc->dhcp_opt))
3723 add_option_mask(ifo->requestmask6,
3724 dhc->dhcp6_opt);
3726 if (ifo->fqdn != FQDN_DISABLE ||
3727 ifo->options & DHCPCD_HOSTNAME)
3728 add_option_mask(ifo->requestmask6, D6_OPTION_FQDN);
3731 #ifndef SMALL
3732 /* Rapid commit won't work with Prefix Delegation Exclusion */
3733 if (dhcp6_findselfsla(ifp))
3734 del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);
3735 #endif
3737 if (state->state == DH6S_INFORM) {
3738 add_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
3739 dhcp6_startinform(ifp);
3740 } else {
3741 del_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
3742 dhcp6_startinit(ifp);
3745 #ifndef SMALL
3746 dhcp6_activateinterfaces(ifp);
3747 #endif
3751 dhcp6_start(struct interface *ifp, enum DH6S init_state)
3753 struct dhcp6_state *state;
3755 state = D6_STATE(ifp);
3756 if (state != NULL) {
3757 switch (init_state) {
3758 case DH6S_INIT:
3759 goto gogogo;
3760 case DH6S_INFORM:
3761 if (state->state == DH6S_INFORMED)
3762 dhcp6_startinform(ifp);
3763 break;
3764 case DH6S_REQUEST:
3765 if (ifp->options->options & DHCPCD_DHCP6 &&
3766 (state->state == DH6S_INFORM ||
3767 state->state == DH6S_INFORMED ||
3768 state->state == DH6S_DELEGATED))
3770 /* Change from stateless to stateful */
3771 init_state = DH6S_INIT;
3772 goto gogogo;
3774 break;
3775 case DH6S_CONFIRM:
3776 init_state = DH6S_INIT;
3777 goto gogogo;
3778 default:
3779 /* Not possible, but sushes some compiler warnings. */
3780 break;
3782 return 0;
3783 } else {
3784 switch (init_state) {
3785 case DH6S_CONFIRM:
3786 /* No DHCPv6 config, no existing state
3787 * so nothing to do. */
3788 return 0;
3789 case DH6S_INFORM:
3790 break;
3791 default:
3792 init_state = DH6S_INIT;
3793 break;
3797 if (!(ifp->options->options & DHCPCD_DHCP6))
3798 return 0;
3800 ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
3801 state = D6_STATE(ifp);
3802 if (state == NULL)
3803 return -1;
3805 state->sol_max_rt = SOL_MAX_RT;
3806 state->inf_max_rt = INF_MAX_RT;
3807 TAILQ_INIT(&state->addrs);
3809 gogogo:
3810 state->state = init_state;
3811 state->lerror = 0;
3812 dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
3813 AF_INET6, ifp);
3814 if (ipv6_linklocal(ifp) == NULL) {
3815 logdebugx("%s: delaying DHCPv6 soliciation for LL address",
3816 ifp->name);
3817 ipv6_addlinklocalcallback(ifp, dhcp6_start1, ifp);
3818 return 0;
3821 dhcp6_start1(ifp);
3822 return 0;
3825 void
3826 dhcp6_reboot(struct interface *ifp)
3828 struct dhcp6_state *state;
3830 state = D6_STATE(ifp);
3831 if (state == NULL)
3832 return;
3834 state->lerror = 0;
3835 switch (state->state) {
3836 case DH6S_BOUND:
3837 dhcp6_startrebind(ifp);
3838 break;
3839 case DH6S_INFORMED:
3840 dhcp6_startinform(ifp);
3841 break;
3842 default:
3843 dhcp6_startdiscover(ifp);
3844 break;
3848 static void
3849 dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
3851 struct dhcp6_state *state;
3852 struct dhcpcd_ctx *ctx;
3853 unsigned long long options;
3855 if (ifp->options)
3856 options = ifp->options->options;
3857 else
3858 options = ifp->ctx->options;
3860 if (ifp->ctx->eloop)
3861 eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
3863 #ifndef SMALL
3864 /* If we're dropping the lease, drop delegated addresses.
3865 * If, for whatever reason, we don't drop them in the future
3866 * then they should at least be marked as deprecated (pltime 0). */
3867 if (drop && (options & DHCPCD_NODROP) != DHCPCD_NODROP)
3868 dhcp6_delete_delegates(ifp);
3869 #endif
3871 state = D6_STATE(ifp);
3872 if (state) {
3873 /* Failure to send the release may cause this function to
3874 * re-enter */
3875 if (state->state == DH6S_RELEASE) {
3876 dhcp6_finishrelease(ifp);
3877 return;
3880 if (drop && options & DHCPCD_RELEASE &&
3881 state->state != DH6S_DELEGATED)
3883 if (ifp->carrier == LINK_UP &&
3884 state->state != DH6S_RELEASED &&
3885 state->state != DH6S_INFORMED)
3887 dhcp6_startrelease(ifp);
3888 return;
3890 unlink(state->leasefile);
3892 dhcp6_freedrop_addrs(ifp, drop, NULL);
3893 free(state->old);
3894 state->old = state->new;
3895 state->old_len = state->new_len;
3896 state->new = NULL;
3897 state->new_len = 0;
3898 if (drop && state->old &&
3899 (options & DHCPCD_NODROP) != DHCPCD_NODROP)
3901 if (reason == NULL)
3902 reason = "STOP6";
3903 script_runreason(ifp, reason);
3905 free(state->old);
3906 free(state->send);
3907 free(state->recv);
3908 free(state);
3909 ifp->if_data[IF_DATA_DHCP6] = NULL;
3912 /* If we don't have any more DHCP6 enabled interfaces,
3913 * close the global socket and release resources */
3914 ctx = ifp->ctx;
3915 if (ctx->ifaces) {
3916 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
3917 if (D6_STATE(ifp))
3918 break;
3921 if (ifp == NULL && ctx->dhcp6_fd != -1) {
3922 eloop_event_delete(ctx->eloop, ctx->dhcp6_fd);
3923 close(ctx->dhcp6_fd);
3924 ctx->dhcp6_fd = -1;
3928 void
3929 dhcp6_drop(struct interface *ifp, const char *reason)
3932 dhcp6_freedrop(ifp, 1, reason);
3935 void
3936 dhcp6_free(struct interface *ifp)
3939 dhcp6_freedrop(ifp, 0, NULL);
3942 void
3943 dhcp6_abort(struct interface *ifp)
3945 #ifdef ND6_ADVERTISE
3946 struct dhcp6_state *state;
3947 struct ipv6_addr *ia;
3948 #endif
3950 eloop_timeout_delete(ifp->ctx->eloop, dhcp6_start1, ifp);
3951 #ifdef ND6_ADVERTISE
3952 state = D6_STATE(ifp);
3953 if (state == NULL)
3954 return;
3955 TAILQ_FOREACH(ia, &state->addrs, next) {
3956 ipv6nd_advertise(ia);
3958 #endif
3961 void
3962 dhcp6_handleifa(int cmd, struct ipv6_addr *ia, pid_t pid)
3964 struct dhcp6_state *state;
3965 struct interface *ifp = ia->iface;
3967 /* If not running in master mode, listen to this address */
3968 if (cmd == RTM_NEWADDR &&
3969 !(ia->addr_flags & IN6_IFF_NOTUSEABLE) &&
3970 ifp->active == IF_ACTIVE_USER &&
3971 !(ifp->ctx->options & DHCPCD_MASTER) &&
3972 ifp->options->options & DHCPCD_DHCP6 &&
3973 ia->dhcp6_fd == -1)
3974 dhcp6_listen(ia->iface->ctx, ia);
3976 if ((state = D6_STATE(ifp)) != NULL)
3977 ipv6_handleifa_addrs(cmd, &state->addrs, ia, pid);
3980 ssize_t
3981 dhcp6_env(FILE *fp, const char *prefix, const struct interface *ifp,
3982 const struct dhcp6_message *m, size_t len)
3984 const struct if_options *ifo;
3985 struct dhcp_opt *opt, *vo;
3986 const uint8_t *p;
3987 struct dhcp6_option o;
3988 size_t i;
3989 char *pfx;
3990 uint32_t en;
3991 const struct dhcpcd_ctx *ctx;
3992 #ifndef SMALL
3993 const struct dhcp6_state *state;
3994 const struct ipv6_addr *ap;
3995 #endif
3997 if (m == NULL)
3998 goto delegated;
4000 if (len < sizeof(*m)) {
4001 /* Should be impossible with guards at packet in
4002 * and reading leases */
4003 errno = EINVAL;
4004 return -1;
4007 ifo = ifp->options;
4008 ctx = ifp->ctx;
4010 /* Zero our indexes */
4011 for (i = 0, opt = ctx->dhcp6_opts;
4012 i < ctx->dhcp6_opts_len;
4013 i++, opt++)
4014 dhcp_zero_index(opt);
4015 for (i = 0, opt = ifp->options->dhcp6_override;
4016 i < ifp->options->dhcp6_override_len;
4017 i++, opt++)
4018 dhcp_zero_index(opt);
4019 for (i = 0, opt = ctx->vivso;
4020 i < ctx->vivso_len;
4021 i++, opt++)
4022 dhcp_zero_index(opt);
4023 if (asprintf(&pfx, "%s_dhcp6", prefix) == -1)
4024 return -1;
4026 /* Unlike DHCP, DHCPv6 options *may* occur more than once.
4027 * There is also no provision for option concatenation unlike DHCP. */
4028 p = (const uint8_t *)m + sizeof(*m);
4029 len -= sizeof(*m);
4030 for (; len != 0; p += o.len, len -= o.len) {
4031 if (len < sizeof(o)) {
4032 errno = EINVAL;
4033 break;
4035 memcpy(&o, p, sizeof(o));
4036 p += sizeof(o);
4037 len -= sizeof(o);
4038 o.len = ntohs(o.len);
4039 if (len < o.len) {
4040 errno = EINVAL;
4041 break;
4043 o.code = ntohs(o.code);
4044 if (has_option_mask(ifo->nomask6, o.code))
4045 continue;
4046 for (i = 0, opt = ifo->dhcp6_override;
4047 i < ifo->dhcp6_override_len;
4048 i++, opt++)
4049 if (opt->option == o.code)
4050 break;
4051 if (i == ifo->dhcp6_override_len &&
4052 o.code == D6_OPTION_VENDOR_OPTS &&
4053 o.len > sizeof(en))
4055 memcpy(&en, p, sizeof(en));
4056 en = ntohl(en);
4057 vo = vivso_find(en, ifp);
4058 } else
4059 vo = NULL;
4060 if (i == ifo->dhcp6_override_len) {
4061 for (i = 0, opt = ctx->dhcp6_opts;
4062 i < ctx->dhcp6_opts_len;
4063 i++, opt++)
4064 if (opt->option == o.code)
4065 break;
4066 if (i == ctx->dhcp6_opts_len)
4067 opt = NULL;
4069 if (opt) {
4070 dhcp_envoption(ifp->ctx,
4071 fp, pfx, ifp->name,
4072 opt, dhcp6_getoption, p, o.len);
4074 if (vo) {
4075 dhcp_envoption(ifp->ctx,
4076 fp, pfx, ifp->name,
4077 vo, dhcp6_getoption,
4078 p + sizeof(en),
4079 o.len - sizeof(en));
4082 free(pfx);
4084 delegated:
4085 #ifndef SMALL
4086 /* Needed for Delegated Prefixes */
4087 state = D6_CSTATE(ifp);
4088 TAILQ_FOREACH(ap, &state->addrs, next) {
4089 if (ap->delegating_prefix)
4090 break;
4092 if (ap == NULL)
4093 return 1;
4094 if (fprintf(fp, "%s_delegated_dhcp6_prefix=", prefix) == -1)
4095 return -1;
4096 TAILQ_FOREACH(ap, &state->addrs, next) {
4097 if (ap->delegating_prefix == NULL)
4098 continue;
4099 if (ap != TAILQ_FIRST(&state->addrs)) {
4100 if (fputc(' ', fp) == EOF)
4101 return -1;
4103 if (fprintf(fp, "%s", ap->saddr) == -1)
4104 return -1;
4106 if (fputc('\0', fp) == EOF)
4107 return -1;
4108 #endif
4110 return 1;
4114 dhcp6_dump(struct interface *ifp)
4116 struct dhcp6_state *state;
4118 ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
4119 if (state == NULL) {
4120 logerr(__func__);
4121 return -1;
4123 TAILQ_INIT(&state->addrs);
4124 dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
4125 AF_INET6, ifp);
4126 if (dhcp6_readlease(ifp, 0) == -1) {
4127 logerr("%s: %s", __func__,
4128 *ifp->name ? ifp->name : state->leasefile);
4129 return -1;
4131 state->reason = "DUMP6";
4132 return script_runreason(ifp, state->reason);
4134 #endif