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