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