Module Name:    src
Committed By:   roy
Date:           Mon Jul 14 11:49:48 UTC 2014

Modified Files:
        src/external/bsd/dhcpcd/dist: dhcp.c dhcpcd.8.in dhcpcd.c
            dhcpcd.conf.5.in if-bsd.c if-options.c ipv6nd.c script.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcp.c
cvs rdiff -u -r1.28 -r1.29 src/external/bsd/dhcpcd/dist/dhcpcd.8.in
cvs rdiff -u -r1.5 -r1.6 src/external/bsd/dhcpcd/dist/dhcpcd.c
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \
    src/external/bsd/dhcpcd/dist/ipv6nd.c
cvs rdiff -u -r1.6 -r1.7 src/external/bsd/dhcpcd/dist/if-bsd.c \
    src/external/bsd/dhcpcd/dist/script.c
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/if-options.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/dhcpcd/dist/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.13 src/external/bsd/dhcpcd/dist/dhcp.c:1.14
--- src/external/bsd/dhcpcd/dist/dhcp.c:1.13	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/dhcp.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp.c,v 1.13 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: dhcp.c,v 1.14 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -128,16 +128,24 @@ static const size_t udp_dhcp_len = sizeo
 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);
 }
 
@@ -289,7 +297,7 @@ decode_rfc3442(char *out, size_t len, co
 			errno = EINVAL;
 			return -1;
 		}
-		ocets = (cidr + 7) / 8;
+		ocets = (cidr + 7) / NBBY;
 		if (!out) {
 			p += 4 + ocets;
 			bytes += ((4 * 4) * 2) + 4;
@@ -360,7 +368,7 @@ decode_rfc3442_rt(const uint8_t *data, s
 		}
 		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);
@@ -946,6 +954,30 @@ make_message(struct dhcp_message **messa
 				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);
 	}
 
@@ -2736,40 +2768,23 @@ dhcp_open(struct interface *ifp)
 }
 
 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";
@@ -3018,13 +3033,22 @@ dhcp_start(struct interface *ifp)
 	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);
 }
 

Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.28 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.29
--- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.28	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in	Mon Jul 14 11:49:48 2014
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.8.in,v 1.28 2014/06/14 20:55:37 roy Exp $
+.\"     $NetBSD: dhcpcd.8.in,v 1.29 2014/07/14 11:49:48 roy Exp $
 .\" Copyright (c) 2006-2014 Roy Marples
 .\" All rights reserved
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 2, 2014
+.Dd July 7, 2014
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -76,7 +76,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
@@ -104,17 +104,17 @@ to renew early.
 .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.
@@ -212,7 +212,7 @@ instead of the default
 .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.
@@ -260,7 +260,7 @@ are disable, none, ptr and both.
 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 .
@@ -553,6 +553,14 @@ Dumps the last lease for the
 to stdout.
 .Ar interface
 could also be a path to a DHCP wire formatted file.
+Use the
+.Fl 4
+or
+.Fl 6
+flags to specify an address family.
+Pass a 2nd
+.Fl U, Fl Fl dumplease option to dump a secondary lease, such as
+DHCPv6 Prefix Delegation when not being mixed with another IA type.
 .It Fl V, Fl Fl variables
 Display a list of option codes and the associated variable for use in
 .Xr dhcpcd-run-hooks 8 .
@@ -672,7 +680,8 @@ RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 213
 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 r...@marples.name
 .Sh BUGS

Index: src/external/bsd/dhcpcd/dist/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.5 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.6
--- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.5	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/dhcpcd.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd.c,v 1.5 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd.c,v 1.6 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -142,14 +142,14 @@ free_globals(struct dhcpcd_ctx *ctx)
 	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;
 	}
@@ -326,6 +326,9 @@ configure_interface1(struct interface *i
 {
 	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);
@@ -342,7 +345,7 @@ configure_interface1(struct interface *i
 		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)
@@ -434,17 +437,27 @@ configure_interface1(struct interface *i
 	}
 
 #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
@@ -496,10 +509,23 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 	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);
@@ -547,6 +573,8 @@ warn_iaid_conflict(struct interface *ifp
 	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
 		if (ifn == ifp)
 			continue;
+		if (ifn->options->options & DHCPCD_PFXDLGONLY)
+			continue;
 		if (memcmp(ifn->options->iaid, iaid,
 		    sizeof(ifn->options->iaid)) == 0)
 			break;
@@ -558,38 +586,39 @@ warn_iaid_conflict(struct interface *ifp
 	}
 
 	/* This is only a problem if the interfaces are on the same network. */
-	if (ifn)
+	if (ifn && strcmp(ifp->name, ifn->name))
 		syslog(LOG_ERR,
 		    "%s: IAID conflicts with one assigned to %s",
 		    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];
+
+	pre_start(ifp);
+	if (if_up(ifp) == -1)
+		syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
 
-	if (ifp->carrier == LINK_UNKNOWN)
-		dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
-	if (ifp->carrier == LINK_DOWN) {
+	if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) {
 		syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
 		return;
 	}
@@ -599,11 +628,17 @@ dhcpcd_startinterface(void *arg)
 		if (ifp->ctx->duid == NULL) {
 			if (duid_init(ifp) == 0)
 				return;
-			syslog(LOG_INFO, "DUID %s",
-			    hwaddr_ntoa(ifp->ctx->duid, ifp->ctx->duid_len,
-			    buf, sizeof(buf)));
+			if (!(ifo->options & DHCPCD_PFXDLGONLY))
+				syslog(LOG_INFO, "DUID %s",
+				    hwaddr_ntoa(ifp->ctx->duid,
+				    ifp->ctx->duid_len,
+				    buf, sizeof(buf)));
 		}
+	}
 
+	if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
+	    !(ifo->options & DHCPCD_PFXDLGONLY))
+	{
 		/* Report IAIDs */
 		syslog(LOG_INFO, "%s: IAID %s", ifp->name,
 		    hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
@@ -624,10 +659,12 @@ dhcpcd_startinterface(void *arg)
 
 	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)
@@ -654,6 +691,8 @@ dhcpcd_startinterface(void *arg)
 				    "%s: dhcp6_start: %m", ifp->name);
 		}
 	}
+	if (ifo->options & DHCPCD_PFXDLGONLY)
+		return;
 
 	if (ifo->options & DHCPCD_IPV4)
 		dhcp_start(ifp);
@@ -674,7 +713,7 @@ handle_link(void *arg)
 }
 
 static void
-init_state(struct interface *ifp, int argc, char **argv)
+dhcpcd_initstate1(struct interface *ifp, int argc, char **argv)
 {
 	struct if_options *ifo;
 
@@ -700,34 +739,27 @@ init_state(struct interface *ifp, int ar
 	}
 }
 
+void
+dhcpcd_initstate(struct interface *ifp)
+{
+
+	dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv);
+}
+
 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
@@ -735,7 +767,7 @@ dhcpcd_handleinterface(void *arg, int ac
 {
 	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;
 
@@ -746,6 +778,7 @@ dhcpcd_handleinterface(void *arg, int ac
 			errno = ESRCH;
 			return -1;
 		}
+		syslog(LOG_DEBUG, "%s: interface departed", ifp->name);
 		ifp->options->options |= DHCPCD_DEPARTED;
 		stop_interface(ifp);
 		return 0;
@@ -767,22 +800,24 @@ dhcpcd_handleinterface(void *arg, int ac
 			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);
+			dhcpcd_initstate(ifp);
 			run_preinit(ifp);
-			dhcpcd_startinterface(ifp);
+			iff = ifp;
 		}
+		if (action > 0)
+			dhcpcd_startinterface(iff);
 	}
 
 	/* Free our discovered list */
@@ -857,7 +892,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in
 			if_free(ifp);
 		} else {
 			TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
-			init_state(ifp, argc, argv);
+			dhcpcd_initstate1(ifp, argc, argv);
 			run_preinit(ifp);
 			dhcpcd_startinterface(ifp);
 		}
@@ -870,7 +905,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in
 static void
 stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release)
 {
-	struct interface *ifp;
+	struct interface *ifp, *ifpm;
 
 	/* drop_dhcp could change the order, so we do it like this. */
 	for (;;) {
@@ -878,6 +913,10 @@ stop_all_interfaces(struct dhcpcd_ctx *c
 		ifp = TAILQ_LAST(ctx->ifaces, if_head);
 		if (ifp == NULL)
 			break;
+		/* Stop the master interface only */
+		ifpm = if_find(ifp->ctx, ifp->name);
+		if (ifpm)
+			ifp = ifpm;
 		if (do_release) {
 			ifp->options->options |= DHCPCD_RELEASE;
 			ifp->options->options &= ~DHCPCD_PERSISTENT;
@@ -1250,10 +1289,13 @@ main(int argc, char **argv)
 			i = 1;
 			break;
 		case 'U':
-			i = 2;
+			if (i == 3)
+				i = 4;
+			else if (i != 4)
+				i = 3;
 			break;
 		case 'V':
-			i = 3;
+			i = 2;
 			break;
 		case '?':
 			usage();
@@ -1267,25 +1309,36 @@ main(int argc, char **argv)
 	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)
 			usage();
 		goto exit_failure;
 	}
-	if (i == 3) {
+	if (i == 2) {
 		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;
@@ -1296,6 +1349,8 @@ main(int argc, char **argv)
 			ctx.options |= DHCPCD_TEST;
 		else
 			ctx.options |= DHCPCD_DUMPLEASE;
+		if (i == 4)
+			ctx.options |= DHCPCD_PFXDLGONLY;
 		ctx.options |= DHCPCD_PERSISTENT;
 		ctx.options &= ~DHCPCD_DAEMONISE;
 	}
@@ -1344,8 +1399,7 @@ main(int argc, char **argv)
 			}
 			snprintf(pidfile, sizeof(pidfile),
 			    PIDFILE, "-", argv[optind], per);
-		}
-		else {
+		} else {
 			snprintf(pidfile, sizeof(pidfile), PIDFILE, "", "", "");
 			ctx.options |= DHCPCD_MASTER;
 		}
@@ -1354,12 +1408,48 @@ main(int argc, char **argv)
 	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 (ctx.options & DHCPCD_PFXDLGONLY)
+			ifp->options->options |= DHCPCD_PFXDLGONLY;
+		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;
 	}
@@ -1399,12 +1489,6 @@ main(int argc, char **argv)
 		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);
@@ -1556,7 +1640,7 @@ main(int argc, char **argv)
 	}
 
 	TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-		init_state(ifp, argc, argv);
+		dhcpcd_initstate1(ifp, argc, argv);
 	}
 
 	if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx))
@@ -1625,7 +1709,6 @@ exit1:
 
 	free_options(ifo);
 	free_globals(&ctx);
-	if_rarestore(&ctx);
 	ipv4_ctxfree(&ctx);
 	ipv6_ctxfree(&ctx);
 	dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED));

Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.8 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.9
--- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.8	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in	Mon Jul 14 11:49:48 2014
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.conf.5.in,v 1.8 2014/06/14 20:55:37 roy Exp $
+.\"     $NetBSD: dhcpcd.conf.5.in,v 1.9 2014/07/14 11:49:48 roy Exp $
 .\" Copyright (c) 2006-2014 Roy Marples
 .\" All rights reserved
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 6, 2014
+.Dd July 7, 2014
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -215,7 +215,7 @@ DNS if the domain part does not match th
 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
@@ -231,7 +231,7 @@ Request a DHCPv6 Temporary Address for
 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
@@ -251,7 +251,10 @@ Otherwise addresses are only assigned fo
 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
@@ -291,6 +294,18 @@ IPv6RS should be disabled globally when 
 .D1 interface eth1
 .D1 ipv4
 .D1 ipv6rs
+.It Ic ia_pd_mix
+To be RFC compliant,
+.Nm dhcpcd
+cannot mix Prefix Delegation with other DHCPv6 address types in the same
+session.
+This has a number of issues: additional DHCP traffic and potential collisions
+between options.
+.Ic ia_pd_mix
+enables
+.Li draft-ietf-dhc-dhcpv6-stateful-issues-06
+support so that Prefix Delegation can be mixed with other address types in
+the same session.
 .It Ic ipv4only
 Only configure IPv4.
 .It Ic ipv6only
@@ -458,6 +473,9 @@ Subsequent options are only parsed for t
 .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 .
@@ -740,11 +758,5 @@ Same as
 .Sh AUTHORS
 .An Roy Marples Aq Mt r...@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-disc...@marples.name
-mailing list.
-.Pp
 Please report them to
 .Lk http://roy.marples.name/projects/dhcpcd
Index: src/external/bsd/dhcpcd/dist/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.8 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.9
--- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.8	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/ipv6nd.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6nd.c,v 1.8 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: ipv6nd.c,v 1.9 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -282,7 +282,7 @@ ipv6nd_sendrsprobe(void *arg)
 	dst.sin6_len = sizeof(dst);
 #endif
 	dst.sin6_scope_id = ifp->index;
-	if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr.s6_addr) != 1) {
+	if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr) != 1) {
 		syslog(LOG_ERR, "%s: %m", __func__);
 		return;
 	}
@@ -627,8 +627,7 @@ ipv6nd_dadcallback(void *arg)
 			ap->dadcounter = dadcounter;
 			ap->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
 			ap->flags |= IPV6_AF_NEW;
-			p = inet_ntop(AF_INET6, ap->addr.s6_addr,
-			    buf, sizeof(buf));
+			p = inet_ntop(AF_INET6, &ap->addr, buf, sizeof(buf));
 			if (p)
 				snprintf(ap->saddr,
 				    sizeof(ap->saddr),
@@ -734,8 +733,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
 		if (ifp == rap->iface &&
-		    memcmp(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr,
-		    sizeof(rap->from.s6_addr)) == 0)
+		    IN6_ARE_ADDR_EQUAL(&rap->from, &ctx->from.sin6_addr))
 			break;
 	}
 
@@ -764,8 +762,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 			return;
 		}
 		rap->iface = ifp;
-		memcpy(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr,
-		    sizeof(rap->from.s6_addr));
+		rap->from = ctx->from.sin6_addr;
 		strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom));
 		TAILQ_INIT(&rap->addrs);
 		TAILQ_INIT(&rap->options);
@@ -852,9 +849,8 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 			}
 			TAILQ_FOREACH(ap, &rap->addrs, next)
 				if (ap->prefix_len ==pi->nd_opt_pi_prefix_len &&
-				    memcmp(ap->prefix.s6_addr,
-				    pi->nd_opt_pi_prefix.s6_addr,
-				    sizeof(ap->prefix.s6_addr)) == 0)
+				    IN6_ARE_ADDR_EQUAL(&ap->prefix,
+				    &pi->nd_opt_pi_prefix))
 					break;
 			if (ap == NULL) {
 				if (!(pi->nd_opt_pi_flags_reserved &
@@ -868,9 +864,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 				ap->iface = rap->iface;
 				ap->flags = IPV6_AF_NEW;
 				ap->prefix_len = pi->nd_opt_pi_prefix_len;
-				memcpy(ap->prefix.s6_addr,
-				   pi->nd_opt_pi_prefix.s6_addr,
-				   sizeof(ap->prefix.s6_addr));
+				ap->prefix = pi->nd_opt_pi_prefix;
 				if (pi->nd_opt_pi_flags_reserved &
 				    ND_OPT_PI_FLAG_AUTO)
 				{
@@ -884,7 +878,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 						break;
 					}
 					cbp = inet_ntop(AF_INET6,
-					    ap->addr.s6_addr,
+					    &ap->addr,
 					    buf, sizeof(buf));
 					if (cbp)
 						snprintf(ap->saddr,
@@ -947,7 +941,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 			op += sizeof(rdnss->nd_opt_rdnss_lifetime);
 			l = 0;
 			for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
-			    op += sizeof(addr.s6_addr))
+			    op += sizeof(addr))
 			{
 				r = ipv6_printaddr(NULL, 0, op, ifp->name);
 				if (r != -1)
@@ -961,7 +955,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, st
 			if (opt == NULL)
 				continue;
 			for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
-			    op += sizeof(addr.s6_addr))
+			    op += sizeof(addr))
 			{
 				r = ipv6_printaddr(tmp, l, op,
 				    ifp->name);
@@ -1401,8 +1395,7 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, st
 
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
 		if (rap->iface == ifp &&
-		    memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr,
-		    sizeof(rap->from.s6_addr)) == 0)
+		    IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na->nd_na_target))
 			break;
 	}
 	if (rap == NULL) {

Index: src/external/bsd/dhcpcd/dist/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.6 src/external/bsd/dhcpcd/dist/if-bsd.c:1.7
--- src/external/bsd/dhcpcd/dist/if-bsd.c:1.6	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/if-bsd.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-bsd.c,v 1.6 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: if-bsd.c,v 1.7 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -891,9 +891,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
 			case AF_INET6:
 				sin6 = (struct sockaddr_in6*)(void *)
 				    rti_info[RTAX_IFA];
-				memcpy(ia6.s6_addr,
-				    sin6->sin6_addr.s6_addr,
-				    sizeof(ia6.s6_addr));
+				ia6 = sin6->sin6_addr;
 				if (rtm->rtm_type == RTM_NEWADDR) {
 					ifa_flags = if_addrflags6(ifname, &ia6);
 					if (ifa_flags == -1)
@@ -1022,45 +1020,6 @@ if_nd6reachable(const char *ifname, stru
 	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)
 {
@@ -1088,10 +1047,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con
 #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) {
@@ -1169,7 +1124,7 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con
 				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)
 			{
@@ -1180,25 +1135,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con
 				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;
@@ -1220,7 +1156,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, con
 			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
Index: src/external/bsd/dhcpcd/dist/script.c
diff -u src/external/bsd/dhcpcd/dist/script.c:1.6 src/external/bsd/dhcpcd/dist/script.c:1.7
--- src/external/bsd/dhcpcd/dist/script.c:1.6	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/script.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: script.c,v 1.6 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: script.c,v 1.7 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -315,7 +315,8 @@ make_env(const struct interface *ifp, co
 	snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
 	l = e = strlen("interface_order=");
 	TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
-		e += strlen(ifp2->name) + 1;
+		if (!(ifp2->options->options & DHCPCD_PFXDLGONLY))
+			e += strlen(ifp2->name) + 1;
 	}
 	EMALLOC(8, e);
 	p = env[8];
@@ -323,11 +324,13 @@ make_env(const struct interface *ifp, co
 	e -= l;
 	p += l;
 	TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
-		l = strlcpy(p, ifp2->name, e);
-		p += l;
-		e -= l;
-		*p++ = ' ';
-		e--;
+		if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) {
+			l = strlcpy(p, ifp2->name, e);
+			p += l;
+			e -= l;
+			*p++ = ' ';
+			e--;
+		}
 	}
 	*--p = '\0';
 	if (strcmp(reason, "TEST") == 0) {
@@ -396,6 +399,16 @@ make_env(const struct interface *ifp, co
 	}
 #endif
 #ifdef INET6
+	if (dhcp6 && d6_state && ifo->options & DHCPCD_PFXDLGONLY) {
+		nenv = realloc(env, sizeof(char *) * (elen + 2));
+		if (nenv == NULL)
+			goto eexit;
+		env = nenv;
+		env[elen] = strdup("ifclass=pd");
+		if (env[elen] == NULL)
+			goto eexit;
+		elen++;
+	}
 	if (dhcp6 && d6_state && d6_state->old) {
 		n = dhcp6_env(NULL, NULL, ifp,
 		    d6_state->old, d6_state->old_len);

Index: src/external/bsd/dhcpcd/dist/if-options.c
diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.9 src/external/bsd/dhcpcd/dist/if-options.c:1.10
--- src/external/bsd/dhcpcd/dist/if-options.c:1.9	Sat Jun 14 20:55:37 2014
+++ src/external/bsd/dhcpcd/dist/if-options.c	Mon Jul 14 11:49:48 2014
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-options.c,v 1.9 2014/06/14 20:55:37 roy Exp $");
+ __RCSID("$NetBSD: if-options.c,v 1.10 2014/07/14 11:49:48 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -96,6 +96,7 @@
 #define O_CONTROLGRP		O_BASE + 34
 #define O_SLAAC			O_BASE + 35
 #define O_GATEWAY		O_BASE + 36
+#define O_PFXDLGMIX		O_BASE + 37
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -182,6 +183,7 @@ const struct option cf_options[] = {
 	{"controlgroup",    required_argument, NULL, O_CONTROLGRP},
 	{"slaac",           required_argument, NULL, O_SLAAC},
 	{"gateway",         no_argument,       NULL, O_GATEWAY},
+	{"ia_pd_mix",       no_argument,       NULL, O_PFXDLGMIX},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -521,7 +523,9 @@ parse_addr(__unused struct in_addr *addr
 
 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[])
 {
@@ -530,6 +534,8 @@ set_option_space(struct dhcpcd_ctx *ctx,
 	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;
@@ -540,9 +546,13 @@ set_option_space(struct dhcpcd_ctx *ctx,
 #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;
@@ -633,15 +643,14 @@ parse_option(struct dhcpcd_ctx *ctx, con
 	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;
 #ifdef _REENTRANT
-#error foo
 	struct group grpbuf;
 #endif
 #ifdef INET6
@@ -736,10 +745,10 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		}
 		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;
@@ -955,22 +964,22 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		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;
@@ -1159,8 +1168,11 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		}
 		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);
@@ -1223,35 +1235,41 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			}
 			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_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));
@@ -1261,14 +1279,47 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			}
 			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);
@@ -1287,12 +1338,6 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			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))
 			{
@@ -1856,6 +1901,9 @@ err_sla:
 		else
 			ifo->options &= ~DHCPCD_SLAACPRIVATE;
 		break;
+	case O_PFXDLGMIX:
+		ifo->options |= DHCPCD_PFXDLGMIX;
+		break;
 	default:
 		return 0;
 	}
@@ -2127,6 +2175,10 @@ read_config(struct dhcpcd_ctx *ctx,
 				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);

Reply via email to