[packages/dhcpcd] - correct patch

arekm arekm at pld-linux.org
Wed Nov 6 14:56:58 CET 2019


commit 4269699a1aad65a58e2fce90ee2e17a9f9cda6cf
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Wed Nov 6 14:56:48 2019 +0100

    - correct patch

 cpuhog.patch     |   52 +
 dhcpcd-git.patch | 3014 ------------------------------------------------------
 2 files changed, 52 insertions(+), 3014 deletions(-)
---
diff --git a/cpuhog.patch b/cpuhog.patch
new file mode 100644
index 0000000..58863ae
--- /dev/null
+++ b/cpuhog.patch
@@ -0,0 +1,52 @@
+From 73ac184333f77b38a8b4c4202c2928278e2237ca Mon Sep 17 00:00:00 2001
+From: Roy Marples <roy at marples.name>
+Date: Tue, 5 Nov 2019 15:52:57 +0000
+Subject: INET: Fix corruption of IPv4 address flags when renewing
+
+What a mistaka to maka!
+---
+ src/ipv4.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+(limited to 'src')
+
+diff --git a/src/ipv4.c b/src/ipv4.c
+index fd2a15d7..53550696 100644
+--- a/src/ipv4.c
++++ b/src/ipv4.c
+@@ -654,7 +654,7 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
+ #endif
+ 		ia->flags = IPV4_AF_NEW;
+ 	} else
+-		ia->flags |= ~IPV4_AF_NEW;
++		ia->flags &= ~IPV4_AF_NEW;
+ 
+ 	ia->mask = *mask;
+ 	ia->brd = *bcast;
+@@ -952,15 +952,13 @@ ipv4_free(struct interface *ifp)
+ 	struct ipv4_state *state;
+ 	struct ipv4_addr *ia;
+ 
+-	if (ifp) {
+-		state = IPV4_STATE(ifp);
+-		if (state) {
+-		        while ((ia = TAILQ_FIRST(&state->addrs))) {
+-				TAILQ_REMOVE(&state->addrs, ia, next);
+-				free(ia);
+-			}
+-			free(state->buffer);
+-			free(state);
+-		}
++	if (ifp == NULL || (state = IPV4_STATE(ifp)) == NULL)
++		return;
++
++	while ((ia = TAILQ_FIRST(&state->addrs))) {
++		TAILQ_REMOVE(&state->addrs, ia, next);
++		free(ia);
+ 	}
++	free(state->buffer);
++	free(state);
+ }
+-- 
+cgit v1.2.1
+
diff --git a/dhcpcd-git.patch b/dhcpcd-git.patch
deleted file mode 100644
index 9a77b9c..0000000
--- a/dhcpcd-git.patch
+++ /dev/null
@@ -1,3014 +0,0 @@
-diff -urN dhcpcd-6.4.0.org/configure dhcpcd-6.4.0/configure
---- dhcpcd-6.4.0.org/configure	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/configure	2014-07-05 21:47:22.000000000 +0200
-@@ -272,8 +272,18 @@
- fi
- 
- echo "Using compiler .. $CC"
--if ! type "$CC" >/dev/null 2>&1; then
--	echo "$CC is not an executable"
-+cat <<EOF >_test.c
-+int main(void) {
-+	return 0;
-+}
-+EOF
-+_CC=false
-+if $CC _test.c -o _test >/dev/null 2>&1; then
-+	[ -x _test ] && _CC=true
-+fi
-+rm -f _test.c _test
-+if ! $_CC; then
-+	echo "$CC does not create executables"
- 	exit 1
- fi
- [ "$CC" != cc ] && echo "CC=	$CC" >>$CONFIG_MK
-@@ -422,7 +432,7 @@
- EOF
- if $XCC _getifaddrs.c -o _getifaddrs 2>/dev/null; then
- 	echo "yes"
--elif $XCC _getifaddrs.c -o _getifaddrs -lsocket >/dev/null; then
-+elif $XCC _getifaddrs.c -o _getifaddrs -lsocket 2>/dev/null; then
- 	echo "yes (-lsocket)"
- 	echo "LDADD+=		-lsocket" >>$CONFIG_MK
- else
-diff -urN dhcpcd-6.4.0.org/control.c dhcpcd-6.4.0/control.c
---- dhcpcd-6.4.0.org/control.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/control.c	2014-07-05 21:47:22.000000000 +0200
-@@ -52,8 +52,9 @@
- control_handle_data(void *arg)
- {
- 	struct fd_list *l = arg, *lp, *last;
--	char buffer[1024], *e, *p, *argvp[255], **ap;
-+	char buffer[1024], *e, *p, *argvp[255], **ap, *a;
- 	ssize_t bytes;
-+	size_t len;
- 	int argc;
- 
- 	bytes = read(l->fd, buffer, sizeof(buffer) - 1);
-@@ -79,14 +80,28 @@
- 	buffer[bytes] = '\0';
- 	p = buffer;
- 	e = buffer + bytes;
--	argc = 0;
--	ap = argvp;
--	while (p < e && (size_t)argc < sizeof(argvp)) {
--		argc++;
--		*ap++ = p;
--		p += strlen(p) + 1;
-+
-+	/* Each command is \n terminated
-+	 * Each argument is NULL separated */
-+	while (p < e) {
-+		argc = 0;
-+		ap = argvp;
-+		while (p < e) {
-+			argc++;
-+			if ((size_t)argc > sizeof(argvp)) {
-+				errno = ENOBUFS;
-+				return;
-+			}
-+			a = *ap++ = p;
-+			len = strlen(p);
-+			p += len + 1;
-+			if (a[len - 1] == '\n') {
-+				a[len - 1] = '\0';
-+				break;
-+			}
-+		}
-+		dhcpcd_handleargs(l->ctx, l, argc, argvp);
- 	}
--	dhcpcd_handleargs(l->ctx, l, argc, argvp);
- }
- 
- static void
-diff -urN dhcpcd-6.4.0.org/defs.h dhcpcd-6.4.0/defs.h
---- dhcpcd-6.4.0.org/defs.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/defs.h	2014-07-05 21:47:22.000000000 +0200
-@@ -49,7 +49,7 @@
- # define LEASEFILE		DBDIR "/" PACKAGE "-%s.lease"
- #endif
- #ifndef LEASEFILE6
--# define LEASEFILE6		DBDIR "/" PACKAGE "-%s.lease6"
-+# define LEASEFILE6		DBDIR "/" PACKAGE "-%s%s.lease6"
- #endif
- #ifndef PIDFILE
- # define PIDFILE		RUNDIR "/" PACKAGE "%s%s%s.pid"
-diff -urN dhcpcd-6.4.0.org/dhcp6.c dhcpcd-6.4.0/dhcp6.c
---- dhcpcd-6.4.0.org/dhcp6.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp6.c	2014-07-05 21:47:22.000000000 +0200
-@@ -121,13 +121,22 @@
- };
- 
- void
--dhcp6_printoptions(const struct dhcpcd_ctx *ctx)
-+dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
-+    const struct dhcp_opt *opts, size_t opts_len)
- {
--	size_t i;
--	const struct dhcp_opt *opt;
-+	size_t i, j;
-+	const struct dhcp_opt *opt, *opt2;
- 
- 	for (i = 0, opt = ctx->dhcp6_opts;
- 	    i < ctx->dhcp6_opts_len; i++, opt++)
-+	{
-+		for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
-+			if (opt2->option == opt->option)
-+				break;
-+		if (j == opts_len)
-+			printf("%05d %s\n", opt->option, opt->var);
-+	}
-+	for (i = 0, opt = opts; i < opts_len; i++, opt++)
- 		printf("%05d %s\n", opt->option, opt->var);
- }
- 
-@@ -304,24 +313,112 @@
- 	m->xid[2] = xid & 0xff;
- }
- 
-+static const struct if_sla *
-+dhcp6_findselfsla(struct interface *ifp, const uint8_t *iaid)
-+{
-+	size_t i, j;
-+
-+	for (i = 0; i < ifp->options->ia_len; i++) {
-+		if (iaid == NULL ||
-+		    memcmp(&ifp->options->ia[i].iaid, iaid,
-+		    sizeof(ifp->options->ia[i].iaid)) == 0)
-+		{
-+			for (j = 0; j < ifp->options->ia[i].sla_len; j++) {
-+				if (strcmp(ifp->options->ia[i].sla[j].ifname,
-+				    ifp->name) == 0)
-+					return &ifp->options->ia[i].sla[j];
-+			}
-+		}
-+	}
-+	return NULL;
-+}
-+
-+static int
-+dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
-+    const struct ipv6_addr *prefix, const struct if_sla *sla)
-+{
-+	struct dhcp6_state *state;
-+	struct if_sla asla;
-+	char iabuf[INET6_ADDRSTRLEN];
-+	const char *ia;
-+
-+	state = D6_STATE(ifp);
-+	if (state == NULL) {
-+		ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
-+		state = D6_STATE(ifp);
-+		if (state == NULL) {
-+			syslog(LOG_ERR, "%s: %m", __func__);
-+			return -1;
-+		}
-+
-+		TAILQ_INIT(&state->addrs);
-+		state->state = DH6S_DELEGATED;
-+		state->reason = "DELEGATED6";
-+	}
-+
-+	if (sla == NULL || sla->sla_set == 0) {
-+		struct interface *ifi;
-+		unsigned int idx;
-+		int bits;
-+
-+		asla.sla = ifp->index;
-+		/* Work out our largest index delegating to. */
-+		idx = 0;
-+		TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
-+			if (ifi != ifp && ifi->index > idx)
-+				idx = ifi->index;
-+		}
-+		bits = ffs((int)idx);
-+		if (prefix->prefix_len + bits > UINT8_MAX)
-+			asla.prefix_len = UINT8_MAX;
-+		else {
-+			asla.prefix_len = prefix->prefix_len + (uint8_t)bits;
-+
-+			/* Make a 64 prefix by default, as this maks SLAAC
-+			 * possible. Otherwise round up to the nearest octet. */
-+			if (asla.prefix_len <= 64)
-+				asla.prefix_len = 64;
-+			else
-+				asla.prefix_len = ROUNDUP8(asla.prefix_len);
-+
-+		}
-+		sla = &asla;
-+	}
-+
-+	if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
-+		sla->sla, addr, sla->prefix_len) == -1)
-+	{
-+		ia = inet_ntop(AF_INET6, &prefix->prefix.s6_addr,
-+		    iabuf, sizeof(iabuf));
-+		syslog(LOG_ERR, "%s: invalid prefix %s/%d + %d/%d: %m",
-+			ifp->name, ia, prefix->prefix_len,
-+			sla->sla, sla->prefix_len);
-+		return -1;
-+	}
-+
-+	return 0;
-+}
-+
- static int
- dhcp6_makemessage(struct interface *ifp)
- {
- 	struct dhcp6_state *state;
- 	struct dhcp6_message *m;
--	struct dhcp6_option *o, *so;
-+	struct dhcp6_option *o, *so, *eo;
- 	const struct dhcp6_option *si, *unicast;
--	size_t l, len, ml, auth_len;
-+	size_t l, n, len, ml, auth_len;
- 	uint8_t u8, type;
- 	uint16_t *u16, n_options;
- 	struct if_options *ifo;
--	const struct dhcp_opt *opt;
-+	const struct dhcp_opt *opt, *opt2;
- 	uint8_t IA, *p;
- 	uint32_t u32;
- 	const struct ipv6_addr *ap;
- 	char hbuf[HOSTNAME_MAX_LEN + 1];
- 	const char *hostname;
- 	int fqdn;
-+	const struct if_sla *sla;
-+	struct in6_addr addr;
- 
- 	state = D6_STATE(ifp);
- 	if (state->send) {
-@@ -356,6 +453,15 @@
- 		    l < ifp->ctx->dhcp6_opts_len;
- 		    l++, opt++)
- 		{
-+			for (n = 0, opt2 = ifo->dhcp6_override;
-+			    n < ifo->dhcp6_override_len;
-+			    n++, opt2++)
-+			{
-+				if (opt->option == opt2->option)
-+					break;
-+			}
-+			if (n < ifo->dhcp6_override_len)
-+			    continue;
- 			if (!(opt->type & NOREQ) &&
- 			    (opt->type & REQUEST ||
- 			    has_option_mask(ifo->requestmask6, opt->option)))
-@@ -364,6 +470,22 @@
- 				len += sizeof(*u16);
- 			}
- 		}
-+		for (l = 0, opt = ifo->dhcp6_override;
-+		    l < ifo->dhcp6_override_len;
-+		    l++, opt++)
-+		{
-+			if (!(opt->type & NOREQ) &&
-+			    (opt->type & REQUEST ||
-+			    has_option_mask(ifo->requestmask6, opt->option)))
-+			{
-+				n_options++;
-+				len += sizeof(*u16);
-+			}
-+		}
-+		if (dhcp6_findselfsla(ifp, NULL)) {
-+			n_options++;
-+			len += sizeof(*u16);
-+		}
- 		if (len)
- 			len += sizeof(*o);
- 
-@@ -405,25 +527,43 @@
- 	case DH6S_REBIND:
- 		/* FALLTHROUGH */
- 	case DH6S_CONFIRM:
-+		/* FALLTHROUGH */
-+	case DH6S_DISCOVER:
- 		if (m == NULL) {
- 			m = state->new;
- 			ml = state->new_len;
- 		}
- 		TAILQ_FOREACH(ap, &state->addrs, next) {
--			if (ap->prefix_vltime == 0)
-+			if (ap->prefix_vltime == 0 &&
-+			    !(ap->flags & IPV6_AF_REQUEST))
- 				continue;
--			if (ifo->ia_type == D6_OPTION_IA_PD)
--				len += sizeof(*o) + sizeof(u8) +
--				    sizeof(u32) + sizeof(u32) +
--				    sizeof(ap->prefix.s6_addr);
--			else
-+			if (ap->ia_type == D6_OPTION_IA_PD) {
-+				if (!(ifo->options & DHCPCD_NOPFXDLG)) {
-+					len += sizeof(*o) + sizeof(u8) +
-+					    sizeof(u32) + sizeof(u32) +
-+					    sizeof(ap->prefix.s6_addr);
-+					sla = dhcp6_findselfsla(ifp, ap->iaid);
-+					if (sla)
-+						len += sizeof(*o) + 1 +
-+						    ((sla->prefix_len -
-+						    ap->prefix_len - 1) / NBBY)
-+						    + 1;
-+
-+				}
-+			} else if (!(ifo->options & DHCPCD_PFXDLGONLY))
- 				len += sizeof(*o) + sizeof(ap->addr.s6_addr) +
- 				    sizeof(u32) + sizeof(u32);
- 		}
- 		/* FALLTHROUGH */
--	case DH6S_INIT: /* FALLTHROUGH */
--	case DH6S_DISCOVER:
--		len += ifo->ia_len * (sizeof(*o) + (sizeof(u32) * 3));
-+	case DH6S_INIT:
-+		for (l = 0; l < ifo->ia_len; l++) {
-+			if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
-+				if (ifo->options & DHCPCD_NOPFXDLG)
-+					continue;
-+			} else if (ifo->options & DHCPCD_PFXDLGONLY)
-+				continue;
-+			len += sizeof(*o) + (sizeof(u32) * 3);
-+		}
- 		IA = 1;
- 		break;
- 	default:
-@@ -528,20 +668,26 @@
- 	}
- 
- 	for (l = 0; IA && l < ifo->ia_len; l++) {
-+		if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
-+			if (ifo->options & DHCPCD_NOPFXDLG)
-+				continue;
-+		} else if (ifo->options & DHCPCD_PFXDLGONLY)
-+			continue;
- 		o = D6_NEXT_OPTION(o);
--		o->code = htons(ifo->ia_type);
-+		o->code = htons(ifo->ia[l].ia_type);
- 		o->len = htons(sizeof(u32) + sizeof(u32) + sizeof(u32));
- 		p = D6_OPTION_DATA(o);
- 		memcpy(p, ifo->ia[l].iaid, sizeof(u32));
- 		p += sizeof(u32);
- 		memset(p, 0, sizeof(u32) + sizeof(u32));
- 		TAILQ_FOREACH(ap, &state->addrs, next) {
--			if (ap->prefix_vltime == 0)
-+			if (ap->prefix_vltime == 0 &&
-+			    !(ap->flags & IPV6_AF_REQUEST))
- 				continue;
- 			if (memcmp(ifo->ia[l].iaid, ap->iaid, sizeof(u32)))
- 				continue;
- 			so = D6_NEXT_OPTION(o);
--			if (ifo->ia_type == D6_OPTION_IA_PD) {
-+			if (ap->ia_type == D6_OPTION_IA_PD) {
- 				so->code = htons(D6_OPTION_IAPREFIX);
- 				so->len = htons(sizeof(ap->prefix.s6_addr) +
- 				    sizeof(u32) + sizeof(u32) + sizeof(u8));
-@@ -557,16 +703,45 @@
- 				p += sizeof(u8);
- 				memcpy(p, &ap->prefix.s6_addr,
- 				    sizeof(ap->prefix.s6_addr));
--				/* Avoid a shadowed declaration warning by
--				 * moving our addition outside of the htons
--				 * macro */
-+
-+				/* RFC6603 Sectio 4.2 */
-+				sla = dhcp6_findselfsla(ifp, ap->iaid);
-+				if (sla &&
-+				    dhcp6_delegateaddr(&addr, ifp, ap, sla) ==0)
-+				{
-+					uint16_t el;
-+					uint8_t *pp;
-+
-+					el = ((sla->prefix_len -
-+					    ap->prefix_len - 1) / NBBY) + 1;
-+					eo = D6_NEXT_OPTION(so);
-+					eo->code = htons(D6_OPTION_PD_EXCLUDE);
-+					eo->len = el + 1;
-+					p = D6_OPTION_DATA(eo);
-+					*p++ = (uint8_t)sla->prefix_len;
-+					pp = addr.s6_addr;
-+					pp += (ap->prefix_len - 1) / NBBY;
-+					u8 = ap->prefix_len % NBBY;
-+					if (u8 % NBBY == 0)
-+						pp++;
-+					else {
-+						*p = (uint8_t)(*pp++ << u8);
-+						el--;
-+					}
-+					memcpy(p, pp, el);
-+					u32 = ntohs(so->len) +
-+					    sizeof(*eo) + eo->len;
-+					so->len = htons(u32);
-+					eo->len = htons(eo->len);
-+				}
-+
- 				u32 = ntohs(o->len) + sizeof(*so)
- 				    + ntohs(so->len);
- 				o->len = htons(u32);
- 			} else {
- 				so->code = htons(D6_OPTION_IA_ADDR);
--				so->len = htons(sizeof(ap->addr.s6_addr) +
--				    sizeof(u32) + sizeof(u32));
-+				so->len = sizeof(ap->addr.s6_addr) +
-+				    sizeof(u32) + sizeof(u32);
- 				p = D6_OPTION_DATA(so);
- 				memcpy(p, &ap->addr.s6_addr,
- 				    sizeof(ap->addr.s6_addr));
-@@ -576,11 +751,9 @@
- 				p += sizeof(u32);
- 				u32 = htonl(ap->prefix_vltime);
- 				memcpy(p, &u32, sizeof(u32));
--				/* Avoid a shadowed declaration warning by
--				 * moving our addition outside of the htons
--				 * macro */
- 				u32 = ntohs(o->len) + sizeof(*so)
--				    + ntohs(so->len);
-+				    + so->len;
-+				so->len = htons(so->len);
- 				o->len = htons(u32);
- 			}
- 		}
-@@ -625,6 +798,28 @@
- 			    l < ifp->ctx->dhcp6_opts_len;
- 			    l++, opt++)
- 			{
-+				for (n = 0, opt2 = ifo->dhcp6_override;
-+				    n < ifo->dhcp6_override_len;
-+				    n++, opt2++)
-+				{
-+					if (opt->option == opt2->option)
-+						break;
-+				}
-+				if (n < ifo->dhcp6_override_len)
-+				    continue;
-+				if (!(opt->type & NOREQ) &&
-+				    (opt->type & REQUEST ||
-+				    has_option_mask(ifo->requestmask6,
-+				        opt->option)))
-+				{
-+					*u16++ = htons(opt->option);
-+					o->len += sizeof(*u16);
-+				}
-+			}
-+			for (l = 0, opt = ifo->dhcp6_override;
-+			    l < ifo->dhcp6_override_len;
-+			    l++, opt++)
-+			{
- 				if (!(opt->type & NOREQ) &&
- 				    (opt->type & REQUEST ||
- 				    has_option_mask(ifo->requestmask6,
-@@ -634,6 +829,10 @@
- 					o->len += sizeof(*u16);
- 				}
- 			}
-+			if (dhcp6_findselfsla(ifp, NULL)) {
-+				*u16++ = htons(D6_OPTION_PD_EXCLUDE);
-+				o->len += sizeof(*u16);
-+			}
- 			o->len = htons(o->len);
- 		}
- 	}
-@@ -949,6 +1148,99 @@
- }
- 
- static void
-+dhcp6_dadcallback(void *arg)
-+{
-+	struct ipv6_addr *ap = arg;
-+	struct interface *ifp;
-+	struct dhcp6_state *state;
-+	int wascompleted;
-+
-+	wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
-+	ap->flags |= IPV6_AF_DADCOMPLETED;
-+	if (ap->flags & IPV6_AF_DUPLICATED)
-+		/* XXX FIXME
-+		 * We should decline the address */
-+		syslog(LOG_WARNING, "%s: DAD detected %s",
-+		    ap->iface->name, ap->saddr);
-+
-+	if (!wascompleted) {
-+		ifp = ap->iface;
-+		state = D6_STATE(ifp);
-+		if (state->state == DH6S_BOUND ||
-+		    state->state == DH6S_DELEGATED)
-+		{
-+			TAILQ_FOREACH(ap, &state->addrs, next) {
-+				if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
-+					wascompleted = 1;
-+					break;
-+				}
-+			}
-+			if (!wascompleted) {
-+				syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed",
-+				    ifp->name);
-+				script_runreason(ifp, state->reason);
-+				dhcpcd_daemonise(ifp->ctx);
-+			}
-+		}
-+	}
-+}
-+
-+static void
-+dhcp6_addrequestedaddrs(struct interface *ifp)
-+{
-+	struct dhcp6_state *state;
-+	size_t i;
-+	struct if_ia *ia;
-+	struct ipv6_addr *a;
-+	char iabuf[INET6_ADDRSTRLEN];
-+	const char *iap;
-+
-+	state = D6_STATE(ifp);
-+	/* Add any requested prefixes / addresses */
-+	for (i = 0; i < ifp->options->ia_len; i++) {
-+		ia = &ifp->options->ia[i];
-+		if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) ||
-+		    !IN6_IS_ADDR_UNSPECIFIED(&ia->addr)))
-+			continue;
-+		a = calloc(1, sizeof(*a));
-+		if (a == NULL) {
-+			syslog(LOG_ERR, "%s: %m", __func__);
-+			return;
-+		}
-+		a->flags = IPV6_AF_REQUEST;
-+		a->iface = ifp;
-+		a->dadcallback = dhcp6_dadcallback;
-+		memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
-+		a->ia_type = ia->ia_type;
-+		//a->prefix_pltime = 0;
-+		//a->prefix_vltime = 0;
-+
-+		if (ia->ia_type == D6_OPTION_IA_PD) {
-+			memcpy(&a->prefix, &ia->addr, sizeof(a->addr));
-+			a->prefix_len = ia->prefix_len;
-+			iap = inet_ntop(AF_INET6, &a->prefix.s6_addr,
-+			    iabuf, sizeof(iabuf));
-+		} else {
-+			memcpy(&a->addr, &ia->addr, sizeof(a->addr));
-+			/*
-+			 * RFC 5942 Section 5
-+			 * We cannot assume any prefix length, nor tie the
-+			 * address to an existing one as it could expire
-+			 * before the address.
-+			 * As such we just give it a 128 prefix.
-+			 */
-+			a->prefix_len = 128;
-+			ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
-+			iap = inet_ntop(AF_INET6, &a->addr.s6_addr,
-+			    iabuf, sizeof(iabuf));
-+		}
-+		snprintf(a->saddr, sizeof(a->saddr),
-+		    "%s/%d", iap, a->prefix_len);
-+		TAILQ_INSERT_TAIL(&state->addrs, a, next);
-+	}
-+}
-+
-+static void
- dhcp6_startdiscover(void *arg)
- {
- 	struct interface *ifp;
-@@ -974,6 +1266,8 @@
- 	dhcp6_freedrop_addrs(ifp, 0, NULL);
- 	unlink(state->leasefile);
- 
-+	dhcp6_addrequestedaddrs(ifp);
-+
- 	if (dhcp6_makemessage(ifp) == -1)
- 		syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name);
- 	else
-@@ -1021,11 +1315,25 @@
- 	dhcp6_startdiscover(ifp);
- }
- 
-+
-+static int
-+dhcp6_hasprefixdelegation(struct interface *ifp)
-+{
-+	size_t i;
-+
-+	for (i = 0; i < ifp->options->ia_len; i++) {
-+		if (ifp->options->ia[i].ia_type == D6_OPTION_IA_PD)
-+			return 1;
-+	}
-+	return 0;
-+}
-+
- static void
- dhcp6_startrebind(void *arg)
- {
- 	struct interface *ifp;
- 	struct dhcp6_state *state;
-+	int pd;
- 
- 	ifp = arg;
- 	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrenew, ifp);
-@@ -1033,13 +1341,16 @@
- 	if (state->state == DH6S_RENEW)
- 		syslog(LOG_WARNING, "%s: failed to renew DHCPv6, rebinding",
- 		    ifp->name);
-+	else
-+		syslog(LOG_INFO, "%s: rebinding prior DHCPc6 lease",
-+		    ifp->name);
- 	state->state = DH6S_REBIND;
- 	state->RTC = 0;
- 	state->MRC = 0;
- 
- 	/* RFC 3633 section 12.1 */
--	if (ifp->options->ia_type == D6_OPTION_IA_PD) {
--		syslog(LOG_INFO, "%s: confirming Prefix Delegation", ifp->name);
-+	pd = dhcp6_hasprefixdelegation(ifp);
-+	if (pd) {
- 		state->IMD = CNF_MAX_DELAY;
- 		state->IRT = CNF_TIMEOUT;
- 		state->MRT = CNF_MAX_RT;
-@@ -1054,7 +1365,7 @@
- 		dhcp6_sendrebind(ifp);
- 
- 	/* RFC 3633 section 12.1 */
--	if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+	if (pd)
- 		eloop_timeout_add_sec(ifp->ctx->eloop,
- 		    CNF_MAX_RD, dhcp6_failrebind, ifp);
- }
-@@ -1264,46 +1575,8 @@
- 	return 0;
- }
- 
--static void
--dhcp6_dadcallback(void *arg)
--{
--	struct ipv6_addr *ap = arg;
--	struct interface *ifp;
--	struct dhcp6_state *state;
--	int wascompleted;
--
--	wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
--	ap->flags |= IPV6_AF_DADCOMPLETED;
--	if (ap->flags & IPV6_AF_DUPLICATED)
--		/* XXX FIXME
--		 * We should decline the address */
--		syslog(LOG_WARNING, "%s: DAD detected %s",
--		    ap->iface->name, ap->saddr);
--
--	if (!wascompleted) {
--		ifp = ap->iface;
--		state = D6_STATE(ifp);
--		if (state->state == DH6S_BOUND ||
--		    state->state == DH6S_DELEGATED)
--		{
--			TAILQ_FOREACH(ap, &state->addrs, next) {
--				if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
--					wascompleted = 1;
--					break;
--				}
--			}
--			if (!wascompleted) {
--				syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed",
--				    ifp->name);
--				script_runreason(ifp, state->reason);
--				dhcpcd_daemonise(ifp->ctx);
--			}
--		}
--	}
--}
--
- static int
--dhcp6_findna(struct interface *ifp, const uint8_t *iaid,
-+dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
-     const uint8_t *d, size_t l)
- {
- 	struct dhcp6_state *state;
-@@ -1345,6 +1618,7 @@
- 			a->iface = ifp;
- 			a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
- 			a->dadcallback = dhcp6_dadcallback;
-+			a->ia_type = ot;
- 			memcpy(a->iaid, iaid, sizeof(a->iaid));
- 			memcpy(&a->addr.s6_addr, &in6.s6_addr,
- 			    sizeof(in6.s6_addr));
-@@ -1357,20 +1631,18 @@
- 			 * As such we just give it a 128 prefix.
- 			 */
- 			a->prefix_len = 128;
--			if (ipv6_makeprefix(&a->prefix, &a->addr,
--			    a->prefix_len) == -1)
--			{
--				syslog(LOG_ERR, "%s: %m", __func__);
--				free(a);
--				continue;
--			}
-+			ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
- 			ia = inet_ntop(AF_INET6, &a->addr.s6_addr,
- 			    iabuf, sizeof(iabuf));
- 			snprintf(a->saddr, sizeof(a->saddr),
- 			    "%s/%d", ia, a->prefix_len);
-+
- 			TAILQ_INSERT_TAIL(&state->addrs, a, next);
--		} else
-+		} else {
-+			if (!(a->flags & IPV6_AF_ONLINK))
-+				a->flags |= IPV6_AF_ONLINK | IPV6_AF_NEW;
- 			a->flags &= ~IPV6_AF_STALE;
-+		}
- 		memcpy(&u32, p, sizeof(u32));
- 		a->prefix_pltime = ntohl(u32);
- 		p += sizeof(u32);
-@@ -1394,8 +1666,8 @@
-     const uint8_t *d, size_t l)
- {
- 	struct dhcp6_state *state;
--	const struct dhcp6_option *o;
--	const uint8_t *p;
-+	const struct dhcp6_option *o, *ex;
-+	const uint8_t *p, *ps, *pe, *op;
- 	struct ipv6_addr *a;
- 	char iabuf[INET6_ADDRSTRLEN];
- 	const char *ia;
-@@ -1420,7 +1692,8 @@
- 			    ifp->name);
- 			continue;
- 		}
--		p = D6_COPTION_DATA(o);
-+		ps = p = D6_COPTION_DATA(o);
-+		pe = ps + u32;
- 		memcpy(&u32, p, sizeof(u32));
- 		pltime = ntohl(u32);
- 		p += sizeof(u32);
-@@ -1431,6 +1704,7 @@
- 		p += sizeof(u8);
- 		len = u8;
- 		memcpy(&prefix.s6_addr, p, sizeof(prefix.s6_addr));
-+		p += sizeof(prefix.s6_addr);
- 
- 		TAILQ_FOREACH(a, &state->addrs, next) {
- 			if (IN6_ARE_ADDR_EQUAL(&a->prefix, &prefix))
-@@ -1445,6 +1719,7 @@
- 			a->iface = ifp;
- 			a->flags = IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
- 			a->dadcallback = dhcp6_dadcallback;
-+			a->ia_type = D6_OPTION_IA_PD;
- 			memcpy(a->iaid, iaid, sizeof(a->iaid));
- 			memcpy(&a->prefix.s6_addr,
- 			    &prefix.s6_addr, sizeof(a->prefix.s6_addr));
-@@ -1455,24 +1730,58 @@
- 			    "%s/%d", ia, a->prefix_len);
- 			TAILQ_INSERT_TAIL(&state->addrs, a, next);
- 		} else {
--			a->flags &= ~IPV6_AF_STALE;
-+			if (!(a->flags & IPV6_AF_DELEGATEDPFX))
-+				a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
-+			a->flags &= ~(IPV6_AF_STALE | IPV6_AF_REQUEST);
- 			if (a->prefix_vltime != vltime)
- 				a->flags |= IPV6_AF_NEW;
- 		}
- 
- 		a->prefix_pltime = pltime;
- 		a->prefix_vltime = vltime;
-+
- 		if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
- 			state->lowpl = a->prefix_pltime;
- 		if (a->prefix_vltime && a->prefix_vltime > state->expire)
- 			state->expire = a->prefix_vltime;
- 		i++;
-+
-+		off = (size_t)(pe - p);
-+		ex = dhcp6_findoption(D6_OPTION_PD_EXCLUDE, p, off);
-+
-+		if (ex) {
-+			off = ntohs(ex->len);
-+			if (off < 2) {
-+				syslog(LOG_ERR, "%s: truncated PD Exclude",
-+				    ifp->name);
-+				ex = NULL;
-+			}
-+		}
-+		if (ex) {
-+			int bytelen, bitlen;
-+
-+			op = D6_COPTION_DATA(ex);
-+			a->prefix_exclude_len = *op++;
-+			memcpy(&a->prefix_exclude, &a->prefix,
-+			    sizeof(a->prefix_exclude));
-+			bytelen = a->prefix_len / NBBY;
-+			bitlen = a->prefix_len % NBBY;
-+			if (bitlen != 0)
-+				a->prefix_exclude.s6_addr[bytelen] |=
-+				    *op++ >> bitlen;
-+			memcpy(a->prefix_exclude.s6_addr + bytelen + 1,
-+			    op, off - 2);
-+		} else {
-+			a->prefix_exclude_len = 0;
-+			memset(&a->prefix_exclude, 0,
-+			    sizeof(a->prefix_exclude));
-+		}
- 	}
- 	return i;
- }
- 
- static int
--dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l,
-+dhcp6_findia(struct interface *ifp, const struct dhcp6_message *m, size_t l,
-     const char *sfrom)
- {
- 	struct dhcp6_state *state;
-@@ -1480,25 +1789,47 @@
- 	const struct dhcp6_option *o;
- 	const uint8_t *p;
- 	int i, e;
-+	size_t j;
- 	uint32_t u32, renew, rebind;
-+	uint16_t code, ol;
- 	uint8_t iaid[4];
--	size_t ol;
-+	char buf[sizeof(iaid) * 3];
- 	struct ipv6_addr *ap, *nap;
- 
-+	if (l < sizeof(*m)) {
-+		syslog(LOG_ERR, "%s: message truncated", ifp->name);
-+		errno = EINVAL;
-+		return -1;
-+	}
-+
- 	ifo = ifp->options;
- 	i = e = 0;
- 	state = D6_STATE(ifp);
- 	TAILQ_FOREACH(ap, &state->addrs, next) {
- 		ap->flags |= IPV6_AF_STALE;
- 	}
--	while ((o = dhcp6_findoption(ifo->ia_type, d, l))) {
--		ol = (size_t)((const uint8_t *)o - d);
--		l -= ol;
--		d += ol;
-+	l -= sizeof(*m);
-+	for (o = D6_FIRST_OPTION(m); l > sizeof(*o); o = D6_NEXT_OPTION(o)) {
- 		ol = ntohs(o->len);
-+		if (sizeof(*o) + ol > l) {
-+			errno = EINVAL;
-+			syslog(LOG_ERR, "%s: option overflow", ifp->name);
-+			break;
-+		}
- 		l -= sizeof(*o) + ol;
--		d += sizeof(*o) + ol;
--		u32 = ifo->ia_type == D6_OPTION_IA_TA ? 4 : 12;
-+
-+		code = ntohs(o->code);
-+		switch(code) {
-+		case D6_OPTION_IA_TA:
-+			u32 = 4;
-+			break;
-+		case D6_OPTION_IA_NA:
-+		case D6_OPTION_IA_PD:
-+			u32 = 12;
-+			break;
-+		default:
-+			continue;
-+		}
- 		if (ol < u32) {
- 			errno = EINVAL;
- 			syslog(LOG_ERR, "%s: IA option truncated", ifp->name);
-@@ -1509,7 +1840,25 @@
- 		memcpy(iaid, p, sizeof(iaid));
- 		p += sizeof(iaid);
- 		ol -= sizeof(iaid);
--		if (ifo->ia_type != D6_OPTION_IA_TA) {
-+
-+		for (j = 0; j < ifo->ia_len; j++) {
-+			if (memcmp(&ifo->ia[j].iaid, iaid, sizeof(iaid)) == 0)
-+				break;
-+		}
-+		if (j == ifo->ia_len) {
-+			syslog(LOG_DEBUG, "%s: ignoring unrequested IAID %s",
-+			    ifp->name,
-+			    hwaddr_ntoa(iaid, sizeof(iaid), buf, sizeof(buf)));
-+			continue;
-+		}
-+		if (ifo->ia[j].ia_type != code) {
-+			syslog(LOG_ERR, "%s: IAID %s: option type mismatch",
-+			    ifp->name,
-+			    hwaddr_ntoa(iaid, sizeof(iaid), buf, sizeof(buf)));
-+			continue;
-+		}
-+
-+		if (code != D6_OPTION_IA_TA) {
- 			memcpy(&u32, p, sizeof(u32));
- 			renew = ntohl(u32);
- 			p += sizeof(u32);
-@@ -1524,22 +1873,24 @@
- 			e = 1;
- 			continue;
- 		}
--		if (ifo->ia_type == D6_OPTION_IA_PD) {
--			if (dhcp6_findpd(ifp, iaid, p, ol) == 0) {
-+		if (code == D6_OPTION_IA_PD) {
-+			if (!(ifo->options & DHCPCD_NOPFXDLG) &&
-+			    dhcp6_findpd(ifp, iaid, p, ol) == 0)
-+			{
- 				syslog(LOG_WARNING,
- 				    "%s: %s: DHCPv6 REPLY missing Prefix",
- 				    ifp->name, sfrom);
- 				continue;
- 			}
--		} else {
--			if (dhcp6_findna(ifp, iaid, p, ol) == 0) {
-+		} else if (!(ifo->options & DHCPCD_PFXDLGONLY)) {
-+			if (dhcp6_findna(ifp, code, iaid, p, ol) == 0) {
- 				syslog(LOG_WARNING,
- 				    "%s: %s: DHCPv6 REPLY missing IA Address",
- 				    ifp->name, sfrom);
- 				continue;
- 			}
- 		}
--		if (ifo->ia_type != D6_OPTION_IA_TA) {
-+		if (code != D6_OPTION_IA_TA) {
- 			if (renew > rebind && rebind > 0) {
- 				if (sfrom)
- 				    syslog(LOG_WARNING,
-@@ -1559,11 +1910,15 @@
- 	}
- 	TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) {
- 		if (ap->flags & IPV6_AF_STALE) {
--			TAILQ_REMOVE(&state->addrs, ap, next);
- 			if (ap->dadcallback)
- 				eloop_q_timeout_delete(ap->iface->ctx->eloop,
- 				    0, NULL, ap);
--			free(ap);
-+			if (ap->flags & IPV6_AF_REQUEST) {
-+				ap->prefix_vltime = ap->prefix_pltime = 0;
-+			} else {
-+				TAILQ_REMOVE(&state->addrs, ap, next);
-+				free(ap);
-+			}
- 		}
- 	}
- 	if (i == 0 && e)
-@@ -1577,25 +1932,14 @@
-     const char *sfrom)
- {
- 	struct dhcp6_state *state;
--	const struct dhcp6_option *o;
- 
- 	state = D6_STATE(ifp);
--	o = dhcp6_getmoption(ifp->options->ia_type, m, len);
--	if (o == NULL) {
--		if (sfrom &&
--		    dhcp6_checkstatusok(ifp, m, NULL, len) != -1)
--			syslog(LOG_ERR, "%s: no IA in REPLY from %s",
--			    ifp->name, sfrom);
--		return -1;
--	}
--
- 	if (dhcp6_checkstatusok(ifp, m, NULL, len) == -1)
- 		return -1;
- 
- 	state->renew = state->rebind = state->expire = 0;
- 	state->lowpl = ND6_INFINITE_LIFETIME;
--	len -= (size_t)((const char *)o - (const char *)m);
--	return dhcp6_findia(ifp, (const uint8_t *)o, len, sfrom);
-+	return dhcp6_findia(ifp, m, len, sfrom);
- }
- 
- static ssize_t
-@@ -1633,6 +1977,7 @@
- 	if (stat(state->leasefile, &st) == -1) {
- 		if (errno == ENOENT)
- 			return 0;
-+		syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__);
- 		return -1;
- 	}
- 	syslog(LOG_DEBUG, "%s: reading lease `%s'",
-@@ -1642,12 +1987,17 @@
- 		return -1;
- 	}
- 	state->new = malloc((size_t)st.st_size);
--	if (state->new == NULL)
-+	if (state->new == NULL) {
-+		syslog(LOG_ERR, "%s: %m", __func__);
- 		return -1;
-+	}
- 	state->new_len = (size_t)st.st_size;
- 	fd = open(state->leasefile, O_RDONLY);
--	if (fd == -1)
-+	if (fd == -1) {
-+		syslog(LOG_ERR, "%s: %s: %s: %m", ifp->name, __func__,
-+		    state->leasefile);
- 		return -1;
-+	}
- 	bytes = read(fd, state->new, state->new_len);
- 	close(fd);
- 	if (bytes < (ssize_t)state->new_len) {
-@@ -1660,7 +2010,7 @@
- 	if (fd == -1)
- 		goto ex;
- 	if (fd == 0) {
--		syslog(LOG_INFO, "%s: lease was for different IA type",
-+		syslog(LOG_INFO, "%s: no useable IA found in lease",
- 		    ifp->name);
- 		goto ex;
- 	}
-@@ -1705,22 +2055,39 @@
- 	free(state->new);
- 	state->new = NULL;
- 	state->new_len = 0;
--	unlink(state->leasefile);
-+	if (!(ifp->ctx->options & DHCPCD_DUMPLEASE))
-+		unlink(state->leasefile);
- 	return 0;
- }
- 
-+
- static void
- dhcp6_startinit(struct interface *ifp)
- {
- 	struct dhcp6_state *state;
- 	int r;
-+	uint8_t has_ta, has_non_ta;
-+	size_t i;
- 
- 	state = D6_STATE(ifp);
- 	state->state = DH6S_INIT;
- 	state->expire = ND6_INFINITE_LIFETIME;
- 	state->lowpl = ND6_INFINITE_LIFETIME;
-+
-+	dhcp6_addrequestedaddrs(ifp);
-+	has_ta = has_non_ta = 0;
-+	for (i = 0; i < ifp->options->ia_len; i++) {
-+		switch (ifp->options->ia[i].ia_type) {
-+		case D6_OPTION_IA_TA:
-+			has_ta = 1;
-+			break;
-+		default:
-+			has_non_ta = 1;
-+		}
-+	}
-+
- 	if (!(ifp->ctx->options & DHCPCD_TEST) &&
--	    ifp->options->ia_type != D6_OPTION_IA_TA &&
-+	    !(has_ta && !has_non_ta) &&
- 	    ifp->options->reboot != 0)
- 	{
- 		r = dhcp6_readlease(ifp);
-@@ -1729,7 +2096,7 @@
- 					ifp->name, state->leasefile);
- 		else if (r != 0) {
- 			/* RFC 3633 section 12.1 */
--			if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+			if (dhcp6_hasprefixdelegation(ifp))
- 				dhcp6_startrebind(ifp);
- 			else
- 				dhcp6_startconfirm(ifp);
-@@ -1740,69 +2107,28 @@
- }
- 
- static struct ipv6_addr *
--dhcp6_delegate_addr(struct interface *ifp, struct ipv6_addr *prefix,
-+dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
-     const struct if_sla *sla, struct interface *ifs)
- {
- 	struct dhcp6_state *state;
--	struct if_sla asla;
- 	struct in6_addr addr;
- 	struct ipv6_addr *a, *ap, *apn;
- 	char iabuf[INET6_ADDRSTRLEN];
- 	const char *ia;
- 
--	state = D6_STATE(ifp);
--	if (state == NULL) {
--		ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
--		state = D6_STATE(ifp);
--		if (state == NULL) {
--			syslog(LOG_ERR, "%s: %m", __func__);
-+	/* RFC6603 Section 4.2 */
-+	if (ifp == ifs) {
-+		if (prefix->prefix_exclude_len == 0) {
-+			syslog(LOG_WARNING,
-+			    "%s: DHCPv6 server does not support "
-+			    "OPTION_PD_EXCLUDE",
-+			    ifp->name);
- 			return NULL;
- 		}
--
--		TAILQ_INIT(&state->addrs);
--		state->state = DH6S_DELEGATED;
--		state->reason = "DELEGATED6";
--	}
--
--	if (sla == NULL || sla->sla_set == 0) {
--		struct interface *ifi;
--		unsigned int idx;
--		int bits;
--
--		asla.sla = ifp->index;
--		/* Work out our largest index delegating to. */
--		idx = 0;
--		TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
--			if (ifi != ifp && ifi->index > idx)
--				idx = ifi->index;
--		}
--		bits = ffs((int)idx);
--		if (prefix->prefix_len + bits > UINT8_MAX)
--			asla.prefix_len = UINT8_MAX;
--		else {
--			asla.prefix_len = prefix->prefix_len + (uint8_t)bits;
--
--			/* Make a 64 prefix by default, as this maks SLAAC
--			 * possible. Otherwise round up to the nearest octet. */
--			if (asla.prefix_len <= 64)
--				asla.prefix_len = 64;
--			else
--				asla.prefix_len = ROUNDUP8(asla.prefix_len);
--
--		}
--		sla = &asla;
--	}
--
--	if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
--		sla->sla, &addr, sla->prefix_len) == -1)
--	{
--		ia = inet_ntop(AF_INET6, &prefix->prefix.s6_addr,
--		    iabuf, sizeof(iabuf));
--		syslog(LOG_ERR, "%s: invalid prefix %s/%d + %d/%d: %m",
--			ifp->name, ia, prefix->prefix_len,
--			sla->sla, sla->prefix_len);
-+		memcpy(&addr, &prefix->prefix_exclude, sizeof(addr));
-+	} else if (dhcp6_delegateaddr(&addr, ifp, prefix, sla) == -1)
- 		return NULL;
--	}
-+
- 
- 	a = calloc(1, sizeof(*a));
- 	if (a == NULL) {
-@@ -1824,6 +2150,7 @@
- 	memcpy(&a->addr.s6_addr, &a->prefix.s6_addr, sizeof(a->addr.s6_addr));
- 	a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] += 1;
- 
-+	state = D6_STATE(ifp);
- 	/* Remove any exiting address */
- 	TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) {
- 		if (IN6_ARE_ADDR_EQUAL(&ap->addr, &a->addr)) {
-@@ -1916,7 +2243,7 @@
- 						    abrt = 1;
- 						break;
- 					}
--					if (dhcp6_delegate_addr(ifd, ap,
-+					if (dhcp6_ifdelegateaddr(ifd, ap,
- 					    NULL, ifp))
- 						k++;
- 				}
-@@ -1935,7 +2262,7 @@
- 						carrier_warned = 1;
- 						break;
- 					}
--					if (dhcp6_delegate_addr(ifd, ap,
-+					if (dhcp6_ifdelegateaddr(ifd, ap,
- 					    sla, ifp))
- 						k++;
- 				}
-@@ -1998,7 +2325,7 @@
- 						    dhcp6_find_delegates1, ifp);
- 						return 1;
- 					}
--					if (dhcp6_delegate_addr(ifp, ap,
-+					if (dhcp6_ifdelegateaddr(ifp, ap,
- 					    sla, ifd))
- 					    k++;
- 				}
-@@ -2225,7 +2552,7 @@
- 				/* PD doesn't use CONFIRM, so REBIND could
- 				 * throw up an invalid prefix if we
- 				 * changed link */
--				if (ifp->options->ia_type == D6_OPTION_IA_PD)
-+				if (dhcp6_hasprefixdelegation(ifp))
- 					dhcp6_startdiscover(ifp);
- 				return;
- 			}
-@@ -2437,10 +2764,10 @@
- 		if (state->expire && state->expire != ND6_INFINITE_LIFETIME)
- 			eloop_timeout_add_sec(ifp->ctx->eloop,
- 			    (time_t)state->expire, dhcp6_startexpire, ifp);
--		if (ifp->options->ia_type == D6_OPTION_IA_PD)
--			dhcp6_delegate_prefix(ifp);
- 
- 		ipv6_addaddrs(&state->addrs);
-+		dhcp6_delegate_prefix(ifp);
-+
- 		if (state->state == DH6S_INFORMED)
- 			syslog(has_new ? LOG_INFO : LOG_DEBUG,
- 			    "%s: refresh in %"PRIu32" seconds",
-@@ -2584,6 +2911,10 @@
- 			add_option_mask(ifo->requestmask6, D6_OPTION_FQDN);
- 	}
- 
-+	/* Rapid commit won't wor with Prefix Delegation Exclusion */
-+	if (dhcp6_findselfsla(ifp, NULL))
-+		del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);
-+
- 	if (state->state == DH6S_INFORM) {
- 		add_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
- 		dhcp6_startinform(ifp);
-@@ -2635,7 +2966,8 @@
- 
- 	state->state = init_state;
- 	snprintf(state->leasefile, sizeof(state->leasefile),
--	    LEASEFILE6, ifp->name);
-+	    LEASEFILE6, ifp->name,
-+	    ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
- 
- 	if (ipv6_linklocal(ifp) == NULL) {
- 		syslog(LOG_DEBUG,
-@@ -2790,18 +3122,21 @@
- dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
-     const struct dhcp6_message *m, size_t len)
- {
--	const struct dhcp6_state *state;
- 	const struct if_options *ifo;
- 	struct dhcp_opt *opt, *vo;
- 	const struct dhcp6_option *o;
--	size_t i, l, n;
-+	size_t i, n;
- 	uint16_t ol, oc;
--	char *v, *val, *pfx;
--	const struct ipv6_addr *ap;
-+	char *pfx;
- 	uint32_t en;
- 	const struct dhcpcd_ctx *ctx;
- 
--	state = D6_CSTATE(ifp);
-+	if (len < sizeof(*m)) {
-+		syslog(LOG_ERR, "%s: message truncated", ifp->name);
-+		errno = EINVAL;
-+		return -1;
-+	}
-+
- 	n = 0;
- 	ifo = ifp->options;
- 	ctx = ifp->ctx;
-@@ -2885,64 +3220,38 @@
- 	}
- 	free(pfx);
- 
--	/* It is tempting to remove this section.
--	 * However, we need it at least for Delegated Prefixes
--	 * (they don't have a DHCPv6 message to parse to get the addressses)
--	 * and it's easier for shell scripts to see which addresses have
--	 * been added */
--	if (TAILQ_FIRST(&state->addrs)) {
--		if (env) {
--			if (ifo->ia_type == D6_OPTION_IA_PD) {
--				l = strlen(prefix) +
--				    strlen("_dhcp6_prefix=");
--				TAILQ_FOREACH(ap, &state->addrs, next) {
--					l += strlen(ap->saddr) + 1;
--				}
--				v = val = env[n] = malloc(l);
--				if (v == NULL) {
--					syslog(LOG_ERR, "%s: %m", __func__);
--					return -1;
--				}
--				i = (size_t)snprintf(v, l, "%s_dhcp6_prefix=",
--				    prefix);
--				v += i;
--				l -= i;
--				TAILQ_FOREACH(ap, &state->addrs, next) {
--					i = strlen(ap->saddr);
--					strlcpy(v, ap->saddr, l);
--					v += i;
--					l -= i;
--					*v++ = ' ';
--				}
--				*--v = '\0';
--			} else {
--				l = strlen(prefix) +
--				    strlen("_dhcp6_ip_address=");
--				TAILQ_FOREACH(ap, &state->addrs, next) {
--					l += strlen(ap->saddr) + 1;
--				}
--				v = val = env[n] = malloc(l);
--				if (v == NULL) {
--					syslog(LOG_ERR, "%s: %m", __func__);
--					return -1;
--				}
--				i = (size_t)snprintf(v, l,
--				    "%s_dhcp6_ip_address=",
--				    prefix);
--				v += i;
--				l -= i;
--				TAILQ_FOREACH(ap, &state->addrs, next) {
--					i = strlen(ap->saddr);
--					strlcpy(v, ap->saddr, l);
--					v += i;
--					l -= i;
--					*v++ = ' ';
--				}
--				*--v = '\0';
--			}
--		}
--		n++;
-+	return (ssize_t)n;
-+}
-+
-+int
-+dhcp6_dump(struct interface *ifp)
-+{
-+	struct dhcp6_state *state;
-+	int r;
-+
-+	ifp->if_data[IF_DATA_DHCP6] = state = calloc(1, sizeof(*state));
-+	if (state == NULL)
-+		goto eexit;
-+	TAILQ_INIT(&state->addrs);
-+	snprintf(state->leasefile, sizeof(state->leasefile),
-+	    LEASEFILE6, ifp->name,
-+	    ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
-+	r = dhcp6_readlease(ifp);
-+	if (r == -1 && errno == ENOENT) {
-+		strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
-+		r = dhcp6_readlease(ifp);
- 	}
-+	if (r == -1) {
-+		if (errno == ENOENT)
-+			syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
-+		else
-+			syslog(LOG_ERR, "%s: dhcp6_readlease: %m", ifp->name);
-+		return -1;
-+	}
-+	state->reason = "DUMP6";
-+	return script_runreason(ifp, state->reason);
- 
--	return (ssize_t)n;
-+eexit:
-+	syslog(LOG_ERR, "%s: %m", __func__);
-+	return -1;
- }
-diff -urN dhcpcd-6.4.0.org/dhcp6.h dhcpcd-6.4.0/dhcp6.h
---- dhcpcd-6.4.0.org/dhcp6.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp6.h	2014-07-05 21:47:22.000000000 +0200
-@@ -89,6 +89,7 @@
- #define D6_OPTION_FQDN			39
- #define D6_OPTION_POSIX_TIMEZONE	41
- #define D6_OPTION_TZDB_TIMEZONE		42
-+#define D6_OPTION_PD_EXCLUDE		67
- #define D6_OPTION_SOL_MAX_RT		82
- #define D6_OPTION_INF_MAX_RT		83
- 
-@@ -225,7 +226,8 @@
-     ((const uint8_t *)(o) + sizeof(struct dhcp6_option))
- 
- #ifdef INET6
--void dhcp6_printoptions(const struct dhcpcd_ctx *);
-+void dhcp6_printoptions(const struct dhcpcd_ctx *,
-+    const struct dhcp_opt *, size_t);
- int dhcp6_addrexists(struct dhcpcd_ctx *, const struct ipv6_addr *);
- size_t dhcp6_find_delegates(struct interface *);
- int dhcp6_start(struct interface *, enum DH6S);
-@@ -236,15 +238,16 @@
- void dhcp6_handleifa(struct dhcpcd_ctx *, int, const char *,
-     const struct in6_addr *addr, int);
- void dhcp6_drop(struct interface *, const char *);
-+int dhcp6_dump(struct interface *);
- #else
--#define dhcp6_printoptions()
- #define dhcp6_addrexists(a, b) (0)
--#define dhcp6_find_delegates(a) (0)
-+#define dhcp6_find_delegates(a)
- #define dhcp6_start(a, b) (0)
- #define dhcp6_reboot(a)
- #define dhcp6_env(a, b, c, d, e)
- #define dhcp6_free(a)
- #define dhcp6_drop(a, b)
-+#define dhcp6_dump(a) -1
- #endif
- 
- #endif
-diff -urN dhcpcd-6.4.0.org/dhcp.c dhcpcd-6.4.0/dhcp.c
---- dhcpcd-6.4.0.org/dhcp.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp.c	2014-07-05 21:47:22.000000000 +0200
-@@ -125,16 +125,24 @@
- static int dhcp_open(struct interface *);
- 
- void
--dhcp_printoptions(const struct dhcpcd_ctx *ctx)
-+dhcp_printoptions(const struct dhcpcd_ctx *ctx,
-+    const struct dhcp_opt *opts, size_t opts_len)
- {
- 	const char * const *p;
--	size_t i;
--	const struct dhcp_opt *opt;
-+	size_t i, j;
-+	const struct dhcp_opt *opt, *opt2;
- 
- 	for (p = dhcp_params; *p; p++)
- 		printf("    %s\n", *p);
- 
--	for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++)
-+	for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++) {
-+		for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
-+			if (opt->option == opt2->option)
-+				break;
-+		if (j == opts_len)
-+			printf("%03d %s\n", opt->option, opt->var);
-+	}
-+	for (i = 0, opt = opts; i < opts_len; i++, opt++)
- 		printf("%03d %s\n", opt->option, opt->var);
- }
- 
-@@ -286,7 +294,7 @@
- 			errno = EINVAL;
- 			return -1;
- 		}
--		ocets = (cidr + 7) / 8;
-+		ocets = (cidr + 7) / NBBY;
- 		if (!out) {
- 			p += 4 + ocets;
- 			bytes += ((4 * 4) * 2) + 4;
-@@ -357,7 +365,7 @@
- 		}
- 		TAILQ_INSERT_TAIL(routes, rt, next);
- 
--		ocets = (cidr + 7) / 8;
-+		ocets = (cidr + 7) / NBBY;
- 		/* If we have ocets then we have a destination and netmask */
- 		if (ocets > 0) {
- 			memcpy(&rt->dest.s_addr, p, ocets);
-@@ -943,6 +951,30 @@
- 				goto toobig;
- 			*p++ = (uint8_t)opt->option;
- 		}
-+		for (i = 0, opt = ifo->dhcp_override;
-+		    i < ifo->dhcp_override_len;
-+		    i++, opt++)
-+		{
-+			/* Check if added above */
-+			for (lp = n_params + 1; lp < p; lp++)
-+				if (*lp == (uint8_t)opt->option)
-+					break;
-+			if (lp < p)
-+				continue;
-+			if (!(opt->type & REQUEST ||
-+				has_option_mask(ifo->requestmask, opt->option)))
-+				continue;
-+			if (opt->type & NOREQ)
-+				continue;
-+			if (type == DHCP_INFORM &&
-+			    (opt->option == DHO_RENEWALTIME ||
-+				opt->option == DHO_REBINDTIME))
-+				continue;
-+			len = (size_t)((p - m) + 2);
-+			if (len > sizeof(*dhcp))
-+				goto toobig;
-+			*p++ = (uint8_t)opt->option;
-+		}
- 		*n_params = (uint8_t)(p - n_params - 1);
- 	}
- 
-@@ -2733,40 +2765,23 @@
- }
- 
- int
--dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname)
-+dhcp_dump(struct interface *ifp)
- {
--	struct interface *ifp;
- 	struct dhcp_state *state;
- 
--	if (ctx->ifaces == NULL) {
--		ctx->ifaces = malloc(sizeof(*ctx->ifaces));
--		if (ctx->ifaces == NULL)
--			return -1;
--		TAILQ_INIT(ctx->ifaces);
--	}
--	state = NULL;
--	ifp = calloc(1, sizeof(*ifp));
--	if (ifp == NULL)
--		goto eexit;
--	ifp->ctx = ctx;
--	TAILQ_INSERT_HEAD(ctx->ifaces, ifp, next);
- 	ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
- 	if (state == NULL)
- 		goto eexit;
--	ifp->options = calloc(1, sizeof(*ifp->options));
--	if (ifp->options == NULL)
--		goto eexit;
--	strlcpy(ifp->name, ifname, sizeof(ifp->name));
- 	snprintf(state->leasefile, sizeof(state->leasefile),
- 	    LEASEFILE, ifp->name);
- 	state->new = read_lease(ifp);
- 	if (state->new == NULL && errno == ENOENT) {
--		strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
-+		strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
- 		state->new = read_lease(ifp);
- 	}
- 	if (state->new == NULL) {
- 		if (errno == ENOENT)
--			syslog(LOG_ERR, "%s: no lease to dump", ifname);
-+			syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
- 		return -1;
- 	}
- 	state->reason = "DUMP";
-@@ -3015,13 +3030,22 @@
- 	if (!(ifp->options->options & DHCPCD_IPV4))
- 		return;
- 
--	tv.tv_sec = DHCP_MIN_DELAY;
--	tv.tv_usec = (suseconds_t)arc4random_uniform(
--	    (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
--	timernorm(&tv);
--	syslog(LOG_DEBUG,
--	    "%s: delaying DHCP for %0.1f seconds",
--	    ifp->name, timeval_to_double(&tv));
-+	/* No point in delaying a static configuration */
-+	if (ifp->options->options & DHCPCD_STATIC &&
-+	    !(ifp->options->options & DHCPCD_INFORM))
-+	{
-+		tv.tv_sec = 0;
-+		tv.tv_usec = 0;
-+	} else {
-+		tv.tv_sec = DHCP_MIN_DELAY;
-+		tv.tv_usec = (suseconds_t)arc4random_uniform(
-+		    (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
-+		timernorm(&tv);
-+		syslog(LOG_DEBUG,
-+		    "%s: delaying DHCP for %0.1f seconds",
-+		    ifp->name, timeval_to_double(&tv));
-+	}
-+
- 	eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
- }
- 
-diff -urN dhcpcd-6.4.0.org/dhcpcd.8.in dhcpcd-6.4.0/dhcpcd.8.in
---- dhcpcd-6.4.0.org/dhcpcd.8.in	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.8.in	2014-07-05 21:47:22.000000000 +0200
-@@ -22,7 +22,7 @@
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
--.Dd June 2, 2014
-+.Dd July 4, 2014
- .Dt DHCPCD 8
- .Os
- .Sh NAME
-@@ -68,6 +68,10 @@
- .Fl U, Fl Fl dumplease
- .Ar interface
- .Nm
-+.Fl Fl pfxdlgonly
-+.Nm
-+.Fl Fl nopfxdlg
-+.Nm
- .Fl Fl version
- .Nm
- .Fl x , Fl Fl exit
-@@ -75,7 +79,7 @@
- .Sh DESCRIPTION
- .Nm
- is an implementation of the DHCP client specified in
--.%R RFC 2131 .
-+.Li RFC 2131 .
- .Nm
- gets the host information
- .Po
-@@ -103,17 +107,17 @@
- .Pp
- .Nm
- is also an implementation of the BOOTP client specified in
--.%R RFC 951 .
-+.Li RFC 951 .
- .Pp
- .Nm
- is also an implementation of the IPv6 Router Solicitor as specified in
--.%R RFC 4861
-+.Li RFC 4861
- and
--.%R RFC 6106 .
-+.Li RFC 6106 .
- .Pp
- .Nm
- is also an implemenation of the DHCPv6 client as specified in
--.%R RFC 3315 .
-+.Li RFC 3315 .
- By default,
- .Nm
- only starts DHCPv6 when instructed to do so by an IPV6 Router Advertisement.
-@@ -211,7 +215,7 @@
- .Pa @SCRIPT@ .
- .It Fl D , Fl Fl duid
- Generate an
--.%R RFC 4361
-+.Li RFC 4361
- compliant clientid.
- This requires persistent storage and not all DHCP servers work with it so it
- is not enabled by default.
-@@ -259,7 +263,7 @@
- itself never does any DNS updates.
- .Nm
- encodes the FQDN hostname as specified in
--.%R RFC1035 .
-+.Li RFC1035 .
- .It Fl f , Fl Fl config Ar file
- Specify a config to load instead of
- .Pa @SYSCONFDIR@/dhcpcd.conf .
-@@ -614,6 +618,30 @@
- so that
- .Nm
- knows which process to signal.
-+.Pp
-+.Li RFC3633
-+DHCPv6 Prefix Delegation does not work in the same state or session as
-+Normal or Temporary Addresses.
-+.Nm
-+is designed for a single state per protocol and as such
-+.Li draft-ietf-dhc-dhcpv6-stateful-issues-06
-+is supported by default, but that is not a published RFC yet.
-+To allow RFC conformance,
-+.Nm
-+supports the
-+.Fl Fl pfxdlgonly
-+and
-+.Fl Fl nopfxdlg
-+options which allow the spawning of two
-+.Nm
-+instances to separate the Prefix Delegation state from the others.
-+You may wish to disable
-+.Xr dhcpcd-run-hooks 8
-+on the
-+.Fl Fl pfxdlgonly
-+instance using the
-+.Fl Fl script \"\"
-+option.
- .Sh FILES
- .Bl -ohang
- .It Pa @SYSCONFDIR@/dhcpcd.conf
-@@ -671,7 +699,8 @@
- RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
- RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
- RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,
--RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6704, RFC\ 7217.
-+RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603, RFC\ 6704,
-+RFC\ 7217.
- .Sh AUTHORS
- .An Roy Marples Aq Mt roy at marples.name
- .Sh BUGS
-diff -urN dhcpcd-6.4.0.org/dhcpcd.c dhcpcd-6.4.0/dhcpcd.c
---- dhcpcd-6.4.0.org/dhcpcd.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.c	2014-07-05 21:47:22.000000000 +0200
-@@ -139,14 +139,14 @@
- 	struct dhcp_opt *opt;
- 
- 	if (ctx->ifac) {
--		for (ctx->ifac--; ctx->ifac >= 0; ctx->ifac--)
--			free(ctx->ifav[ctx->ifac]);
-+		for (; ctx->ifac > 0; ctx->ifac--)
-+			free(ctx->ifav[ctx->ifac - 1]);
- 		free(ctx->ifav);
- 		ctx->ifav = NULL;
- 	}
- 	if (ctx->ifdc) {
--		for (ctx->ifdc--; ctx->ifdc >= 0; ctx->ifdc--)
--			free(ctx->ifdv[ctx->ifdc]);
-+		for (; ctx->ifdc > 0; ctx->ifdc--)
-+			free(ctx->ifdv[ctx->ifdc - 1]);
- 		free(ctx->ifdv);
- 		ctx->ifdv = NULL;
- 	}
-@@ -323,6 +323,9 @@
- {
- 	struct if_options *ifo = ifp->options;
- 	int ra_global, ra_iface;
-+#ifdef INET6
-+	size_t i;
-+#endif
- 
- 	/* Do any platform specific configuration */
- 	if_conf(ifp);
-@@ -339,7 +342,7 @@
- 		ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
- 	if (!(ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
- 		ifo->options &= ~DHCPCD_IPV6RS;
--	if (ifo->options & DHCPCD_LINK && if_carrier(ifp) == LINK_UNKNOWN)
-+	if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_UNKNOWN)
- 		ifo->options &= ~DHCPCD_LINK;
- 
- 	if (ifo->metric != -1)
-@@ -431,17 +434,27 @@
- 	}
- 
- #ifdef INET6
--	if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) {
--		ifo->ia = malloc(sizeof(*ifo->ia));
--		if (ifo->ia == NULL)
--			syslog(LOG_ERR, "%s: %m", __func__);
--		else {
--			if (ifo->ia_type == 0)
--				ifo->ia_type = D6_OPTION_IA_NA;
--			memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
--			ifo->ia_len = 1;
--			ifo->ia->sla = NULL;
--			ifo->ia->sla_len = 0;
-+	if (ifo->options & DHCPCD_IPV6) {
-+		if (ifo->ia == NULL) {
-+			ifo->ia = malloc(sizeof(*ifo->ia));
-+			if (ifo->ia == NULL)
-+				syslog(LOG_ERR, "%s: %m", __func__);
-+			else {
-+				ifo->ia_len = 1;
-+				ifo->ia->ia_type = D6_OPTION_IA_NA;
-+				memcpy(ifo->ia->iaid, ifo->iaid,
-+				    sizeof(ifo->iaid));
-+				memset(&ifo->ia->addr, 0,
-+				    sizeof(ifo->ia->addr));
-+				ifo->ia->sla = NULL;
-+				ifo->ia->sla_len = 0;
-+			}
-+		} else {
-+			for (i = 0; i < ifo->ia_len; i++) {
-+				if (!ifo->ia[i].iaid_set)
-+					memcpy(ifo->ia->iaid, ifo->iaid,
-+					    sizeof(ifo->iaid));
-+			}
- 		}
- 	}
- #endif
-@@ -493,10 +506,23 @@
- 	if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
- 		return;
- 
--	if (carrier == LINK_UNKNOWN)
-+	switch(carrier) {
-+	case LINK_UNKNOWN:
- 		carrier = if_carrier(ifp); /* will set ifp->flags */
--	else
-+		break;
-+	case LINK_UP:
-+		/* we have a carrier! however, we need to ignore the flags
-+		 * set in the kernel message as sometimes this message is
-+		 * reported before IFF_UP is set by the kernel even though
-+		 * dhcpcd has already set it.
-+		 *
-+		 * So we check the flags now. If IFF_UP is still not set
-+		 * then we should expect an accompanying link_down message */
-+		if_setflag(ifp, 0); /* will set ifp->flags */
-+		break;
-+	default:
- 		ifp->flags = flags;
-+	}
- 
- 	if (carrier == LINK_UNKNOWN)
- 		syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
-@@ -561,32 +587,33 @@
- 		    ifp->name, ifn->name);
- }
- 
--void
--dhcpcd_startinterface(void *arg)
-+static void
-+pre_start(struct interface *ifp)
- {
--	struct interface *ifp = arg;
--	struct if_options *ifo = ifp->options;
--	size_t i;
--	char buf[DUID_LEN * 3];
- 
- 	/* Add our link-local address before upping the interface
- 	 * so our RFC7217 address beats the hwaddr based one.
- 	 * This is also a safety check incase it was ripped out
- 	 * from under us. */
--	if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
-+	if (ifp->options->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
- 		syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
--		ifo->options &= DHCPCD_IPV6;
-+		ifp->options->options &= DHCPCD_IPV6;
- 	}
-+}
- 
--	if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) {
--		if (if_up(ifp) == -1)
--			syslog(LOG_ERR, "%s: if_up: %m",
--			    ifp->name);
--	}
-+void
-+dhcpcd_startinterface(void *arg)
-+{
-+	struct interface *ifp = arg;
-+	struct if_options *ifo = ifp->options;
-+	size_t i;
-+	char buf[DUID_LEN * 3];
- 
--	if (ifp->carrier == LINK_UNKNOWN)
--		dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
--	if (ifp->carrier == LINK_DOWN) {
-+	pre_start(ifp);
-+	if (if_up(ifp) == -1)
-+		syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
-+
-+	if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) {
- 		syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
- 		return;
- 	}
-@@ -621,10 +648,12 @@
- 
- 	if (ifo->options & DHCPCD_IPV6) {
- 		if (ifo->options & DHCPCD_IPV6RS &&
--		    !(ifo->options & DHCPCD_INFORM))
-+		    !(ifo->options & (DHCPCD_INFORM | DHCPCD_PFXDLGONLY)))
- 			ipv6nd_startrs(ifp);
- 
--		if (!(ifo->options & DHCPCD_IPV6RS)) {
-+		if (!(ifo->options & DHCPCD_IPV6RS) ||
-+		    ifo->options & DHCPCD_IA_FORCED)
-+		{
- 			ssize_t nolease;
- 
- 			if (ifo->options & DHCPCD_IA_FORCED)
-@@ -651,6 +680,8 @@
- 				    "%s: dhcp6_start: %m", ifp->name);
- 		}
- 	}
-+	if (ifo->options & DHCPCD_PFXDLGONLY)
-+		return;
- 
- 	if (ifo->options & DHCPCD_IPV4)
- 		dhcp_start(ifp);
-@@ -700,31 +731,17 @@
- static void
- run_preinit(struct interface *ifp)
- {
--	const char *reason;
- 
--	reason = NULL; /* appease gcc */
--	if (ifp->options->options & DHCPCD_LINK) {
--		switch (if_carrier(ifp)) {
--		case LINK_DOWN:
--			ifp->carrier = LINK_DOWN;
--			reason = "NOCARRIER";
--			break;
--		case LINK_UP:
--			ifp->carrier = LINK_UP;
--			reason = "CARRIER";
--			break;
--		default:
--			ifp->carrier = LINK_UNKNOWN;
--			return;
--		}
--	} else
--		ifp->carrier = LINK_UNKNOWN;
-+	pre_start(ifp);
-+	if (ifp->ctx->options & DHCPCD_TEST)
-+		return;
- 
--	if (!(ifp->ctx->options & DHCPCD_TEST))
--		script_runreason(ifp, "PREINIT");
-+	script_runreason(ifp, "PREINIT");
- 
--	if (ifp->carrier != LINK_UNKNOWN && !(ifp->ctx->options & DHCPCD_TEST))
--		script_runreason(ifp, reason);
-+	if (ifp->carrier != LINK_UNKNOWN &&
-+	    ifp->options->options & DHCPCD_LINK)
-+		script_runreason(ifp,
-+		    ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
- }
- 
- int
-@@ -732,7 +749,7 @@
- {
- 	struct dhcpcd_ctx *ctx;
- 	struct if_head *ifs;
--	struct interface *ifp, *ifn, *ifl = NULL;
-+	struct interface *ifp, *iff, *ifn;
- 	const char * const argv[] = { ifname };
- 	int i;
- 
-@@ -743,6 +760,7 @@
- 			errno = ESRCH;
- 			return -1;
- 		}
-+		syslog(LOG_DEBUG, "%s: interface departed", ifp->name);
- 		ifp->options->options |= DHCPCD_DEPARTED;
- 		stop_interface(ifp);
- 		return 0;
-@@ -764,22 +782,24 @@
- 			continue;
- 		i = 0;
- 		/* Check if we already have the interface */
--		ifl = if_find(ctx, ifp->name);
--		if (ifl) {
-+		iff = if_find(ctx, ifp->name);
-+		if (iff) {
-+			syslog(LOG_DEBUG, "%s: interface updated", iff->name);
- 			/* The flags and hwaddr could have changed */
--			ifl->flags = ifp->flags;
--			ifl->hwlen = ifp->hwlen;
-+			iff->flags = ifp->flags;
-+			iff->hwlen = ifp->hwlen;
- 			if (ifp->hwlen != 0)
--				memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
-+				memcpy(iff->hwaddr, ifp->hwaddr, iff->hwlen);
- 		} else {
-+			syslog(LOG_DEBUG, "%s: interface added", ifp->name);
- 			TAILQ_REMOVE(ifs, ifp, next);
- 			TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
--		}
--		if (action > 0) {
- 			init_state(ifp, ctx->argc, ctx->argv);
- 			run_preinit(ifp);
--			dhcpcd_startinterface(ifp);
-+			iff = ifp;
- 		}
-+		if (action > 0)
-+			dhcpcd_startinterface(iff);
- 	}
- 
- 	/* Free our discovered list */
-@@ -1264,6 +1284,8 @@
- 	ctx.ifv = argv + optind;
- 
- 	ifo = read_config(&ctx, NULL, NULL, NULL);
-+	if (ifo == NULL)
-+		goto exit_failure;
- 	opt = add_options(&ctx, NULL, ifo, argc, argv);
- 	if (opt != 1) {
- 		if (opt == 0)
-@@ -1272,17 +1294,26 @@
- 	}
- 	if (i == 3) {
- 		printf("Interface options:\n");
-+		if (optind == argc - 1) {
-+			free_options(ifo);
-+			ifo = read_config(&ctx, argv[optind], NULL, NULL);
-+			if (ifo == NULL)
-+				goto exit_failure;
-+			add_options(&ctx, NULL, ifo, argc, argv);
-+		}
- 		if_printoptions();
- #ifdef INET
- 		if (family == 0 || family == AF_INET) {
- 			printf("\nDHCPv4 options:\n");
--			dhcp_printoptions(&ctx);
-+			dhcp_printoptions(&ctx,
-+			    ifo->dhcp_override, ifo->dhcp_override_len);
- 		}
- #endif
- #ifdef INET6
- 		if (family == 0 || family == AF_INET6) {
- 			printf("\nDHCPv6 options:\n");
--			dhcp6_printoptions(&ctx);
-+			dhcp6_printoptions(&ctx,
-+			    ifo->dhcp6_override, ifo->dhcp6_override_len);
- 		}
- #endif
- 		goto exit_success;
-@@ -1341,9 +1372,10 @@
- 			}
- 			snprintf(pidfile, sizeof(pidfile),
- 			    PIDFILE, "-", argv[optind], per);
--		}
--		else {
--			snprintf(pidfile, sizeof(pidfile), PIDFILE, "", "", "");
-+		} else {
-+			snprintf(pidfile, sizeof(pidfile), PIDFILE,
-+			    ctx.options & DHCPCD_PFXDLGONLY ? ".pd" : "",
-+			    "", "");
- 			ctx.options |= DHCPCD_MASTER;
- 		}
- 	}
-@@ -1351,18 +1383,52 @@
- 	if (chdir("/") == -1)
- 		syslog(LOG_ERR, "chdir `/': %m");
- 
-+	/* Freeing allocated addresses from dumping leases can trigger
-+	 * eloop removals as well, so init here. */
-+	ctx.eloop = eloop_init();
-+	if (ctx.eloop == NULL) {
-+		syslog(LOG_ERR, "%s: %m", __func__);
-+		goto exit_failure;
-+	}
-+
- 	if (ctx.options & DHCPCD_DUMPLEASE) {
- 		if (optind != argc - 1) {
- 			syslog(LOG_ERR, "dumplease requires an interface");
- 			goto exit_failure;
- 		}
--		if (dhcp_dump(&ctx, argv[optind]) == -1)
-+		i = 0;
-+		/* We need to try and find the interface so we can
-+		 * load the hardware address to compare automated IAID */
-+		ctx.ifaces = if_discover(&ctx, 1, argv + optind);
-+		if (ctx.ifaces == NULL)
-+			goto exit_failure;
-+		ifp = TAILQ_FIRST(ctx.ifaces);
-+		if (ifp == NULL) {
-+			ifp = calloc(1, sizeof(*ifp));
-+			if (ifp == NULL) {
-+				syslog(LOG_ERR, "%s: %m", __func__);
-+				goto exit_failure;
-+			}
-+			strlcpy(ifp->name, argv[optind], sizeof(ifp->name));
-+			ifp->ctx = &ctx;
-+			TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next);
-+		}
-+		configure_interface(ifp, ctx.argc, ctx.argv);
-+		if (family == 0 || family == AF_INET) {
-+			if (dhcp_dump(ifp) == -1)
-+				i = 1;
-+		}
-+		if (family == 0 || family == AF_INET6) {
-+			if (dhcp6_dump(ifp) == -1)
-+				i = 1;
-+		}
-+		if (i == -1)
- 			goto exit_failure;
- 		goto exit_success;
- 	}
- 
- #ifdef USE_SIGNALS
--	if (!(ctx.options & DHCPCD_TEST) &&
-+	if (!(ctx.options & (DHCPCD_TEST | DHCPCD_PFXDLGONLY)) &&
- 	    (sig == 0 || ctx.ifc != 0))
- 	{
- #endif
-@@ -1396,12 +1462,6 @@
- 		syslog(LOG_WARNING,
- 		    PACKAGE " will not work correctly unless run as root");
- 
--	ctx.eloop = eloop_init();
--	if (ctx.eloop == NULL) {
--		syslog(LOG_ERR, "%s: %m", __func__);
--		goto exit_failure;
--	}
--
- #ifdef USE_SIGNALS
- 	if (sig != 0) {
- 		pid = read_pid(pidfile);
-@@ -1484,7 +1544,7 @@
- 	}
- 
- 
--	if (ctx.options & DHCPCD_MASTER) {
-+	if (ctx.options & DHCPCD_MASTER && !(ctx.options & DHCPCD_PFXDLGONLY)) {
- 		if (control_start(&ctx, NULL) == -1)
- 			syslog(LOG_ERR, "control_start: %m");
- 	}
-@@ -1622,7 +1682,6 @@
- 
- 	free_options(ifo);
- 	free_globals(&ctx);
--	if_rarestore(&ctx);
- 	ipv4_ctxfree(&ctx);
- 	ipv6_ctxfree(&ctx);
- 	dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED));
-diff -urN dhcpcd-6.4.0.org/dhcpcd.conf.5.in dhcpcd-6.4.0/dhcpcd.conf.5.in
---- dhcpcd-6.4.0.org/dhcpcd.conf.5.in	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.conf.5.in	2014-07-05 21:47:22.000000000 +0200
-@@ -22,7 +22,7 @@
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
--.Dd June 6, 2014
-+.Dd July 4, 2014
- .Dt DHCPCD.CONF 5
- .Os
- .Sh NAME
-@@ -214,7 +214,7 @@
- Also, see the
- .Ic env
- option above to control how the hostname is set on the host.
--.It Ic ia_na Op Ar iaid
-+.It Ic ia_na Op Ar iaid Op / address
- Request a DHCPv6 Normal Address for
- .Ar iaid .
- .Ar iaid
-@@ -230,7 +230,7 @@
- You can request more than one ia_ta by specifying a unique
- .Ar iaid
- for each one.
--.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len
-+.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len
- Request a DHCPv6 Delegated Prefix for
- .Ar iaid .
- This option must be used in an
-@@ -250,7 +250,10 @@
- and
- .Ar sla_id .
- Each assigned address will have a suffix of 1.
--You cannot assign a prefix to the requesting interface.
-+You cannot assign a prefix to the requesting interface unless the
-+DHCPv6 server supports
-+.Li RFC6603
-+Prefix Exclude Option.
- .Nm dhcpcd
- has to be running for all the interfaces it is delegating to.
- A default
-@@ -290,6 +293,12 @@
- .D1 interface eth1
- .D1 ipv4
- .D1 ipv6rs
-+.Pp
-+Using this option with other IA options in the same interface block is not
-+currently RFC conformant.
-+Please see the
-+.Li BUGS
-+section below.
- .It Ic ipv4only
- Only configure IPv4.
- .It Ic ipv6only
-@@ -457,6 +466,9 @@
- .Ar ssid .
- .It Ic slaac Op Ar hwaddr | Ar private
- Selects the interface identifier used for SLAAC generated IPv6 addresses.
-+If
-+.Ar private
-+is used, a RFC7217 address is generated.
- .It Ic static Ar value
- Configures a static
- .Ar value .
-@@ -739,11 +751,21 @@
- .Sh AUTHORS
- .An Roy Marples Aq Mt roy at marples.name
- .Sh BUGS
--When configuring DHCPv6 you can only select one IA type.
--I can't think of a use case where you would want different types,
--so if you have one then please bring it up for discussion on the
--.Aq Mt  dhcpcd-discuss at marples.name
--mailing list.
-+Combining different DHCPv6 IA options in the same interface block is not
-+currently RFC conformant.
-+See
-+.Lk http://datatracker.ietf.org/doc/draft-ietf-dhc-dhcpv6-stateful-issues
-+for details.
-+.Nm dhcpcd
-+strives to comply with this document and will be updated when finally published.
-+To enable RFC conformance, spawn separate
-+.Nm dhcpcd
-+instances using the
-+.Fl Fl pfxdlgonly
-+and
-+.Fl Fl nopfxdlg
-+options as described in
-+.Xr dhcpcd 8 .
- .Pp
- Please report them to
- .Lk http://roy.marples.name/projects/dhcpcd
-diff -urN dhcpcd-6.4.0.org/dhcpcd-definitions.conf dhcpcd-6.4.0/dhcpcd-definitions.conf
---- dhcpcd-6.4.0.org/dhcpcd-definitions.conf	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-definitions.conf	2014-07-05 21:47:22.000000000 +0200
-@@ -360,6 +360,7 @@
- embed		uint32			vltime
- embed		ip6address		prefix
- encap 13	option
-+encap 67	option
- 
- # DHCPv6 Network Information Service Options, RFC3898
- define6 27	array ip6address	nis_servers
-@@ -463,6 +464,11 @@
- # DHCPv6 AFTR-Name, RFC6334
- define6 64	domain			aftr_name
- 
-+# DHCPv6 Prefix Exclude Option, RFC6603
-+define6 67	embed			pd_exclude
-+embed		byte			prefix_len
-+embed		binhex			subnetID
-+
- # DHCPv6 Home Info Discovery in MIPv6, RFC6610
- define6 69	encap			mip6_idinf
- encap 71	option
-diff -urN dhcpcd-6.4.0.org/dhcpcd.h dhcpcd-6.4.0/dhcpcd.h
---- dhcpcd-6.4.0.org/dhcpcd.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd.h	2014-07-05 21:47:22.000000000 +0200
-@@ -123,11 +123,8 @@
- 	struct dhcp_opt *dhcp6_opts;
- 	size_t dhcp6_opts_len;
- 	struct ipv6_ctx *ipv6;
--	char **ra_restore;
--	size_t ra_restore_len;
- #ifndef __linux__
- 	int ra_global;
--	int ra_kernel_set;
- #endif
- #endif /* INET6 */
- 
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/02-dump dhcpcd-6.4.0/dhcpcd-hooks/02-dump
---- dhcpcd-6.4.0.org/dhcpcd-hooks/02-dump	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/02-dump	2014-07-05 21:47:22.000000000 +0200
-@@ -1,6 +1,8 @@
- # Just echo our DHCP options we have
- 
--if [ "$reason" = "DUMP" ]; then
-+case "$reason" in
-+DUMP|DUMP6)
- 	set | sed -ne 's/^new_//p' | sort
- 	exit 0
--fi
-+	;;
-+esac
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/20-resolv.conf dhcpcd-6.4.0/dhcpcd-hooks/20-resolv.conf
---- dhcpcd-6.4.0.org/dhcpcd-hooks/20-resolv.conf	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/20-resolv.conf	2014-07-05 21:47:22.000000000 +0200
-@@ -70,7 +70,7 @@
- 
- add_resolv_conf()
- {
--	local x= conf="$signature$NL" i=${ra_count:-0} ra=
-+	local x= conf="$signature$NL" i=${ra_count:-0} ra= warn=true
- 
- 	while [ $i -ne 0 ]; do
- 		eval ra=\$ra${i}_rdnss
-@@ -101,24 +101,23 @@
- 
- 	if [ -n "$new_domain_name" ]; then
- 		set -- $new_domain_name
--		new_domain_name="$1"
--		if valid_domainname "$new_domain_name"; then
--			conf="${conf}domain $new_domain_name$NL"
-+		if valid_domainname "$1"; then
-+			conf="${conf}domain $1$NL"
- 		else
--			syslog err "Invalid domain name: $new_domain_name"
-+			syslog err "Invalid domain name: $1"
- 		fi
--		# Support RFC violating search in domain
--		if [ -z "$new_domain_search" -a -n "$2" ]; then
--			new_domain_search="$*"
-+		# If there is no search this, make this one
-+		if [ -z "$new_domain_search" ]; then
-+			new_domain_search="$new_domain_name"
-+			[ "$new_domain_name" = "$1" ] && warn=true
- 		fi
- 	fi
--	if [ -n "$new_domain_search" -a \
--	    "$new_domain_search" != "$new_domain_name" ]
--	then
-+	if [ -n "$new_domain_search" ]; then
- 		if valid_domainname_list $new_domain_search; then
- 			conf="${conf}search $new_domain_search$NL"
--		else
--			syslog err "Invalid domain name in list: $new_domain_search"
-+		elif ! $warn; then
-+			syslog err "Invalid domain name in list:" \
-+			    "$new_domain_search"
- 		fi
- 	fi
- 	for x in ${new_domain_name_servers}; do
-diff -urN dhcpcd-6.4.0.org/dhcpcd-hooks/Makefile dhcpcd-6.4.0/dhcpcd-hooks/Makefile
---- dhcpcd-6.4.0.org/dhcpcd-hooks/Makefile	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcpcd-hooks/Makefile	2014-07-05 21:47:22.000000000 +0200
-@@ -25,7 +25,7 @@
- 
- install: proginstall
- 
--import:
-+import: ${HOOKSCRIPTS}
- 	${INSTALL} -d /tmp/${DISTPREFIX}/dhcpcd-hooks
- 	for x in ${SCRIPTS}; do \
- 		t="/tmp/${DISTPREFIX}/dhcpcd-hooks/$$x"; \
-diff -urN dhcpcd-6.4.0.org/dhcp-common.c dhcpcd-6.4.0/dhcp-common.c
---- dhcpcd-6.4.0.org/dhcp-common.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp-common.c	2014-07-05 21:47:22.000000000 +0200
-@@ -86,6 +86,7 @@
- 
- int
- make_option_mask(const struct dhcp_opt *dopts, size_t dopts_len,
-+    const struct dhcp_opt *odopts, size_t odopts_len,
-     uint8_t *mask, const char *opts, int add)
- {
- 	char *token, *o, *p, *t;
-@@ -94,14 +95,14 @@
- 	unsigned int n;
- 	size_t i;
- 
--	o = p = strdup(opts);
- 	if (opts == NULL)
- 		return -1;
-+	o = p = strdup(opts);
- 	while ((token = strsep(&p, ", "))) {
- 		if (*token == '\0')
- 			continue;
--		for (i = 0, opt = dopts; i < dopts_len; i++, opt++) {
--			match = 0;
-+		match = 0;
-+		for (i = 0, opt = odopts; i < odopts_len; i++, opt++) {
- 			if (strcmp(opt->var, token) == 0)
- 				match = 1;
- 			else {
-@@ -111,26 +112,40 @@
- 					if (opt->option == n)
- 						match = 1;
- 			}
--			if (match) {
--				if (add == 2 && !(opt->type & ADDRIPV4)) {
--					free(o);
--					errno = EINVAL;
--					return -1;
--				}
--				if (add == 1 || add == 2)
--					add_option_mask(mask,
--					    opt->option);
--				else
--					del_option_mask(mask,
--					    opt->option);
-+			if (match)
- 				break;
-+		}
-+		if (match == 0) {
-+			for (i = 0, opt = dopts; i < dopts_len; i++, opt++) {
-+				if (strcmp(opt->var, token) == 0)
-+				        match = 1;
-+				else {
-+					errno = 0;
-+					n = (unsigned int)strtol(token, &t, 0);
-+					if (errno == 0 && !*t)
-+						if (opt->option == n)
-+							match = 1;
-+				}
-+				if (match)
-+					break;
- 			}
- 		}
--		if (!opt->option) {
-+		if (!match || !opt->option) {
- 			free(o);
- 			errno = ENOENT;
- 			return -1;
- 		}
-+		if (add == 2 && !(opt->type & ADDRIPV4)) {
-+			free(o);
-+			errno = EINVAL;
-+			return -1;
-+		}
-+		if (add == 1 || add == 2)
-+			add_option_mask(mask,
-+			    opt->option);
-+		else
-+			del_option_mask(mask,
-+			    opt->option);
- 	}
- 	free(o);
- 	return 0;
-diff -urN dhcpcd-6.4.0.org/dhcp-common.h dhcpcd-6.4.0/dhcp-common.h
---- dhcpcd-6.4.0.org/dhcp-common.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp-common.h	2014-07-05 21:47:22.000000000 +0200
-@@ -88,6 +88,7 @@
- #define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
- #define has_option_mask(var, val) (var[val >>3] & (1 << (val & 7)))
- int make_option_mask(const struct dhcp_opt *, size_t,
-+    const struct dhcp_opt *, size_t,
-     uint8_t *, const char *, int);
- 
- size_t encode_rfc1035(const char *src, uint8_t *dst);
-diff -urN dhcpcd-6.4.0.org/dhcp.h dhcpcd-6.4.0/dhcp.h
---- dhcpcd-6.4.0.org/dhcp.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/dhcp.h	2014-07-05 21:47:22.000000000 +0200
-@@ -250,7 +250,8 @@
- ssize_t decode_rfc3442(char *, size_t, const uint8_t *p, size_t);
- ssize_t decode_rfc5969(char *, size_t, const uint8_t *p, size_t);
- 
--void dhcp_printoptions(const struct dhcpcd_ctx *);
-+void dhcp_printoptions(const struct dhcpcd_ctx *,
-+    const struct dhcp_opt *, size_t);
- int get_option_addr(struct dhcpcd_ctx *,struct in_addr *,
-     const struct dhcp_message *, uint8_t);
- #define is_bootp(i, m) ((m) &&						\
-@@ -285,16 +286,15 @@
- void dhcp_reboot_newopts(struct interface *, unsigned long long);
- void dhcp_close(struct interface *);
- void dhcp_free(struct interface *);
--int dhcp_dump(struct dhcpcd_ctx *, const char *);
-+int dhcp_dump(struct interface *);
- #else
--#define dhcp_printoptions
- #define dhcp_drop(a, b)
- #define dhcp_start(a) {}
- #define dhcp_reboot(a, b) b = b
- #define dhcp_reboot_newopts(a, b)
- #define dhcp_close(a)
- #define dhcp_free(a)
--#define dhcp_dump(a, b) -1
-+#define dhcp_dump(a) -1
- #endif
- 
- #endif
-diff -urN dhcpcd-6.4.0.org/if-bsd.c dhcpcd-6.4.0/if-bsd.c
---- dhcpcd-6.4.0.org/if-bsd.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-bsd.c	2014-07-05 21:47:22.000000000 +0200
-@@ -1019,45 +1019,6 @@
- 	return flags;
- }
- 
--void
--if_rarestore(struct dhcpcd_ctx *ctx)
--{
--
--	if (ctx->options & DHCPCD_FORKED)
--		return;
--
--	for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) {
--#ifdef ND6_IFF_ACCEPT_RTADV
--		if (!(ctx->options & DHCPCD_FORKED)) {
--			syslog(LOG_DEBUG,
--			    "%s: restoring kernel IPv6 RA support",
--			    ctx->ra_restore[ctx->ra_restore_len - 1]);
--			if (set_if_nd6_flag(
--			    ctx->ra_restore[ctx->ra_restore_len -1],
--			    ND6_IFF_ACCEPT_RTADV) == -1)
--				syslog(LOG_ERR, "%s: set_if_nd6_flag: %m",
--				    ctx->ra_restore[ctx->ra_restore_len - 1]);
--#ifdef ND6_IFF_OVERRIDE_RTADV
--			if (ctx->ra_kernel_set == 0 && del_if_nd6_flag(
--			    ctx->ra_restore[ctx->ra_restore_len -1],
--			    ND6_IFF_OVERRIDE_RTADV) == -1)
--				syslog(LOG_ERR, "%s: del_if_nd6_flag: %m",
--				    ctx->ra_restore[ctx->ra_restore_len - 1]);
--#endif
--		}
--#endif
--		free(ctx->ra_restore[ctx->ra_restore_len - 1]);
--	}
--	free(ctx->ra_restore);
--	ctx->ra_restore = NULL;
--
--	if (ctx->ra_kernel_set) {
--		syslog(LOG_DEBUG, "restoring kernel IPv6 RA support");
--		if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 1) == -1)
--			syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
--	}
--}
--
- static int
- if_raflush(void)
- {
-@@ -1085,10 +1046,6 @@
- #ifdef ND6_IFF_OVERRIDE_RTADV
- 		int override;
- #endif
--#ifdef ND6_IFF_ACCEPT_RTADV
--		size_t i;
--		char *p, **nrest;
--#endif
- 
- #ifdef ND6_IFF_IFDISABLED
- 		if (del_if_nd6_flag(ifname, ND6_IFF_IFDISABLED) == -1) {
-@@ -1166,7 +1123,7 @@
- 				return ra;
- 			}
- #ifdef ND6_IFF_OVERRIDE_RTADV
--			if (override == 0 && ctx->ra_kernel_set == 0 &&
-+			if (override == 0 &&
- 			    set_if_nd6_flag(ifname, ND6_IFF_OVERRIDE_RTADV)
- 			    == -1)
- 			{
-@@ -1177,25 +1134,6 @@
- 				return ra;
- 			}
- #endif
--			for (i = 0; i < ctx->ra_restore_len; i++)
--				if (strcmp(ctx->ra_restore[i], ifname) == 0)
--					break;
--			if (i == ctx->ra_restore_len) {
--				p = strdup(ifname);
--				if (p == NULL) {
--					syslog(LOG_ERR, "%s: %m", __func__);
--					return 0;
--				}
--				nrest = realloc(ctx->ra_restore,
--				    (ctx->ra_restore_len + 1) * sizeof(char *));
--				if (nrest == NULL) {
--					syslog(LOG_ERR, "%s: %m", __func__);
--					free(p);
--					return 0;
--				}
--				ctx->ra_restore = nrest;
--				ctx->ra_restore[ctx->ra_restore_len++] = p;
--			}
- 			return 0;
- 		}
- 		return ra;
-@@ -1217,7 +1155,6 @@
- 			return ra;
- 		}
- 		ra = 0;
--		ctx->ra_kernel_set = 1;
- 
- 		/* Flush the kernel knowledge of advertised routers
- 		 * and prefixes so the kernel does not expire prefixes
-diff -urN dhcpcd-6.4.0.org/if.c dhcpcd-6.4.0/if.c
---- dhcpcd-6.4.0.org/if.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if.c	2014-07-05 21:47:22.000000000 +0200
-@@ -133,7 +133,7 @@
- }
- 
- int
--if_up(struct interface *ifp)
-+if_setflag(struct interface *ifp, short flag)
- {
- 	struct ifreq ifr;
- 	int s, r;
-@@ -152,10 +152,10 @@
- #endif
- 	r = -1;
- 	if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
--		if ((ifr.ifr_flags & IFF_UP))
-+		if (flag == 0 || ifr.ifr_flags & flag)
- 			r = 0;
- 		else {
--			ifr.ifr_flags |= IFF_UP;
-+			ifr.ifr_flags |= flag;
- 			if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
- 				r = 0;
- 		}
-@@ -295,6 +295,7 @@
- 		ifp->ctx = ctx;
- 		strlcpy(ifp->name, p, sizeof(ifp->name));
- 		ifp->flags = ifa->ifa_flags;
-+		ifp->carrier = if_carrier(ifp);
- 
- 		sdl_type = 0;
- 		/* Don't allow loopback unless explicit */
-diff -urN dhcpcd-6.4.0.org/if.h dhcpcd-6.4.0/if.h
---- dhcpcd-6.4.0.org/if.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if.h	2014-07-05 21:47:22.000000000 +0200
-@@ -90,7 +90,8 @@
- #define RAW_EOF			1 << 0
- #define RAW_PARTIALCSUM		2 << 0
- 
--int if_up(struct interface *ifp);
-+int if_setflag(struct interface *ifp, short flag);
-+#define if_up(ifp) if_setflag((ifp), IFF_UP)
- struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
- struct interface *if_find(struct dhcpcd_ctx *, const char *);
- void if_free(struct interface *);
-@@ -131,7 +132,6 @@
- 
- #ifdef INET6
- int if_checkipv6(struct dhcpcd_ctx *ctx, const char *, int);
--void if_rarestore(struct dhcpcd_ctx *);
- int if_nd6reachable(const char *ifname, struct in6_addr *addr);
- 
- int if_address6(const struct ipv6_addr *, int);
-@@ -145,7 +145,6 @@
- #define if_delroute6(rt) if_route6(rt, -1)
- #else
- #define if_checkipv6(a, b, c) (-1)
--#define if_rarestore(a)
- #endif
- 
- int if_machinearch(char *, size_t);
-diff -urN dhcpcd-6.4.0.org/if-linux.c dhcpcd-6.4.0/if-linux.c
---- dhcpcd-6.4.0.org/if-linux.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-linux.c	2014-07-05 21:47:22.000000000 +0200
-@@ -1223,33 +1223,11 @@
- 
- static const char *prefix = "/proc/sys/net/ipv6/conf";
- 
--void
--if_rarestore(struct dhcpcd_ctx *ctx)
--{
--	char path[256];
--
--	for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) {
--		if (!(ctx->options & DHCPCD_FORKED)) {
--			syslog(LOG_DEBUG,
--			    "%s: restoring kernel IPv6 RA support",
--			    ctx->ra_restore[ctx->ra_restore_len - 1]);
--			snprintf(path, sizeof(path), "%s/%s/accept_ra",
--			    prefix, ctx->ra_restore[ctx->ra_restore_len - 1]);
--			if (write_path(path, "1") == -1 && errno != ENOENT)
--			    syslog(LOG_ERR, "write_path: %s: %m", path);
--		}
--		free(ctx->ra_restore[ctx->ra_restore_len - 1]);
--	}
--	free(ctx->ra_restore);
--	ctx->ra_restore = NULL;
--}
--
- int
--if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
-+if_checkipv6(__unused struct dhcpcd_ctx *ctx, const char *ifname, int own)
- {
- 	int ra;
--	size_t i;
--	char path[256], *p, **nrest;
-+	char path[256];
- 
- 	if (ifname == NULL)
- 		ifname = "all";
-@@ -1283,25 +1261,6 @@
- 			syslog(LOG_ERR, "write_path: %s: %m", path);
- 			return ra;
- 		}
--		for (i = 0; i < ctx->ra_restore_len; i++)
--			if (strcmp(ctx->ra_restore[i], ifname) == 0)
--				break;
--		if (i == ctx->ra_restore_len) {
--			p = strdup(ifname);
--			if (p == NULL) {
--				syslog(LOG_ERR, "%s: %m", __func__);
--				return 0;
--			}
--			nrest = realloc(ctx->ra_restore,
--			    (ctx->ra_restore_len + 1) * sizeof(char *));
--			if (nrest == NULL) {
--				syslog(LOG_ERR, "%s: %m", __func__);
--				free(p);
--				return 0;
--			}
--			ctx->ra_restore = nrest;
--			ctx->ra_restore[ctx->ra_restore_len++] = p;
--		}
- 		return 0;
- 	}
- 
-diff -urN dhcpcd-6.4.0.org/if-options.c dhcpcd-6.4.0/if-options.c
---- dhcpcd-6.4.0.org/if-options.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-options.c	2014-07-05 21:47:22.000000000 +0200
-@@ -93,6 +93,8 @@
- #define O_CONTROLGRP		O_BASE + 34
- #define O_SLAAC			O_BASE + 35
- #define O_GATEWAY		O_BASE + 36
-+#define O_NOPFXDLG		O_BASE + 37
-+#define O_PFXDLGONLY		O_BASE + 38
- 
- const struct option cf_options[] = {
- 	{"background",      no_argument,       NULL, 'b'},
-@@ -179,6 +181,8 @@
- 	{"controlgroup",    required_argument, NULL, O_CONTROLGRP},
- 	{"slaac",           required_argument, NULL, O_SLAAC},
- 	{"gateway",         no_argument,       NULL, O_GATEWAY},
-+	{"nopfxdlg",        no_argument,       NULL, O_NOPFXDLG},
-+	{"pfxdlgonly",      no_argument,       NULL, O_PFXDLGONLY},
- 	{NULL,              0,                 NULL, '\0'}
- };
- 
-@@ -518,7 +522,9 @@
- 
- static const char *
- set_option_space(struct dhcpcd_ctx *ctx,
--    const char *arg, const struct dhcp_opt **d, size_t *dl,
-+    const char *arg,
-+    const struct dhcp_opt **d, size_t *dl,
-+    const struct dhcp_opt **od, size_t *odl,
-     struct if_options *ifo,
-     uint8_t *request[], uint8_t *require[], uint8_t *no[])
- {
-@@ -527,6 +533,8 @@
- 	if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
- 		*d = ctx->dhcp6_opts;
- 		*dl = ctx->dhcp6_opts_len;
-+		*od = ifo->dhcp6_override;
-+		*odl = ifo->dhcp6_override_len;
- 		*request = ifo->requestmask6;
- 		*require = ifo->requiremask6;
- 		*no = ifo->nomask6;
-@@ -537,9 +545,13 @@
- #ifdef INET
- 	*d = ctx->dhcp_opts;
- 	*dl = ctx->dhcp_opts_len;
-+	*od = ifo->dhcp_override;
-+	*odl = ifo->dhcp_override_len;
- #else
- 	*d = NULL;
- 	*dl = 0;
-+	*od = NULL;
-+	*odl = 0;
- #endif
- 	*request = ifo->requestmask;
- 	*require = ifo->requiremask;
-@@ -630,10 +642,10 @@
- 	struct in_addr addr, addr2;
- 	in_addr_t *naddr;
- 	struct rt *rt;
--	const struct dhcp_opt *d;
-+	const struct dhcp_opt *d, *od;
- 	uint8_t *request, *require, *no;
- 	struct dhcp_opt **dop, *ndop;
--	size_t *dop_len, dl;
-+	size_t *dop_len, dl, odl;
- 	struct vivco *vivco;
- 	struct token *token;
- 	struct group *grp;
-@@ -733,10 +745,10 @@
- 		}
- 		break;
- 	case 'o':
--		arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
- 		    &request, &require, &no);
--		if (make_option_mask(d, dl, request, arg, 1) != 0 ||
--		    make_option_mask(d, dl, no, arg, -1) != 0)
-+		if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-+		    make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
- 		{
- 			syslog(LOG_ERR, "unknown option `%s'", arg);
- 			return -1;
-@@ -952,22 +964,22 @@
- 		ifo->options |= DHCPCD_MASTER;
- 		break;
- 	case 'O':
--		arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
- 		    &request, &require, &no);
--		if (make_option_mask(d, dl, request, arg, -1) != 0 ||
--		    make_option_mask(d, dl, require, arg, -1) != 0 ||
--		    make_option_mask(d, dl, no, arg, 1) != 0)
-+		if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
-+		    make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
-+		    make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
- 		{
- 			syslog(LOG_ERR, "unknown option `%s'", arg);
- 			return -1;
- 		}
- 		break;
- 	case 'Q':
--		arg = set_option_space(ctx, arg, &d, &dl, ifo,
-+		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
- 		    &request, &require, &no);
--		if (make_option_mask(d, dl, require, arg, 1) != 0 ||
--		    make_option_mask(d, dl, request, arg, 1) != 0 ||
--		    make_option_mask(d, dl, no, arg, -1) != 0)
-+		if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
-+		    make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-+		    make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
- 		{
- 			syslog(LOG_ERR, "unknown option `%s'", arg);
- 			return -1;
-@@ -1156,8 +1168,11 @@
- 		}
- 		break;
- 	case O_DESTINATION:
--		if (make_option_mask(ctx->dhcp_opts, ctx->dhcp_opts_len,
--		    ifo->dstmask, arg, 2) != 0) {
-+		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-+		    &request, &require, &no);
-+		if (make_option_mask(d, dl, od, odl,
-+		    ifo->dstmask, arg, 2) != 0)
-+		{
- 			if (errno == EINVAL)
- 				syslog(LOG_ERR, "option `%s' does not take"
- 				    " an IPv4 address", arg);
-@@ -1220,35 +1235,40 @@
- 			}
- 			i = D6_OPTION_IA_PD;
- 		}
--		if (arg != NULL && ifname == NULL) {
-+		if (ifname == NULL && arg) {
- 			syslog(LOG_ERR,
- 			    "IA with IAID must belong in an interface block");
- 			return -1;
- 		}
- 		ifo->options |= DHCPCD_IA_FORCED;
--		if (ifo->ia_type != 0 && ifo->ia_type != i) {
--			syslog(LOG_ERR, "cannot specify a different IA type");
--			return -1;
--		}
--		ifo->ia_type = (uint16_t)i;
--		if (arg == NULL)
--			break;
- 		fp = strwhite(arg);
--		if (fp)
-+		if (fp) {
- 			*fp++ = '\0';
--		if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
--			return -1;
-+			fp = strskipwhite(fp);
-+		}
-+		if (arg) {
-+			p = strchr(arg, '/');
-+			if (p)
-+				*p++ = '\0';
-+			if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
-+				return -1;
-+		}
- 		ia = NULL;
- 		for (sl = 0; sl < ifo->ia_len; sl++) {
--			if (ifo->ia[sl].iaid[0] == iaid[0] &&
-+			if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
-+			    (ifo->ia[sl].iaid[0] == iaid[0] &&
- 			    ifo->ia[sl].iaid[1] == iaid[1] &&
- 			    ifo->ia[sl].iaid[2] == iaid[2] &&
--			    ifo->ia[sl].iaid[3] == iaid[3])
-+			    ifo->ia[sl].iaid[3] == iaid[3]))
- 			{
- 			        ia = &ifo->ia[sl];
- 				break;
- 			}
- 		}
-+		if (ia && ia->ia_type != (uint16_t)i) {
-+			syslog(LOG_ERR, "Cannot mix IA for the same IAID");
-+			break;
-+		}
- 		if (ia == NULL) {
- 			ia = realloc(ifo->ia,
- 			    sizeof(*ifo->ia) * (ifo->ia_len + 1));
-@@ -1258,14 +1278,47 @@
- 			}
- 			ifo->ia = ia;
- 			ia = &ifo->ia[ifo->ia_len++];
--			ia->iaid[0] = iaid[0];
--			ia->iaid[1] = iaid[1];
--			ia->iaid[2] = iaid[2];
--			ia->iaid[3] = iaid[3];
--			ia->sla = NULL;
-+			ia->ia_type = (uint16_t)i;
-+			if (arg) {
-+				ia->iaid[0] = iaid[0];
-+				ia->iaid[1] = iaid[1];
-+				ia->iaid[2] = iaid[2];
-+				ia->iaid[3] = iaid[3];
-+				ia->iaid_set = 1;
-+			} else
-+				ia->iaid_set = 0;
-+			if (!ia->iaid_set ||
-+			    p == NULL ||
-+			    ia->ia_type == D6_OPTION_IA_TA)
-+			{
-+				memset(&ia->addr, 0, sizeof(ia->addr));
-+				ia->prefix_len = 0;
-+			} else {
-+				arg = p;
-+				p = strchr(arg, '/');
-+				if (p)
-+					*p++ = '\0';
-+				if (inet_pton(AF_INET6, arg, &ia->addr) == -1) {
-+					syslog(LOG_ERR, "%s: %m", arg);
-+					memset(&ia->addr, 0, sizeof(ia->addr));
-+				}
-+				if (p && ia->ia_type == D6_OPTION_IA_PD) {
-+					i = atoint(p);
-+					if (i != -1 && (i < 8 || i > 120)) {
-+						errno = EINVAL;
-+						i = -1;
-+					}
-+					if (i == -1) {
-+						syslog(LOG_ERR, "%s: %m", p);
-+						ia->prefix_len = 0;
-+					} else
-+						ia->prefix_len = (uint8_t)i;
-+				}
-+			}
- 			ia->sla_len = 0;
-+			ia->sla = NULL;
- 		}
--		if (ifo->ia_type != D6_OPTION_IA_PD)
-+		if (ia->ia_type != D6_OPTION_IA_PD)
- 			break;
- 		for (p = fp; p; p = fp) {
- 			fp = strwhite(p);
-@@ -1284,12 +1337,6 @@
- 			np = strchr(p, '/');
- 			if (np)
- 				*np++ = '\0';
--			if (strcmp(ifname, p) == 0) {
--				syslog(LOG_ERR,
--				    "%s: cannot assign IA_PD to itself",
--				    ifname);
--				goto err_sla;
--			}
- 			if (strlcpy(sla->ifname, p,
- 			    sizeof(sla->ifname)) >= sizeof(sla->ifname))
- 			{
-@@ -1853,6 +1900,12 @@
- 		else
- 			ifo->options &= ~DHCPCD_SLAACPRIVATE;
- 		break;
-+	case O_NOPFXDLG:
-+		ifo->options |= DHCPCD_NOPFXDLG;
-+		break;
-+	case O_PFXDLGONLY:
-+		ifo->options |= DHCPCD_PFXDLGONLY;
-+		break;
- 	default:
- 		return 0;
- 	}
-@@ -2124,6 +2177,10 @@
- 				skip = 1;
- 			continue;
- 		}
-+		/* Skip arping if we have selected a profile but not parsing
-+		 * one. */
-+		if (profile && !have_profile && strcmp(option, "arping") == 0)
-+			continue;
- 		if (skip)
- 			continue;
- 		parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);
-diff -urN dhcpcd-6.4.0.org/if-options.h dhcpcd-6.4.0/if-options.h
---- dhcpcd-6.4.0.org/if-options.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/if-options.h	2014-07-05 21:47:22.000000000 +0200
-@@ -28,6 +28,7 @@
- #ifndef IF_OPTIONS_H
- #define IF_OPTIONS_H
- 
-+#include <sys/param.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <netinet/in.h>
-@@ -102,6 +103,8 @@
- #define DHCPCD_IAID			(1ULL << 48)
- #define DHCPCD_DHCP			(1ULL << 49)
- #define DHCPCD_DHCP6			(1ULL << 50)
-+#define DHCPCD_NOPFXDLG			(1ULL << 51)
-+#define DHCPCD_PFXDLGONLY		(1ULL << 52)
- 
- extern const struct option cf_options[];
- 
-@@ -115,6 +118,10 @@
- struct if_ia {
- 	uint8_t iaid[4];
- #ifdef INET6
-+	uint16_t ia_type;
-+	uint8_t iaid_set;
-+	struct in6_addr addr;
-+	uint8_t prefix_len;
- 	size_t sla_len;
- 	struct if_sla *sla;
- #endif
-@@ -128,13 +135,13 @@
- struct if_options {
- 	uint8_t iaid[4];
- 	int metric;
--	uint8_t requestmask[256 / 8];
--	uint8_t requiremask[256 / 8];
--	uint8_t nomask[256 / 8];
--	uint8_t requestmask6[(UINT16_MAX + 1) / 8];
--	uint8_t requiremask6[(UINT16_MAX + 1) / 8];
--	uint8_t nomask6[(UINT16_MAX + 1) / 8];
--	uint8_t dstmask[256 / 8];
-+	uint8_t requestmask[256 / NBBY];
-+	uint8_t requiremask[256 / NBBY];
-+	uint8_t nomask[256 / NBBY];
-+	uint8_t requestmask6[(UINT16_MAX + 1) / NBBY];
-+	uint8_t requiremask6[(UINT16_MAX + 1) / NBBY];
-+	uint8_t nomask6[(UINT16_MAX + 1) / NBBY];
-+	uint8_t dstmask[256 / NBBY];
- 	uint32_t leasetime;
- 	time_t timeout;
- 	time_t reboot;
-@@ -163,7 +170,6 @@
- 	in_addr_t *arping;
- 	char *fallback;
- 
--	uint16_t ia_type;
- 	struct if_ia *ia;
- 	size_t ia_len;
- 
-diff -urN dhcpcd-6.4.0.org/ipv4.c dhcpcd-6.4.0/ipv4.c
---- dhcpcd-6.4.0.org/ipv4.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv4.c	2014-07-05 21:47:22.000000000 +0200
-@@ -82,13 +82,13 @@
- 		errno = EINVAL;
- 		return -1;
- 	}
--	ocets = (cidr + 7) / 8;
-+	ocets = (cidr + 7) / NBBY;
- 
- 	addr->s_addr = 0;
- 	if (ocets > 0) {
- 		memset(&addr->s_addr, 255, (size_t)ocets - 1);
- 		memset((unsigned char *)&addr->s_addr + (ocets - 1),
--		    (256 - (1 << (32 - cidr) % 8)), 1);
-+		    (256 - (1 << (32 - cidr) % NBBY)), 1);
- 	}
- 
- 	return 0;
-diff -urN dhcpcd-6.4.0.org/ipv6.c dhcpcd-6.4.0/ipv6.c
---- dhcpcd-6.4.0.org/ipv6.c	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv6.c	2014-07-05 21:47:22.000000000 +0200
-@@ -652,7 +652,6 @@
- 	i = 0;
- 	TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
- 		if (ap->prefix_vltime == 0) {
--			TAILQ_REMOVE(addrs, ap, next);
- 			if (ap->flags & IPV6_AF_ADDED) {
- 				syslog(LOG_INFO, "%s: deleting address %s",
- 				    ap->iface->name, ap->saddr);
-@@ -664,7 +663,12 @@
- 			}
- 			eloop_q_timeout_delete(ap->iface->ctx->eloop,
- 			    0, NULL, ap);
--			free(ap);
-+			if (ap->flags & IPV6_AF_REQUEST) {
-+				ap->flags &= ~IPV6_AF_ADDED;
-+			} else {
-+				TAILQ_REMOVE(addrs, ap, next);
-+				free(ap);
-+			}
- 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr)) {
- 			if (ap->flags & IPV6_AF_NEW)
- 				i++;
-diff -urN dhcpcd-6.4.0.org/ipv6.h dhcpcd-6.4.0/ipv6.h
---- dhcpcd-6.4.0.org/ipv6.h	2014-06-14 22:13:12.000000000 +0200
-+++ dhcpcd-6.4.0/ipv6.h	2014-07-05 21:47:22.000000000 +0200
-@@ -90,7 +90,10 @@
- 	short flags;
- 	char saddr[INET6_ADDRSTRLEN];
- 	uint8_t iaid[4];
-+	uint16_t ia_type;
- 	struct interface *delegating_iface;
-+	uint8_t prefix_exclude_len;
-+	struct in6_addr prefix_exclude;
- 
- 	void (*dadcallback)(void *);
- 	int dadcounter;
-@@ -109,7 +112,8 @@
- #define IPV6_AF_DADCOMPLETED	0x0040
- #define IPV6_AF_DELEGATED	0x0080
- #define IPV6_AF_DELEGATEDPFX	0x0100
--#define IPV6_AF_DELEGATEDZERO	0X0200
-+#define IPV6_AF_DELEGATEDZERO	0x0200
-+#define IPV6_AF_REQUEST		0x0400
- 
- struct rt6 {
- 	TAILQ_ENTRY(rt6) next;
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/dhcpcd.git/commitdiff/4269699a1aad65a58e2fce90ee2e17a9f9cda6cf



More information about the pld-cvs-commit mailing list