Module Name:    src
Committed By:   roy
Date:           Sat May  2 15:18:37 UTC 2015

Modified Files:
        src/external/bsd/dhcpcd/dist: arp.c arp.h common.c defs.h dhcp.c dhcp.h
            dhcp6.c dhcp6.h dhcpcd.c dhcpcd.conf.5.in eloop.c if-bsd.c
            if-options.c if-options.h if.c if.h ipv4.c ipv4.h ipv4ll.c ipv6.c
            ipv6.h ipv6nd.c ipv6nd.h script.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/arp.c \
    src/external/bsd/dhcpcd/dist/common.c \
    src/external/bsd/dhcpcd/dist/dhcp6.c src/external/bsd/dhcpcd/dist/ipv6.h
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/arp.h \
    src/external/bsd/dhcpcd/dist/dhcp.h src/external/bsd/dhcpcd/dist/dhcp6.h
cvs rdiff -u -r1.16 -r1.17 src/external/bsd/dhcpcd/dist/defs.h
cvs rdiff -u -r1.29 -r1.30 src/external/bsd/dhcpcd/dist/dhcp.c
cvs rdiff -u -r1.23 -r1.24 src/external/bsd/dhcpcd/dist/dhcpcd.c
cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \
    src/external/bsd/dhcpcd/dist/if-bsd.c
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/eloop.c \
    src/external/bsd/dhcpcd/dist/if-options.h \
    src/external/bsd/dhcpcd/dist/if.h src/external/bsd/dhcpcd/dist/ipv4.h \
    src/external/bsd/dhcpcd/dist/ipv4ll.c
cvs rdiff -u -r1.22 -r1.23 src/external/bsd/dhcpcd/dist/if-options.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.c
cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/if.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/ipv4.c
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/ipv6.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.h
cvs rdiff -u -r1.18 -r1.19 src/external/bsd/dhcpcd/dist/script.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/arp.c
diff -u src/external/bsd/dhcpcd/dist/arp.c:1.11 src/external/bsd/dhcpcd/dist/arp.c:1.12
--- src/external/bsd/dhcpcd/dist/arp.c:1.11	Fri Mar 27 18:53:15 2015
+++ src/external/bsd/dhcpcd/dist/arp.c	Sat May  2 15:18:36 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: arp.c,v 1.11 2015/03/27 18:53:15 christos Exp $");
+ __RCSID("$NetBSD: arp.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -44,6 +44,7 @@
 #define ELOOP_QUEUE 5
 #include "config.h"
 #include "arp.h"
+#include "if.h"
 #include "ipv4.h"
 #include "common.h"
 #include "dhcp.h"
@@ -57,7 +58,7 @@
 	(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
 
 static ssize_t
-arp_send(const struct interface *ifp, int op, in_addr_t sip, in_addr_t tip)
+arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
 {
 	uint8_t arp_buffer[ARP_LEN];
 	struct arphdr ar;
@@ -68,7 +69,7 @@ arp_send(const struct interface *ifp, in
 	ar.ar_pro = htons(ETHERTYPE_IP);
 	ar.ar_hln = ifp->hwlen;
 	ar.ar_pln = sizeof(sip);
-	ar.ar_op = htons((uint16_t)op);
+	ar.ar_op = htons(ARPOP_REQUEST);
 
 	p = arp_buffer;
 	len = 0;
@@ -99,12 +100,20 @@ eexit:
 void
 arp_report_conflicted(const struct arp_state *astate, const struct arp_msg *amsg)
 {
-	char buf[HWADDR_LEN * 3];
 
-	logger(astate->iface->ctx, LOG_ERR, "%s: hardware address %s claims %s",
-	    astate->iface->name,
-	    hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf)),
-	    inet_ntoa(astate->failed));
+	if (amsg) {
+		char buf[HWADDR_LEN * 3];
+
+		logger(astate->iface->ctx, LOG_ERR,
+		    "%s: hardware address %s claims %s",
+		    astate->iface->name,
+		    hwaddr_ntoa(amsg->sha, astate->iface->hwlen,
+		    buf, sizeof(buf)),
+		    inet_ntoa(astate->failed));
+	} else
+		logger(astate->iface->ctx, LOG_ERR,
+		    "%s: DAD detected %s",
+		    astate->iface->name, inet_ntoa(astate->failed));
 }
 
 static void
@@ -226,8 +235,7 @@ arp_announce1(void *arg)
 		    "%s: ARP announcing %s (%d of %d)",
 		    ifp->name, inet_ntoa(astate->addr),
 		    astate->claims, ANNOUNCE_NUM);
-	if (arp_send(ifp, ARPOP_REQUEST,
-		astate->addr.s_addr, astate->addr.s_addr) == -1)
+	if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr) == -1)
 		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
 	eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
 	    astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
@@ -274,7 +282,7 @@ arp_probe1(void *arg)
 	    ifp->name, inet_ntoa(astate->addr),
 	    astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
 	    timespec_to_double(&tv));
-	if (arp_send(ifp, ARPOP_REQUEST, 0, astate->addr.s_addr) == -1)
+	if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
 		logger(ifp->ctx, LOG_ERR, "send_arp: %m");
 }
 
@@ -289,19 +297,38 @@ arp_probe(struct arp_state *astate)
 	arp_probe1(astate);
 }
 
+static struct arp_state *
+arp_find(struct interface *ifp, const struct in_addr *addr)
+{
+	struct arp_state *astate;
+	struct dhcp_state *state;
+
+	state = D_STATE(ifp);
+	TAILQ_FOREACH(astate, &state->arp_states, next) {
+		if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
+			return astate;
+	}
+	errno = ESRCH;
+	return NULL;
+}
+
 struct arp_state *
-arp_new(struct interface *ifp) {
+arp_new(struct interface *ifp, const struct in_addr *addr)
+{
 	struct arp_state *astate;
 	struct dhcp_state *state;
 
-	astate = calloc(1, sizeof(*astate));
-	if (astate == NULL) {
+	if (addr && (astate = arp_find(ifp, addr)))
+		return astate;
+
+	if ((astate = calloc(1, sizeof(*astate))) == NULL) {
 		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
 		return NULL;
 	}
-
-	astate->iface = ifp;
 	state = D_STATE(ifp);
+	astate->iface = ifp;
+	if (addr)
+		astate->addr = *addr;
 	TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
 	return astate;
 }
@@ -366,3 +393,33 @@ arp_close(struct interface *ifp)
 #endif
 	}
 }
+
+void
+arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
+    int flags)
+{
+#ifdef IN_IFF_DUPLICATED
+	struct dhcp_state *state = D_STATE(ifp);
+	struct arp_state *astate, *asn;
+
+	if (cmd != RTM_NEWADDR || (state = D_STATE(ifp)) == NULL)
+		return;
+
+	TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
+		if (astate->addr.s_addr == addr->s_addr) {
+			if (flags & IN_IFF_DUPLICATED) {
+				if (astate->conflicted_cb)
+					astate->conflicted_cb(astate, NULL);
+			} else if (!(flags & IN_IFF_NOTUSEABLE)) {
+				if (astate->probed_cb)
+					astate->probed_cb(astate);
+			}
+		}
+	}
+#else
+	UNUSED(cmd);
+	UNUSED(ifp);
+	UNUSED(addr);
+	UNUSED(flags);
+#endif
+}
Index: src/external/bsd/dhcpcd/dist/common.c
diff -u src/external/bsd/dhcpcd/dist/common.c:1.11 src/external/bsd/dhcpcd/dist/common.c:1.12
--- src/external/bsd/dhcpcd/dist/common.c:1.11	Tue Mar 31 18:01:09 2015
+++ src/external/bsd/dhcpcd/dist/common.c	Sat May  2 15:18:36 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: common.c,v 1.11 2015/03/31 18:01:09 christos Exp $");
+ __RCSID("$NetBSD: common.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -28,11 +28,6 @@
  * SUCH DAMAGE.
  */
 
-/* Needed define to get at getline for glibc and FreeBSD */
-#ifndef _GNU_SOURCE
-#  define _GNU_SOURCE
-#endif
-
 #ifdef __APPLE__
 #  include <mach/mach_time.h>
 #  include <mach/kern_return.h>
@@ -196,8 +191,8 @@ logger(struct dhcpcd_ctx *ctx, int pri, 
 		return;
 
 	serrno = errno;
-
 	va_start(va, fmt);
+
 #ifndef HAVE_PRINTF_M
 	/* Print strerrno(errno) in place of %m */
 	if (ctx == NULL || !(ctx->options & DHCPCD_QUIET) || ctx->log_fd != -1)
Index: src/external/bsd/dhcpcd/dist/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.11 src/external/bsd/dhcpcd/dist/dhcp6.c:1.12
--- src/external/bsd/dhcpcd/dist/dhcp6.c:1.11	Sat Mar 28 14:16:52 2015
+++ src/external/bsd/dhcpcd/dist/dhcp6.c	Sat May  2 15:18:36 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp6.c,v 1.11 2015/03/28 14:16:52 christos Exp $");
+ __RCSID("$NetBSD: dhcp6.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -219,7 +219,7 @@ dhcp6_makevendor(struct dhcp6_option *o,
 }
 
 static const struct dhcp6_option *
-dhcp6_findoption(unsigned int code, const uint8_t *d, size_t len)
+dhcp6_findoption(uint16_t code, const uint8_t *d, size_t len)
 {
 	const struct dhcp6_option *o;
 	size_t ol;
@@ -283,7 +283,7 @@ dhcp6_getoption(struct dhcpcd_ctx *ctx,
 }
 
 static const struct dhcp6_option *
-dhcp6_getmoption(unsigned int code, const struct dhcp6_message *m, size_t len)
+dhcp6_getmoption(uint16_t code, const struct dhcp6_message *m, size_t len)
 {
 
 	if (len < sizeof(*m)) {
@@ -490,6 +490,21 @@ dhcp6_delegateaddr(struct in6_addr *addr
 	return sla->prefix_len;
 }
 
+int
+dhcp6_has_public_addr(const struct interface *ifp)
+{
+	const struct dhcp6_state *state = D6_CSTATE(ifp);
+	const struct ipv6_addr *ia;
+
+	if (state == NULL)
+		return 0;
+	TAILQ_FOREACH(ia, &state->addrs, next) {
+		if (ipv6_publicaddr(ia))
+			return 1;
+	}
+	return 0;
+}
+
 static int
 dhcp6_makemessage(struct interface *ifp)
 {
@@ -497,9 +512,9 @@ dhcp6_makemessage(struct interface *ifp)
 	struct dhcp6_message *m;
 	struct dhcp6_option *o, *so, *eo;
 	const struct dhcp6_option *si, *unicast;
-	size_t l, n, len, ml, auth_len;
+	size_t l, n, len, ml;
 	uint8_t u8, type;
-	uint16_t u16, n_options;
+	uint16_t u16, n_options, auth_len;
 	struct if_options *ifo;
 	const struct dhcp_opt *opt, *opt2;
 	uint8_t IA, *p;
@@ -704,17 +719,22 @@ dhcp6_makemessage(struct interface *ifp)
 		return -1;
 	}
 
+	auth_len = 0;
 	if (ifo->auth.options & DHCPCD_AUTH_SEND) {
-		auth_len = (size_t)dhcp_auth_encode(&ifo->auth,
+		ssize_t alen = dhcp_auth_encode(&ifo->auth,
 		    state->auth.token, NULL, 0, 6, type, NULL, 0);
-		if ((ssize_t)auth_len == -1) {
+		if (alen != -1 && alen > UINT16_MAX) {
+			errno = ERANGE;
+			alen = -1;
+		}
+		if (alen == -1)
 			logger(ifp->ctx, LOG_ERR,
 			    "%s: dhcp_auth_encode: %m", ifp->name);
-			auth_len = 0;
-		} else if (auth_len != 0)
+		else if (alen != 0) {
+			auth_len = (uint16_t)alen;
 			len += sizeof(*o) + auth_len;
-	} else
-		auth_len = 0; /* appease GCC */
+		}
+	}
 
 	state->send = malloc(len);
 	if (state->send == NULL)
@@ -816,9 +836,9 @@ dhcp6_makemessage(struct interface *ifp)
 					eo->len = htons(eo->len);
 				}
 
-				u32 = (uint32_t)(ntohs(o->len) + sizeof(*so)
+				u16 = (uint16_t)(ntohs(o->len) + sizeof(*so)
 				    + ntohs(so->len));
-				o->len = htons((uint16_t)u32);
+				o->len = htons(u16);
 			} else {
 				so->code = htons(D6_OPTION_IA_ADDR);
 				so->len = sizeof(ap->addr) +
@@ -1134,7 +1154,7 @@ logsend:
 	cm->cmsg_type = IPV6_PKTINFO;
 	cm->cmsg_len = CMSG_LEN(sizeof(pi));
 	memset(&pi, 0, sizeof(pi));
-	pi.ipi6_ifindex = CAST_IPI6_IFINDEX(ifp->index);
+	pi.ipi6_ifindex = ifp->index;
 	memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
 
 	if (sendmsg(ctx->dhcp_fd, &ctx->sndhdr, 0) == -1) {
@@ -1241,9 +1261,6 @@ dhcp6_dadcompleted(const struct interfac
 	const struct ipv6_addr *ap;
 
 	state = D6_CSTATE(ifp);
-	if (!TAILQ_FIRST(&state->addrs))
-		return 0;
-
 	TAILQ_FOREACH(ap, &state->addrs, next) {
 		if (ap->flags & IPV6_AF_ADDED &&
 		    !(ap->flags & IPV6_AF_DADCOMPLETED))
@@ -2126,7 +2143,7 @@ dhcp6_writelease(const struct interface 
 }
 
 static int
-dhcp6_readlease(struct interface *ifp)
+dhcp6_readlease(struct interface *ifp, int validate)
 {
 	struct dhcp6_state *state;
 	struct stat st;
@@ -2135,43 +2152,37 @@ dhcp6_readlease(struct interface *ifp)
 	const struct dhcp6_option *o;
 	struct timespec acquired;
 	time_t now;
+	int retval;
 
 	state = D6_STATE(ifp);
-	if (stat(state->leasefile, &st) == -1) {
-		if (errno == ENOENT)
-			return 0;
-		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
+	if (stat(state->leasefile, &st) == -1)
 		return -1;
-	}
 	logger(ifp->ctx, LOG_DEBUG, "%s: reading lease `%s'",
 	    ifp->name, state->leasefile);
 	if (st.st_size > UINT32_MAX) {
-		logger(ifp->ctx, LOG_ERR, "%s: file too big", ifp->name);
+		errno = E2BIG;
 		return -1;
 	}
-	state->new = malloc((size_t)st.st_size);
-	if (state->new == NULL) {
-		logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+	if ((fd = open(state->leasefile, O_RDONLY)) == -1)
 		return -1;
-	}
-	state->new_len = (size_t)st.st_size;
-	fd = open(state->leasefile, O_RDONLY);
-	if (fd == -1) {
-		logger(ifp->ctx, LOG_ERR, "%s: %s: %s: %m",
-		    ifp->name, __func__, state->leasefile);
+	if ((state->new = malloc((size_t)st.st_size)) == NULL)
 		return -1;
-	}
+	retval = -1;
+	state->new_len = (size_t)st.st_size;
 	bytes = read(fd, state->new, state->new_len);
 	close(fd);
-	if (bytes != (ssize_t)state->new_len) {
-		logger(ifp->ctx, LOG_ERR, "%s: read: %m", __func__);
+	if (bytes != (ssize_t)state->new_len)
 		goto ex;
+
+	/* If not validating IA's and if they have expired,
+	 * skip to the auth check. */
+	if (!validate) {
+		fd = 0;
+		goto auth;
 	}
 
-	if ((now = time(NULL)) == -1) {
-		logger(ifp->ctx, LOG_ERR, "%s: time: %m", __func__);
+	if ((now = time(NULL)) == -1)
 		goto ex;
-	}
 
 	get_monotonic(&acquired);
 	acquired.tv_sec -= now - st.st_mtime;
@@ -2189,10 +2200,14 @@ dhcp6_readlease(struct interface *ifp)
 			logger(ifp->ctx,
 			    LOG_DEBUG,"%s: discarding expired lease",
 			    ifp->name);
+			retval = 0;
 			goto ex;
 		}
 	}
 
+auth:
+
+	retval = 0;
 	/* Authenticate the message */
 	o = dhcp6_getmoption(D6_OPTION_AUTH, state->new, state->new_len);
 	if (o) {
@@ -2228,10 +2243,9 @@ ex:
 	state->new_len = 0;
 	if (!(ifp->ctx->options & DHCPCD_DUMPLEASE))
 		unlink(state->leasefile);
-	return 0;
+	return retval;
 }
 
-
 static void
 dhcp6_startinit(struct interface *ifp)
 {
@@ -2261,11 +2275,13 @@ dhcp6_startinit(struct interface *ifp)
 	    !(has_ta && !has_non_ta) &&
 	    ifp->options->reboot != 0)
 	{
-		r = dhcp6_readlease(ifp);
-		if (r == -1)
-			logger(ifp->ctx, LOG_ERR, "%s: dhcp6_readlease: %s: %m",
-			    ifp->name, state->leasefile);
-		else if (r != 0) {
+		r = dhcp6_readlease(ifp, 1);
+		if (r == -1) {
+			if (errno != ENOENT)
+				logger(ifp->ctx, LOG_ERR,
+				    "%s: dhcp6_readlease: %s: %m",
+				    ifp->name, state->leasefile);
+		} else if (r != 0) {
 			/* RFC 3633 section 12.1 */
 			if (dhcp6_hasprefixdelegation(ifp))
 				dhcp6_startrebind(ifp);
@@ -2355,9 +2371,6 @@ dhcp6_script_try_run(struct interface *i
 	int completed;
 
 	state = D6_STATE(ifp);
-	if (!TAILQ_FIRST(&state->addrs))
-		return;
-
 	completed = 1;
 	/* If all addresses have completed DAD run the script */
 	TAILQ_FOREACH(ap, &state->addrs, next) {
@@ -2409,7 +2422,7 @@ dhcp6_delegate_prefix(struct interface *
 				if (strcmp(sla->ifname, ia->sla[j].ifname) == 0)
 					break;
 			if (j >= i &&
-			    if_find(ifp->ctx, sla->ifname) == NULL)
+			    if_find(ifp->ctx->ifaces, sla->ifname) == NULL)
 			{
 				logger(ifp->ctx, LOG_INFO,
 				    "%s: loading for delegation", sla->ifname);
@@ -2717,7 +2730,7 @@ dhcp6_handledata(void *arg)
 	    i++, opt++)
 	{
 		if (has_option_mask(ifo->requiremask6, opt->option) &&
-		    dhcp6_getmoption(opt->option, r, len) == NULL)
+		    dhcp6_getmoption((uint16_t)opt->option, r, len) == NULL)
 		{
 			logger(ifp->ctx, LOG_WARNING,
 			    "%s: reject DHCPv6 (no option %s) from %s",
@@ -2725,7 +2738,7 @@ dhcp6_handledata(void *arg)
 			return;
 		}
 		if (has_option_mask(ifo->rejectmask6, opt->option) &&
-		    dhcp6_getmoption(opt->option, r, len))
+		    dhcp6_getmoption((uint16_t)opt->option, r, len))
 		{
 			logger(ifp->ctx, LOG_WARNING,
 			    "%s: reject DHCPv6 (option %s) from %s",
@@ -2767,6 +2780,8 @@ dhcp6_handledata(void *arg)
 	case DHCP6_REPLY:
 		switch(state->state) {
 		case DH6S_INFORM:
+			if (dhcp6_checkstatusok(ifp, r, NULL, len) == -1)
+				return;
 			/* RFC4242 */
 			o = dhcp6_getmoption(D6_OPTION_INFO_REFRESH_TIME,
 			    r, len);
@@ -3027,6 +3042,7 @@ recv:
 			eloop_timeout_add_sec(ifp->ctx->eloop,
 			    (time_t)state->expire, dhcp6_startexpire, ifp);
 
+		ipv6nd_runignoredra(ifp);
 		ipv6_addaddrs(&state->addrs);
 		dhcp6_delegate_prefix(ifp);
 
@@ -3567,7 +3583,6 @@ 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) {
@@ -3578,14 +3593,9 @@ dhcp6_dump(struct interface *ifp)
 	dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
 	    AF_INET6, ifp,
 	    ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
-	r = dhcp6_readlease(ifp);
-	if (r == -1) {
-		if (errno == ENOENT)
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: no lease to dump", ifp->name);
-		else
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: dhcp6_readlease: %m", ifp->name);
+	if (dhcp6_readlease(ifp, 0) == -1) {
+		logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
+		    *ifp->name ? ifp->name : state->leasefile, __func__);
 		return -1;
 	}
 	state->reason = "DUMP6";
Index: src/external/bsd/dhcpcd/dist/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.11 src/external/bsd/dhcpcd/dist/ipv6.h:1.12
--- src/external/bsd/dhcpcd/dist/ipv6.h:1.11	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6.h	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6.h,v 1.11 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: ipv6.h,v 1.12 2015/05/02 15:18:37 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -31,14 +31,8 @@
 #define IPV6_H
 
 #include <sys/uio.h>
-
 #include <netinet/in.h>
 
-#if defined(__linux__) && defined(__GLIBC__)
-#  define _LINUX_IN6_H
-#  include <linux/ipv6.h>
-#endif
-
 #include "config.h"
 #include "dhcpcd.h"
 
@@ -198,13 +192,6 @@ struct ipv6_state {
 			CMSG_SPACE(sizeof(int)))
 
 
-/* ipi6.ifiindex differes between OS's so have a cast function */
-#ifdef __linux__
-#define CAST_IPI6_IFINDEX(idx) (int)(idx)
-#else
-#define CAST_IPI6_IFINDEX(idx) (idx)
-#endif
-
 #ifdef INET6
 struct ipv6_ctx {
 	struct sockaddr_in6 from;
@@ -248,6 +235,7 @@ void ipv6_handleifa(struct dhcpcd_ctx *c
     const char *, const struct in6_addr *, uint8_t, int);
 int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
     const struct in6_addr *, int);
+int ipv6_publicaddr(const struct ipv6_addr *);
 const struct ipv6_addr *ipv6_iffindaddr(const struct interface *,
     const struct in6_addr *);
 struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,

Index: src/external/bsd/dhcpcd/dist/arp.h
diff -u src/external/bsd/dhcpcd/dist/arp.h:1.8 src/external/bsd/dhcpcd/dist/arp.h:1.9
--- src/external/bsd/dhcpcd/dist/arp.h:1.8	Fri Jan 30 09:47:05 2015
+++ src/external/bsd/dhcpcd/dist/arp.h	Sat May  2 15:18:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: arp.h,v 1.8 2015/01/30 09:47:05 roy Exp $ */
+/* $NetBSD: arp.h,v 1.9 2015/05/02 15:18:36 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -71,11 +71,13 @@ TAILQ_HEAD(arp_statehead, arp_state);
 void arp_report_conflicted(const struct arp_state *, const struct arp_msg *);
 void arp_announce(struct arp_state *);
 void arp_probe(struct arp_state *);
-struct arp_state *arp_new(struct interface *);
+struct arp_state *arp_new(struct interface *, const struct in_addr *);
 void arp_cancel(struct arp_state *);
 void arp_free(struct arp_state *);
 void arp_free_but(struct arp_state *);
 void arp_close(struct interface *);
+
+void arp_handleifa(int, struct interface *, const struct in_addr *, int);
 #else
 #define arp_close(a) {}
 #endif
Index: src/external/bsd/dhcpcd/dist/dhcp.h
diff -u src/external/bsd/dhcpcd/dist/dhcp.h:1.8 src/external/bsd/dhcpcd/dist/dhcp.h:1.9
--- src/external/bsd/dhcpcd/dist/dhcp.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcp.h	Sat May  2 15:18:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: dhcp.h,v 1.9 2015/05/02 15:18:36 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -259,8 +259,8 @@ void dhcp_printoptions(const struct dhcp
     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) &&						\
-	    !IN_LINKLOCAL(htonl((m)->yiaddr)) &&			\
+#define IS_BOOTP(i, m) ((m) &&						    \
+	    !IN_LINKLOCAL(htonl((m)->yiaddr)) &&			    \
 	    get_option_uint8((i)->ctx, NULL, (m), DHO_MESSAGETYPE) == -1)
 struct rt_head *get_option_routes(struct interface *,
     const struct dhcp_message *);
@@ -276,15 +276,14 @@ ssize_t make_message(struct dhcp_message
 int valid_dhcp_packet(unsigned char *);
 
 void dhcp_handleifa(int, struct interface *,
-    const struct in_addr *, const struct in_addr *, const struct in_addr *);
+    const struct in_addr *, const struct in_addr *, const struct in_addr *,
+    int);
 
 void dhcp_drop(struct interface *, const char *);
 void dhcp_start(struct interface *);
 void dhcp_stop(struct interface *);
-void dhcp_decline(struct interface *);
 void dhcp_discover(void *);
 void dhcp_inform(struct interface *);
-void dhcp_probe(struct interface *);
 void dhcp_bind(struct interface *, struct arp_state *);
 void dhcp_reboot_newopts(struct interface *, unsigned long long);
 void dhcp_close(struct interface *);
Index: src/external/bsd/dhcpcd/dist/dhcp6.h
diff -u src/external/bsd/dhcpcd/dist/dhcp6.h:1.8 src/external/bsd/dhcpcd/dist/dhcp6.h:1.9
--- src/external/bsd/dhcpcd/dist/dhcp6.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcp6.h	Sat May  2 15:18:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp6.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: dhcp6.h,v 1.9 2015/05/02 15:18:36 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -237,6 +237,7 @@ void dhcp6_printoptions(const struct dhc
 struct ipv6_addr *dhcp6_findaddr(struct dhcpcd_ctx *, const struct in6_addr *,
     short);
 size_t dhcp6_find_delegates(struct interface *);
+int dhcp6_has_public_addr(const struct interface *);
 int dhcp6_start(struct interface *, enum DH6S);
 void dhcp6_reboot(struct interface *);
 ssize_t dhcp6_env(char **, const char *, const struct interface *,

Index: src/external/bsd/dhcpcd/dist/defs.h
diff -u src/external/bsd/dhcpcd/dist/defs.h:1.16 src/external/bsd/dhcpcd/dist/defs.h:1.17
--- src/external/bsd/dhcpcd/dist/defs.h:1.16	Fri Mar 27 11:33:46 2015
+++ src/external/bsd/dhcpcd/dist/defs.h	Sat May  2 15:18:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: defs.h,v 1.16 2015/03/27 11:33:46 roy Exp $ */
+/* $NetBSD: defs.h,v 1.17 2015/05/02 15:18:36 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,7 +30,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"6.8.1"
+#define VERSION			"6.8.2"
 
 #ifndef CONFIG
 # define CONFIG			SYSCONFDIR "/" PACKAGE ".conf"

Index: src/external/bsd/dhcpcd/dist/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.29 src/external/bsd/dhcpcd/dist/dhcp.c:1.30
--- src/external/bsd/dhcpcd/dist/dhcp.c:1.29	Sat Mar 28 14:16:52 2015
+++ src/external/bsd/dhcpcd/dist/dhcp.c	Sat May  2 15:18:36 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp.c,v 1.29 2015/03/28 14:16:52 christos Exp $");
+ __RCSID("$NetBSD: dhcp.c,v 1.30 2015/05/02 15:18:36 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -163,6 +163,12 @@ get_option(struct dhcpcd_ctx *ctx,
 	const uint8_t *op = NULL;
 	size_t bl = 0;
 
+	/* Check we have the magic cookie */
+	if (dhcp->cookie != htonl(MAGIC_COOKIE)) {
+		errno = ENOTSUP;
+		return NULL;
+	}
+
 	while (p < e) {
 		o = *p++;
 		if (o == opt) {
@@ -621,11 +627,11 @@ get_option_routes(struct interface *ifp,
 		p = get_option(ifp->ctx, dhcp, DHO_STATICROUTE, &len);
 	else
 		p = NULL;
-	if (p) {
+	/* RFC 2131 Section 5.8 states length MUST be in multiples of 8 */
+	if (p && len % 8 == 0) {
 		e = p + len;
 		while (p < e) {
-			route = calloc(1, sizeof(*route));
-			if (route == NULL) {
+			if ((route = calloc(1, sizeof(*route))) == NULL) {
 				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
 				ipv4_freeroutes(routes);
 				return NULL;
@@ -634,6 +640,13 @@ get_option_routes(struct interface *ifp,
 			p += 4;
 			memcpy(&route->gate.s_addr, p, 4);
 			p += 4;
+			/* RFC 2131 Section 5.8 states default route is
+			 * illegal */
+			if (route->dest.s_addr == htonl(INADDR_ANY)) {
+				errno = EINVAL;
+				free(route);
+				continue;
+			}
 			route->net.s_addr = route_netmask(route->dest.s_addr);
 			TAILQ_INSERT_TAIL(routes, route, next);
 		}
@@ -647,8 +660,7 @@ get_option_routes(struct interface *ifp,
 	if (p) {
 		e = p + len;
 		while (p < e) {
-			route = calloc(1, sizeof(*route));
-			if (route == NULL) {
+			if ((route = calloc(1, sizeof(*route))) == NULL) {
 				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
 				ipv4_freeroutes(routes);
 				return NULL;
@@ -701,10 +713,10 @@ make_message(struct dhcp_message **messa
 {
 	struct dhcp_message *dhcp;
 	uint8_t *m, *lp, *p, *auth;
-	uint8_t *n_params = NULL;
+	uint8_t *n_params = NULL, auth_len;
 	uint32_t ul;
 	uint16_t sz;
-	size_t len, i, auth_len;
+	size_t len, i;
 	const struct dhcp_opt *opt;
 	struct if_options *ifo = ifp->options;
 	const struct dhcp_state *state = D_CSTATE(ifp);
@@ -757,9 +769,11 @@ make_message(struct dhcp_message **messa
 	dhcp->xid = htonl(state->xid);
 	dhcp->cookie = htonl(MAGIC_COOKIE);
 
-	*p++ = DHO_MESSAGETYPE;
-	*p++ = 1;
-	*p++ = type;
+	if (!(ifo->options & DHCPCD_BOOTP)) {
+		*p++ = DHO_MESSAGETYPE;
+		*p++ = 1;
+		*p++ = type;
+	}
 
 	if (state->clientid) {
 		*p++ = DHO_CLIENTID;
@@ -814,23 +828,25 @@ make_message(struct dhcp_message **messa
 	    type == DHCP_INFORM ||
 	    type == DHCP_REQUEST)
 	{
-		int mtu;
+		if (!(ifo->options & DHCPCD_BOOTP)) {
+			int mtu;
 
-		*p++ = DHO_MAXMESSAGESIZE;
-		*p++ = 2;
-		mtu = if_getmtu(ifp->name);
-		if (mtu < MTU_MIN) {
-			if (if_setmtu(ifp->name, MTU_MIN) == 0)
-				sz = MTU_MIN;
-		} else if (mtu > MTU_MAX) {
-			/* Even though our MTU could be greater than
-			 * MTU_MAX (1500) dhcpcd does not presently
-			 * handle DHCP packets any bigger. */
-			mtu = MTU_MAX;
-		}
-		sz = htons((uint16_t)mtu);
-		memcpy(p, &sz, 2);
-		p += 2;
+			*p++ = DHO_MAXMESSAGESIZE;
+			*p++ = 2;
+			mtu = if_getmtu(ifp->name);
+			if (mtu < MTU_MIN) {
+				if (if_setmtu(ifp->name, MTU_MIN) == 0)
+					sz = MTU_MIN;
+			} else if (mtu > MTU_MAX) {
+				/* Even though our MTU could be greater than
+				 * MTU_MAX (1500) dhcpcd does not presently
+				 * handle DHCP packets any bigger. */
+				mtu = MTU_MAX;
+			}
+			sz = htons((uint16_t)mtu);
+			memcpy(p, &sz, 2);
+			p += 2;
+		}
 
 		if (ifo->userclass[0]) {
 			*p++ = DHO_USERCLASS;
@@ -1004,19 +1020,23 @@ make_message(struct dhcp_message **messa
 	auth = NULL;
 
 	if (ifo->auth.options & DHCPCD_AUTH_SEND) {
-		auth_len = (size_t)dhcp_auth_encode(&ifo->auth,
+		ssize_t alen = dhcp_auth_encode(&ifo->auth,
 		    state->auth.token,
 		    NULL, 0, 4, type, NULL, 0);
-		if ((ssize_t)auth_len == -1) {
+		if (alen != -1 && alen > UINT8_MAX) {
+			errno = ERANGE;
+			alen = -1;
+		}
+		if (alen == -1)
 			logger(ifp->ctx, LOG_ERR,
 			    "%s: dhcp_auth_encode: %m", ifp->name);
-			auth_len = 0;
-		} else if (auth_len != 0) {
-			len = (size_t)((p + auth_len) - m);
-			if (auth_len > 255 || len > sizeof(*dhcp))
+		else if (alen != 0) {
+			auth_len = (uint8_t)alen;
+			len = (size_t)((p + alen) - m);
+			if (len > sizeof(*dhcp))
 				goto toobig;
 			*p++ = DHO_AUTHENTICATION;
-			*p++ = (uint8_t)auth_len;
+			*p++ = auth_len;
 			auth = p;
 			p += auth_len;
 		}
@@ -1024,13 +1044,10 @@ make_message(struct dhcp_message **messa
 
 	*p++ = DHO_END;
 
-#ifdef BOOTP_MESSAGE_LENTH_MIN
-	/* Some crappy DHCP servers think they have to obey the BOOTP minimum
-	 * message length.
-	 * They are wrong, but we should still cater for them. */
+	/* Pad out to the BOOTP minimum message length.
+	 * Some DHCP servers incorrectly require this. */
 	while (p - m < BOOTP_MESSAGE_LENTH_MIN)
 		*p++ = DHO_PAD;
-#endif
 
 	len = (size_t)(p - m);
 	if (ifo->auth.options & DHCPCD_AUTH_SEND && auth_len != 0)
@@ -1058,7 +1075,7 @@ write_lease(const struct interface *ifp,
 	const struct dhcp_state *state = D_CSTATE(ifp);
 
 	/* We don't write BOOTP leases */
-	if (is_bootp(ifp, dhcp)) {
+	if (IS_BOOTP(ifp, dhcp)) {
 		unlink(state->leasefile);
 		return 0;
 	}
@@ -1126,6 +1143,7 @@ read_lease(struct interface *ifp)
 	/* We may have found a BOOTP server */
 	if (get_option_uint8(ifp->ctx, &type, dhcp, DHO_MESSAGETYPE) == -1)
 		type = 0;
+
 	/* Authenticate the message */
 	auth = get_option(ifp->ctx, dhcp, DHO_AUTHENTICATION, &auth_len);
 	if (auth) {
@@ -1497,18 +1515,18 @@ checksum(const void *data, unsigned int 
 	uint32_t sum = 0;
 
 	while (len > 1) {
-		sum += (uint32_t)addr[0] * 256 + (uint32_t)addr[1];
+		sum += (uint32_t)(addr[0] * 256 + addr[1]);
 		addr += 2;
 		len -= 2;
 	}
 
 	if (len == 1)
-		sum += (uint32_t)*addr * 256;
+		sum += (uint32_t)(*addr * 256);
 
 	sum = (sum >> 16) + (sum & 0xffff);
 	sum += (sum >> 16);
 
-	return (uint16_t)~htons(sum);
+	return (uint16_t)~htons((uint16_t)sum);
 }
 
 static struct udp_dhcp_packet *
@@ -1574,10 +1592,15 @@ send_message(struct interface *ifp, uint
 	in_addr_t a = INADDR_ANY;
 	struct timespec tv;
 	int s;
+#ifdef IN_IFF_NOTUSEABLE
+	struct ipv4_addr *ia;
+#endif
 
 	if (!callback)
 		logger(ifp->ctx, LOG_DEBUG, "%s: sending %s with xid 0x%x",
-		    ifp->name, get_dhcp_op(type), state->xid);
+		    ifp->name,
+		    ifo->options & DHCPCD_BOOTP ? "BOOTP" : get_dhcp_op(type),
+		    state->xid);
 	else {
 		if (state->interval == 0)
 			state->interval = 4;
@@ -1592,7 +1615,9 @@ send_message(struct interface *ifp, uint
 		timespecnorm(&tv);
 		logger(ifp->ctx, LOG_DEBUG,
 		    "%s: sending %s (xid 0x%x), next in %0.1f seconds",
-		    ifp->name, get_dhcp_op(type), state->xid,
+		    ifp->name,
+		    ifo->options & DHCPCD_BOOTP ? "BOOTP" : get_dhcp_op(type),
+		    state->xid,
 		    timespec_to_double(&tv));
 	}
 
@@ -1602,6 +1627,10 @@ send_message(struct interface *ifp, uint
 	if (state->added && !(state->added & STATE_FAKE) &&
 	    state->addr.s_addr != INADDR_ANY &&
 	    state->new != NULL &&
+#ifdef IN_IFF_NOTUSEABLE
+	    ((ia = ipv4_iffindaddr(ifp, &state->addr, NULL)) &&
+	    !(ia->addr_flags & IN_IFF_NOTUSEABLE)) &&
+#endif
 	    (state->new->cookie == htonl(MAGIC_COOKIE) ||
 	    ifp->options->options & DHCPCD_INFORM))
 	{
@@ -1618,7 +1647,7 @@ send_message(struct interface *ifp, uint
 	 * Also, we should not unicast from a BOOTP lease. */
 	if (s == -1 ||
 	    (!(ifo->options & DHCPCD_INFORM) &&
-	    is_bootp(ifp, state->new)))
+	    IS_BOOTP(ifp, state->new)))
 	{
 		a = state->addr.s_addr;
 		state->addr.s_addr = INADDR_ANY;
@@ -1751,7 +1780,8 @@ dhcp_discover(void *arg)
 		    ifp->name, inet_ntoa(ifo->req_addr));
 	else
 		logger(ifp->ctx, LOG_INFO,
-		    "%s: soliciting a DHCP lease", ifp->name);
+		    "%s: soliciting a %s lease",
+		    ifp->name, ifo->options & DHCPCD_BOOTP ? "BOOTP" : "DHCP");
 	send_discover(ifp);
 }
 
@@ -1779,7 +1809,7 @@ dhcp_expire(void *arg)
 	dhcp_discover(ifp);
 }
 
-void
+static void
 dhcp_decline(struct interface *ifp)
 {
 
@@ -1804,12 +1834,14 @@ dhcp_renew(void *arg)
 	send_renew(ifp);
 }
 
+#ifndef IN_IFF_TENTATIVE
 static void
 dhcp_arp_announced(struct arp_state *astate)
 {
 
 	arp_close(astate->iface);
 }
+#endif
 
 static void
 dhcp_rebind(void *arg)
@@ -1958,13 +1990,18 @@ dhcp_bind(struct interface *ifp, struct 
 
 applyaddr:
 	ipv4_applyaddr(ifp);
-	if (dhcpcd_daemonise(ifp->ctx))
-		return;
-	if (ifo->options & DHCPCD_ARP) {
+	if (ifo->options & DHCPCD_ARP &&
+	    !(ifp->ctx->options & DHCPCD_FORKED))
+	{
+#ifdef IN_IFF_TENTATIVE
+		if (astate)
+			arp_free_but(astate);
+		else if (!ipv4ll)
+			arp_close(ifp);
+#else
 		if (state->added) {
 			if (astate == NULL) {
-				astate = arp_new(ifp);
-				astate->addr = state->addr;
+				astate = arp_new(ifp, &state->addr);
 				astate->announced_cb =
 				    dhcp_arp_announced;
 			}
@@ -1975,6 +2012,7 @@ applyaddr:
 			}
 		} else if (!ipv4ll)
 			arp_close(ifp);
+#endif
 	}
 }
 
@@ -2328,7 +2366,12 @@ dhcp_arp_probed(struct arp_state *astate
 	}
 	dhcp_close(astate->iface);
 	eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate->iface);
+#ifdef IN_IFF_TENTATIVE
+	ipv4_finaliseaddr(astate->iface);
+	arp_close(astate->iface);
+#else
 	dhcp_bind(astate->iface, astate);
+#endif
 }
 
 static void
@@ -2341,6 +2384,7 @@ dhcp_arp_conflicted(struct arp_state *as
 	ifo = astate->iface->options;
 	if (state->arping_index &&
 	    state->arping_index <= ifo->arping_len &&
+	    amsg &&
 	    (amsg->sip.s_addr == ifo->arping[state->arping_index - 1] ||
 	    (amsg->sip.s_addr == 0 &&
 	    amsg->tip.s_addr == ifo->arping[state->arping_index - 1])))
@@ -2367,18 +2411,30 @@ dhcp_arp_conflicted(struct arp_state *as
 		dhcpcd_startinterface(astate->iface);
 	}
 
-	if (state->offer == NULL)
-		return;
-
-	/* RFC 2131 3.1.5, Client-server interaction */
-	if (amsg->sip.s_addr == state->offer->yiaddr ||
-	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == state->offer->yiaddr))
+	/* RFC 2131 3.1.5, Client-server interaction
+	 * NULL amsg means IN_IFF_DUPLICATED */
+	if (amsg == NULL || (state->offer &&
+	    (amsg->sip.s_addr == state->offer->yiaddr ||
+	    (amsg->sip.s_addr == 0 &&
+	    amsg->tip.s_addr == state->offer->yiaddr))))
 	{
-		astate->failed.s_addr = state->offer->yiaddr;
+#ifdef IN_IFF_DUPLICATED
+		struct ipv4_addr *ia;
+#endif
+
+		if (amsg)
+			astate->failed.s_addr = state->offer->yiaddr;
+		else
+			astate->failed = astate->addr;
 		arp_report_conflicted(astate, amsg);
 		unlink(state->leasefile);
 		if (!state->lease.frominfo)
 			dhcp_decline(astate->iface);
+#ifdef IN_IFF_DUPLICATED
+		ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL);
+		if (ia)
+			ipv4_deladdr(astate->iface, &ia->addr, &ia->net);
+#endif
 		eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
 		    astate->iface);
 		eloop_timeout_add_sec(astate->iface->ctx->eloop,
@@ -2386,23 +2442,6 @@ dhcp_arp_conflicted(struct arp_state *as
 	}
 }
 
-void
-dhcp_probe(struct interface *ifp)
-{
-	const struct dhcp_state *state;
-	struct arp_state *astate;
-
-	astate = arp_new(ifp);
-	if (astate) {
-		state = D_CSTATE(ifp);
-		astate->addr = state->addr;
-		astate->probed_cb = dhcp_arp_probed;
-		astate->conflicted_cb = dhcp_arp_conflicted;
-		astate->announced_cb = dhcp_arp_announced;
-		arp_probe(astate);
-	}
-}
-
 static void
 dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
     const struct in_addr *from)
@@ -2417,10 +2456,18 @@ dhcp_handledhcp(struct interface *ifp, s
 	unsigned int i;
 	size_t auth_len;
 	char *msg;
+	struct arp_state *astate;
+	struct ipv4_addr *ia;
 
 	/* We may have found a BOOTP server */
 	if (get_option_uint8(ifp->ctx, &type, dhcp, DHO_MESSAGETYPE) == -1)
 		type = 0;
+	else if (ifo->options & DHCPCD_BOOTP) {
+		logger(ifp->ctx, LOG_DEBUG,
+		    "%s: ignoring DHCP reply (excpecting BOOTP)",
+		    ifp->name);
+		return;
+	}
 
 	/* Authenticate the message */
 	auth = get_option(ifp->ctx, dhcp, DHO_AUTHENTICATION, &auth_len);
@@ -2553,9 +2600,9 @@ dhcp_handledhcp(struct interface *ifp, s
 		if (has_option_mask(ifo->requiremask, i) &&
 		    get_option_uint8(ifp->ctx, &tmp, dhcp, (uint8_t)i) != 0)
 		{
-			/* If we are bootp, then ignore the need for serverid.
-			 * To ignore bootp, require dhcp_message_type.
-			 * However, nothing really stops bootp from providing
+			/* If we are BOOTP, then ignore the need for serverid.
+			 * To ignore BOOTP, require dhcp_message_type.
+			 * However, nothing really stops BOOTP from providing
 			 * DHCP style options as well so the above isn't
 			 * always true. */
 			if (type == 0 && i == DHO_SERVERID)
@@ -2621,6 +2668,21 @@ dhcp_handledhcp(struct interface *ifp, s
 		return;
 	}
 
+#ifdef IN_IFF_DUPLICATED
+	ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+	if (ia && ia->addr_flags & IN_IFF_DUPLICATED) {
+		log_dhcp(LOG_WARNING, "declined duplicate address",
+		    ifp, dhcp, from);
+		if (type)
+			dhcp_decline(ifp);
+		ipv4_deladdr(ifp, &ia->addr, &ia->net);
+		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+		eloop_timeout_add_sec(ifp->ctx->eloop,
+		    DHCP_RAND_MAX, dhcp_discover, ifp);
+		return;
+	}
+#endif
+
 	if ((type == 0 || type == DHCP_OFFER) &&
 	    (state->state == DHS_DISCOVER || state->state == DHS_IPV4LL_BOUND))
 	{
@@ -2695,28 +2757,35 @@ dhcp_handledhcp(struct interface *ifp, s
 
 	lease->frominfo = 0;
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+	astate = NULL;
 
-	if (ifo->options & DHCPCD_ARP &&
-	    state->addr.s_addr != state->offer->yiaddr)
+#ifndef IN_IFF_TENTATIVE
+	if (ifo->options & DHCPCD_ARP
+	    && state->addr.s_addr != state->offer->yiaddr)
+#endif
 	{
+		addr.s_addr = state->offer->yiaddr;
+#ifndef IN_IFF_TENTATIVE
 		/* If the interface already has the address configured
 		 * then we can't ARP for duplicate detection. */
-		addr.s_addr = state->offer->yiaddr;
-		if (!ipv4_iffindaddr(ifp, &addr, NULL)) {
-			struct arp_state *astate;
-
-			astate = arp_new(ifp);
+		ia = ipv4_findaddr(ifp->ctx, &addr);
+		if (ia) {
+#endif
+			astate = arp_new(ifp, &addr);
 			if (astate) {
-				astate->addr = addr;
 				astate->probed_cb = dhcp_arp_probed;
 				astate->conflicted_cb = dhcp_arp_conflicted;
+#ifndef IN_IFF_TENTATIVE
 				arp_probe(astate);
+#endif
 			}
+#ifndef IN_IFF_TENTATIVE
 			return;
 		}
+#endif
 	}
 
-	dhcp_bind(ifp, NULL);
+	dhcp_bind(ifp, astate);
 }
 
 static size_t
@@ -2939,9 +3008,8 @@ dhcp_dump(struct interface *ifp)
 	    AF_INET, ifp, "");
 	state->new = read_lease(ifp);
 	if (state->new == NULL) {
-		if (errno == ENOENT)
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: no lease to dump", ifp->name);
+		logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
+		    *ifp->name ? ifp->name : state->leasefile, __func__);
 		return -1;
 	}
 	state->reason = "DUMP";
@@ -3098,7 +3166,8 @@ dhcp_start1(void *arg)
 			/* Don't log an error if some other process
 			 * is handling this. */
 			if (errno != EADDRINUSE)
-				logger(ifp->ctx, LOG_ERR, "dhcp_openudp: %m");
+				logger(ifp->ctx, LOG_ERR,
+				    "%s: dhcp_openudp: %m", __func__);
 		} else
 			eloop_event_add(ifp->ctx->eloop,
 			    ifp->ctx->udp_fd, dhcp_handleudp,
@@ -3118,7 +3187,7 @@ dhcp_start1(void *arg)
 	if (state->arping_index < ifo->arping_len) {
 		struct arp_state *astate;
 
-		astate = arp_new(ifp);
+		astate = arp_new(ifp, NULL);
 		if (astate) {
 			astate->probed_cb = dhcp_arp_probed;
 			astate->conflicted_cb = dhcp_arp_conflicted;
@@ -3148,8 +3217,31 @@ dhcp_start1(void *arg)
 	}
 	/* We don't want to read the old lease if we NAK an old test */
 	nolease = state->offer && ifp->ctx->options & DHCPCD_TEST;
-	if (!nolease)
+	if (!nolease) {
 		state->offer = read_lease(ifp);
+		/* Check the saved lease matches the type we want */
+		if (state->offer) {
+#ifdef IN_IFF_DUPLICATED
+			struct in_addr addr;
+			struct ipv4_addr *ia;
+
+			addr.s_addr = state->offer->yiaddr;
+			ia = ipv4_iffindaddr(ifp, &addr, NULL);
+#endif
+
+			if ((IS_BOOTP(ifp, state->offer) &&
+			    !(ifo->options & DHCPCD_BOOTP)) ||
+#ifdef IN_IFF_DUPLICATED
+			    (ia && ia->addr_flags & IN_IFF_DUPLICATED) ||
+#endif
+			    (!IS_BOOTP(ifp, state->offer) &&
+			    ifo->options & DHCPCD_BOOTP))
+			{
+				free(state->offer);
+				state->offer = NULL;
+			}
+		}
+	}
 	if (state->offer) {
 		get_lease(ifp->ctx, &state->lease, state->offer);
 		state->lease.frominfo = 1;
@@ -3253,10 +3345,11 @@ dhcp_start(struct interface *ifp)
 }
 
 void
-dhcp_handleifa(int type, struct interface *ifp,
+dhcp_handleifa(int cmd, struct interface *ifp,
 	const struct in_addr *addr,
 	const struct in_addr *net,
-	const struct in_addr *dst)
+	const struct in_addr *dst,
+	__unused int flags)
 {
 	struct dhcp_state *state;
 	struct if_options *ifo;
@@ -3266,22 +3359,20 @@ dhcp_handleifa(int type, struct interfac
 	if (state == NULL)
 		return;
 
-	if (type == RTM_DELADDR) {
-		if (state->new &&
-		    (state->new->yiaddr == addr->s_addr ||
-		    (state->new->yiaddr == INADDR_ANY &&
-		     state->new->ciaddr == addr->s_addr)))
+	if (cmd == RTM_DELADDR) {
+		if (state->addr.s_addr == addr->s_addr &&
+		    state->net.s_addr == net->s_addr)
 		{
 			logger(ifp->ctx, LOG_INFO,
 			    "%s: removing IP address %s/%d",
-			    ifp->name, inet_ntoa(state->lease.addr),
-			    inet_ntocidr(state->lease.net));
+			    ifp->name, inet_ntoa(state->addr),
+			    inet_ntocidr(state->net));
 			dhcp_drop(ifp, "EXPIRE");
 		}
 		return;
 	}
 
-	if (type != RTM_NEWADDR)
+	if (cmd != RTM_NEWADDR)
 		return;
 
 	ifo = ifp->options;

Index: src/external/bsd/dhcpcd/dist/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.23 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.24
--- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.23	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.c	Sat May  2 15:18:36 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd.c,v 1.23 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd.c,v 1.24 2015/05/02 15:18:36 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -316,6 +316,17 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 }
 
 static void
+dhcpcd_drop(struct interface *ifp, int stop)
+{
+
+	dhcp6_drop(ifp, stop ? NULL : "EXPIRE6");
+	ipv6nd_drop(ifp);
+	ipv6_drop(ifp);
+	dhcp_drop(ifp, stop ? "STOP" : "EXPIRE");
+	arp_close(ifp);
+}
+
+static void
 stop_interface(struct interface *ifp)
 {
 	struct dhcpcd_ctx *ctx;
@@ -324,11 +335,7 @@ stop_interface(struct interface *ifp)
 	logger(ctx, LOG_INFO, "%s: removing interface", ifp->name);
 	ifp->options->options |= DHCPCD_STOPPING;
 
-	dhcp6_drop(ifp, NULL);
-	ipv6nd_drop(ifp);
-	ipv6_drop(ifp);
-	dhcp_drop(ifp, "STOP");
-	arp_close(ifp);
+	dhcpcd_drop(ifp, 1);
 	if (ifp->options->options & DHCPCD_DEPARTED)
 		script_runreason(ifp, "DEPARTED");
 	else
@@ -381,7 +388,7 @@ configure_interface1(struct interface *i
 		ifo->options &= ~(DHCPCD_IPV6RS | DHCPCD_DHCP6);
 
 	if (ifo->options & DHCPCD_SLAACPRIVATE &&
-	    !(ifp->ctx->options & DHCPCD_TEST))
+	    !(ifp->ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST)))
 		ifo->options |= DHCPCD_IPV6RA_OWN;
 
 	/* If we're a psuedo interface, ensure we disable as much as we can */
@@ -389,7 +396,9 @@ configure_interface1(struct interface *i
 		ifp->options->options &= ~(DHCPCD_IPV4 | DHCPCD_IPV6RS);
 
 	/* We want to disable kernel interface RA as early as possible. */
-	if (ifo->options & DHCPCD_IPV6RS) {
+	if (ifo->options & DHCPCD_IPV6RS &&
+	    !(ifp->ctx->options & DHCPCD_DUMPLEASE))
+	{
 		/* If not doing any DHCP, disable the RDNSS requirement. */
 		if (!(ifo->options & (DHCPCD_DHCP | DHCPCD_DHCP6)))
 			ifo->options &= ~DHCPCD_IPV6RA_REQRDNSS;
@@ -399,7 +408,8 @@ configure_interface1(struct interface *i
 		    ifp->options->options & DHCPCD_IPV6RA_OWN ? 1 : 0);
 		if (ra_global == -1 || ra_iface == -1)
 			ifo->options &= ~DHCPCD_IPV6RS;
-		else if (ra_iface == 0 && !(ifp->ctx->options & DHCPCD_TEST))
+		else if (ra_iface == 0 &&
+		    !(ifp->ctx->options & DHCPCD_TEST))
 			ifo->options |= DHCPCD_IPV6RA_OWN;
 	}
 
@@ -541,6 +551,7 @@ dhcpcd_selectprofile(struct interface *i
 		    ifp->name, profile);
 	} else
 		*ifp->profile = '\0';
+
 	free_options(ifp->options);
 	ifp->options = ifo;
 	if (profile)
@@ -552,11 +563,20 @@ static void
 configure_interface(struct interface *ifp, int argc, char **argv,
     unsigned long long options)
 {
+	time_t old;
 
+	old = ifp->options ? ifp->options->mtime : 0;
 	dhcpcd_selectprofile(ifp, NULL);
 	add_options(ifp->ctx, ifp->name, ifp->options, argc, argv);
 	ifp->options->options |= options;
 	configure_interface1(ifp);
+
+	/* If the mtime has changed drop any old lease */
+	if (ifp->options && old != 0 && ifp->options->mtime != old) {
+		logger(ifp->ctx, LOG_WARNING,
+		    "%s: confile file changed, expiring leases", ifp->name);
+		dhcpcd_drop(ifp, 0);
+	}
 }
 
 static void
@@ -584,7 +604,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 {
 	struct interface *ifp;
 
-	ifp = if_find(ctx, ifname);
+	ifp = if_find(ctx->ifaces, ifname);
 	if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
 		return;
 
@@ -617,18 +637,22 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 	} else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
 		if (ifp->carrier != LINK_DOWN) {
 			if (ifp->carrier == LINK_UP)
-				logger(ctx, LOG_INFO, "%s: carrier lost", ifp->name);
+				logger(ctx, LOG_INFO, "%s: carrier lost",
+				    ifp->name);
 			ifp->carrier = LINK_DOWN;
 			script_runreason(ifp, "NOCARRIER");
-			dhcp6_drop(ifp, "EXPIRE6");
-			ipv6nd_drop(ifp);
-			ipv6_drop(ifp);
-			dhcp_drop(ifp, "EXPIRE");
+#ifdef NOCARRIER_PRESERVE_IP
 			arp_close(ifp);
+			ipv4_buildroutes(ifp->ctx);
+			ipv6nd_expire(ifp, 0);
+#else
+			dhcpcd_drop(ifp, 0);
+#endif
 		}
 	} else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
 		if (ifp->carrier != LINK_UP) {
-			logger(ctx, LOG_INFO, "%s: carrier acquired", ifp->name);
+			logger(ctx, LOG_INFO, "%s: carrier acquired",
+			    ifp->name);
 			ifp->carrier = LINK_UP;
 #if !defined(__linux__) && !defined(__NetBSD__)
 			/* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
@@ -636,10 +660,30 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 			 * through the disovery process to work it out. */
 			dhcpcd_handleinterface(ctx, 0, ifp->name);
 #endif
-			if (ifp->wireless)
+			if (ifp->wireless) {
+				uint8_t ossid[IF_SSIDSIZE];
+#ifdef NOCARRIER_PRESERVE_IP
+				size_t olen;
+
+				olen = ifp->ssid_len;
+#endif
+				memcpy(ossid, ifp->ssid, ifp->ssid_len);
 				if_getssid(ifp);
+#ifdef NOCARRIER_PRESERVE_IP
+				/* If we changed SSID network, drop leases */
+				if (ifp->ssid_len != olen ||
+				    memcmp(ifp->ssid, ossid, ifp->ssid_len))
+					dhcpcd_drop(ifp, 0);
+#endif
+			}
 			dhcpcd_initstate(ifp, 0);
 			script_runreason(ifp, "CARRIER");
+#ifdef NOCARRIER_PRESERVE_IP
+			/* Set any IPv6 Routers we remembered to expire
+			 * faster than they would normally as we
+			 * maybe on a new network. */
+			ipv6nd_expire(ifp, RTR_CARRIER_EXPIRE);
+#endif
 			/* RFC4941 Section 3.5 */
 			if (ifp->options->options & DHCPCD_IPV6RA_OWN)
 				ipv6_gentempifid(ifp);
@@ -900,7 +944,7 @@ dhcpcd_handleinterface(void *arg, int ac
 
 	ctx = arg;
 	if (action == -1) {
-		ifp = if_find(ctx, ifname);
+		ifp = if_find(ctx->ifaces, ifname);
 		if (ifp == NULL) {
 			errno = ESRCH;
 			return -1;
@@ -931,7 +975,7 @@ dhcpcd_handleinterface(void *arg, int ac
 			continue;
 		i = 0;
 		/* Check if we already have the interface */
-		iff = if_find(ctx, ifp->name);
+		iff = if_find(ctx->ifaces, ifp->name);
 		if (iff) {
 			logger(ctx, LOG_DEBUG, "%s: interface updated", iff->name);
 			/* The flags and hwaddr could have changed */
@@ -970,7 +1014,7 @@ dhcpcd_handlehwaddr(struct dhcpcd_ctx *c
 	struct interface *ifp;
 	char buf[sizeof(ifp->hwaddr) * 3];
 
-	ifp = if_find(ctx, ifname);
+	ifp = if_find(ctx->ifaces, ifname);
 	if (ifp == NULL)
 		return;
 
@@ -1033,7 +1077,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in
 
 	while ((ifp = TAILQ_FIRST(ifs))) {
 		TAILQ_REMOVE(ifs, ifp, next);
-		ifn = if_find(ctx, ifp->name);
+		ifn = if_find(ctx->ifaces, ifp->name);
 		if (ifn) {
 			if (action)
 				if_reboot(ifn, argc, argv);
@@ -1286,7 +1330,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 			return 0;
 		}
 		for (oi = optind; oi < argc; oi++) {
-			if ((ifp = if_find(ctx, argv[oi])) == NULL)
+			if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
 				continue;
 			if (do_release) {
 				ifp->options->options |= DHCPCD_RELEASE;
@@ -1687,7 +1731,6 @@ main(int argc, char **argv)
 		}
 	}
 
-
 	if (ctx.options & DHCPCD_MASTER) {
 		if (control_start(&ctx, NULL) == -1)
 			logger(&ctx, LOG_ERR, "control_start: %m");
@@ -1740,7 +1783,7 @@ main(int argc, char **argv)
 		goto exit_failure;
 	}
 	for (i = 0; i < ctx.ifc; i++) {
-		if (if_find(&ctx, ctx.ifv[i]) == NULL)
+		if (if_find(ctx.ifaces, ctx.ifv[i]) == NULL)
 			logger(&ctx, LOG_ERR,
 			    "%s: interface not found or invalid",
 			    ctx.ifv[i]);

Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.19 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.20
--- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.19	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.conf.5.in,v 1.19 2015/03/26 10:26:37 roy Exp $
+.\"     $NetBSD: dhcpcd.conf.5.in,v 1.20 2015/05/02 15:18:37 roy Exp $
 .\" Copyright (c) 2006-2015 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 March 17, 2015
+.Dd April 6, 2015
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -111,6 +111,11 @@ Only accept packets from
 is ignored if
 .Ic whitelist
 is set.
+.It Ic bootp
+Be a BOOTP client.
+Basically, this just doesn't send a DHCP Message Type option and will only
+interact with a BOOTP server.
+All other DHCP options still work.
 .It Ic broadcast
 Instructs the DHCP server to broadcast replies back to the client.
 Normally this is only set for non Ethernet interfaces,
@@ -369,6 +374,12 @@ Each time dhcpcd receives an IPv6 Router
 the default route only.
 This allows dhcpcd to prefer an interface for outbound traffic based on metric
 and/or user selection rather than the kernel.
+.It Ic ipv6ra_accept_nopublic
+Some IPv6 routers advertise themselves as a default router without any
+public prefixes or managed addresses.
+Generally, this is incorrect behaviour and
+.Nm dhcpcd
+will ignore the advertisement unless this option is turned on.
 .It Ic ipv6rs
 Enables IPv6 Router Advertisment solicitation.
 This is on by default, but is documented here in the case where it is disabled
Index: src/external/bsd/dhcpcd/dist/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.19 src/external/bsd/dhcpcd/dist/if-bsd.c:1.20
--- src/external/bsd/dhcpcd/dist/if-bsd.c:1.19	Fri Mar 27 18:51:08 2015
+++ src/external/bsd/dhcpcd/dist/if-bsd.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-bsd.c,v 1.19 2015/03/27 18:51:08 christos Exp $");
+ __RCSID("$NetBSD: if-bsd.c,v 1.20 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -284,7 +284,7 @@ if_findsdl(struct dhcpcd_ctx *ctx, struc
 		char ifname[IF_NAMESIZE];
 		memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
 		ifname[sdl->sdl_nlen] = '\0';
-		return if_find(ctx, ifname);
+		return if_find(ctx->ifaces, ifname);
 	}
 	return NULL;
 }
@@ -294,7 +294,7 @@ if_findsdl(struct dhcpcd_ctx *ctx, struc
 const char *if_pfname = "Berkley Packet Filter";
 
 int
-if_openrawsocket(struct interface *ifp, int protocol)
+if_openrawsocket(struct interface *ifp, uint16_t protocol)
 {
 	struct dhcp_state *state;
 	int fd = -1;
@@ -378,7 +378,7 @@ eexit:
 }
 
 ssize_t
-if_sendrawpacket(const struct interface *ifp, int protocol,
+if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
     const void *data, size_t len)
 {
 	struct iovec iov[2];
@@ -388,7 +388,7 @@ if_sendrawpacket(const struct interface 
 
 	memset(&hw, 0, ETHER_HDR_LEN);
 	memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
-	hw.ether_type = htons((uint16_t)protocol);
+	hw.ether_type = htons(protocol);
 	iov[0].iov_base = &hw;
 	iov[0].iov_len = ETHER_HDR_LEN;
 	iov[1].iov_base = UNCONST(data);
@@ -404,7 +404,7 @@ if_sendrawpacket(const struct interface 
 /* BPF requires that we read the entire buffer.
  * So we pass the buffer in the API so we can loop on >1 packet. */
 ssize_t
-if_readrawpacket(struct interface *ifp, int protocol,
+if_readrawpacket(struct interface *ifp, uint16_t protocol,
     void *data, size_t len, int *flags)
 {
 	int fd;
@@ -520,7 +520,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
 
 	if (rtm->rtm_index)
-		rt->iface = if_findindex(ctx, rtm->rtm_index);
+		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
 	else if (rtm->rtm_addrs & RTA_IFP) {
 		struct sockaddr_dl *sdl;
 
@@ -549,7 +549,6 @@ if_route(unsigned char cmd, const struct
 		struct sockaddr sa;
 		struct sockaddr_in sin;
 		struct sockaddr_dl sdl;
-		struct sockaddr_storage ss;
 	} su;
 	struct rtm
 	{
@@ -609,8 +608,8 @@ if_route(unsigned char cmd, const struct
 #endif
 		}
 	}
-	if (rt->dest.s_addr == rt->gate.s_addr &&
-	    rt->net.s_addr == INADDR_BROADCAST)
+	if (rt->net.s_addr == htonl(INADDR_BROADCAST) &&
+	    rt->gate.s_addr == htonl(INADDR_ANY))
 	{
 #ifdef RTF_CLONING
 		/* We add a cloning network route for a single host.
@@ -625,7 +624,7 @@ if_route(unsigned char cmd, const struct
 		rtm.hdr.rtm_flags |= RTF_HOST;
 #endif
 	} else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
-	    rt->net.s_addr == INADDR_BROADCAST)
+	    rt->net.s_addr == htonl(INADDR_BROADCAST))
 	{
 		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
 		/* Going via lo0 so remove the interface flags */
@@ -717,7 +716,40 @@ if_initrt(struct interface *ifp)
 	free(buf);
 	return 0;
 }
+
+#ifdef SIOCGIFAFLAG_IN
+int
+if_addrflags(const struct in_addr *addr, const struct interface *ifp)
+{
+	int s, flags;
+	struct ifreq ifr;
+	struct sockaddr_in *sin;
+
+	s = socket(PF_INET, SOCK_DGRAM, 0);
+	flags = -1;
+	if (s != -1) {
+		memset(&ifr, 0, sizeof(ifr));
+		strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+		sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
+		sin->sin_family = AF_INET;
+		sin->sin_addr = *addr;
+		if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1)
+			flags = ifr.ifr_addrflags;
+		close(s);
+	}
+	return flags;
+}
+#else
+int
+if_addrflags(__unused const struct in_addr *addr,
+    __unused const struct interface *ifp)
+{
+
+	errno = ENOTSUP;
+	return 0;
+}
 #endif
+#endif /* INET */
 
 #ifdef INET6
 static void
@@ -877,7 +909,7 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 	COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
 
 	if (rtm->rtm_index)
-		rt->iface = if_findindex(ctx, rtm->rtm_index);
+		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
 	else if (rtm->rtm_addrs & RTA_IFP) {
 		struct sockaddr_dl *sdl;
 
@@ -905,7 +937,6 @@ if_route6(unsigned char cmd, const struc
 		struct sockaddr sa;
 		struct sockaddr_in6 sin;
 		struct sockaddr_dl sdl;
-		struct sockaddr_storage ss;
 	} su;
 	struct rtm
 	{
@@ -1132,6 +1163,8 @@ if_managelink(struct dhcpcd_ctx *ctx)
 	struct rt6 rt6;
 	struct in6_addr ia6, net6;
 	struct sockaddr_in6 *sin6;
+#endif
+#if (defined(INET) && defined(IN_IFF_TENTATIVE)) || defined(INET6)
 	int ifa_flags;
 #endif
 
@@ -1161,7 +1194,8 @@ if_managelink(struct dhcpcd_ctx *ctx)
 #endif
 		case RTM_IFINFO:
 			ifm = (struct if_msghdr *)(void *)p;
-			if ((ifp = if_findindex(ctx, ifm->ifm_index)) == NULL)
+			ifp = if_findindex(ctx->ifaces, ifm->ifm_index);
+			if (ifp == NULL)
 				break;
 			switch (ifm->ifm_data.ifi_link_state) {
 			case LINK_STATE_DOWN:
@@ -1237,7 +1271,8 @@ if_managelink(struct dhcpcd_ctx *ctx)
 		case RTM_DELADDR:	/* FALLTHROUGH */
 		case RTM_NEWADDR:
 			ifam = (struct ifa_msghdr *)(void *)p;
-			if ((ifp = if_findindex(ctx, ifam->ifam_index)) == NULL)
+			ifp = if_findindex(ctx->ifaces, ifam->ifam_index);
+			if (ifp == NULL)
 				break;
 			cp = (char *)(void *)(ifam + 1);
 			get_addrs(ifam->ifam_addrs, cp, rti_info);
@@ -1264,9 +1299,15 @@ if_managelink(struct dhcpcd_ctx *ctx)
 				COPYOUT(rt.dest, rti_info[RTAX_IFA]);
 				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
 				COPYOUT(rt.gate, rti_info[RTAX_BRD]);
+				if (rtm->rtm_type == RTM_NEWADDR) {
+					ifa_flags = if_addrflags(&rt.dest, ifp);
+					if (ifa_flags == -1)
+						break;
+				} else
+					ifa_flags = 0;
 				ipv4_handleifa(ctx, rtm->rtm_type,
 				    NULL, ifp->name,
-				    &rt.dest, &rt.net, &rt.gate);
+				    &rt.dest, &rt.net, &rt.gate, ifa_flags);
 				break;
 #endif
 #ifdef INET6

Index: src/external/bsd/dhcpcd/dist/eloop.c
diff -u src/external/bsd/dhcpcd/dist/eloop.c:1.9 src/external/bsd/dhcpcd/dist/eloop.c:1.10
--- src/external/bsd/dhcpcd/dist/eloop.c:1.9	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/eloop.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: eloop.c,v 1.9 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: eloop.c,v 1.10 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -28,9 +28,6 @@
  * SUCH DAMAGE.
  */
 
-/* Needed for ppoll(2) */
-#define _GNU_SOURCE
-
 #include <sys/time.h>
 
 #include <errno.h>
Index: src/external/bsd/dhcpcd/dist/if-options.h
diff -u src/external/bsd/dhcpcd/dist/if-options.h:1.9 src/external/bsd/dhcpcd/dist/if-options.h:1.10
--- src/external/bsd/dhcpcd/dist/if-options.h:1.9	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/if-options.h	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: if-options.h,v 1.9 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: if-options.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -111,6 +111,12 @@
 #define DHCPCD_PFXDLGMIX		(1ULL << 53)
 #define DHCPCD_IPV6RA_AUTOCONF		(1ULL << 54)
 #define DHCPCD_ROUTER_HOST_ROUTE_WARNED	(1ULL << 55)
+#define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC	(1ULL << 56)
+#define DHCPCD_BOOTP			(1ULL << 57)
+
+#define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \
+		DHCPCD_ROUTER_HOST_ROUTE_WARNED)
+#define DHCPCD_CONF (DHCPCD_NOPFXDLG | DHCPCD_PFXDLGONLY)
 
 extern const struct option cf_options[];
 
@@ -140,6 +146,7 @@ struct vivco {
 };
 
 struct if_options {
+	time_t mtime;
 	uint8_t iaid[4];
 	int metric;
 	uint8_t requestmask[256 / NBBY];
Index: src/external/bsd/dhcpcd/dist/if.h
diff -u src/external/bsd/dhcpcd/dist/if.h:1.9 src/external/bsd/dhcpcd/dist/if.h:1.10
--- src/external/bsd/dhcpcd/dist/if.h:1.9	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/if.h	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.9 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: if.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -31,8 +31,14 @@
 #define INTERFACE_H
 
 #include <net/if.h>
+#ifdef __FreeBSD__
+#include <net/if_var.h>
+#endif
 #include <net/route.h>		/* for RTM_ADD et all */
 #include <netinet/in.h>
+#ifdef BSD
+#include <netinet/in_var.h>	/* for IN_IFF_TENTATIVE et all */
+#endif
 
 /* Some systems have route metrics.
  * OpenBSD route priority is not this. */
@@ -42,6 +48,14 @@
 # endif
 #endif
 
+/* Some systems have in-built IPv4 DAD.
+ * However, we need them to do DAD at carrier up as well. */
+#ifdef IN_IFF_TENTATIVE
+#  ifdef __NetBSD__
+#    define NOCARRIER_PRESERVE_IP
+#  endif
+#endif
+
 #include "config.h"
 #include "dhcpcd.h"
 #include "ipv4.h"
@@ -85,8 +99,8 @@
 int if_setflag(struct interface *ifp, short flag);
 #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING))
 struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
-struct interface *if_find(struct dhcpcd_ctx *, const char *);
-struct interface *if_findindex(struct dhcpcd_ctx *, unsigned int);
+struct interface *if_find(struct if_head *, const char *);
+struct interface *if_findindex(struct if_head *, unsigned int);
 void if_sortinterfaces(struct dhcpcd_ctx *);
 void if_free(struct interface *);
 int if_domtu(const char *, short int);
@@ -114,10 +128,10 @@ int if_managelink(struct dhcpcd_ctx *);
 
 #ifdef INET
 extern const char *if_pfname;
-int if_openrawsocket(struct interface *, int);
+int if_openrawsocket(struct interface *, uint16_t);
 ssize_t if_sendrawpacket(const struct interface *,
-    int, const void *, size_t);
-ssize_t if_readrawpacket(struct interface *, int, void *, size_t, int *);
+    uint16_t, const void *, size_t);
+ssize_t if_readrawpacket(struct interface *, uint16_t, void *, size_t, int *);
 
 int if_address(const struct interface *,
     const struct in_addr *, const struct in_addr *,
@@ -127,6 +141,8 @@ int if_address(const struct interface *,
 #define if_deladdress(ifp, addr, net)		\
 	if_address(ifp, addr, net, NULL, -1)
 
+int if_addrflags(const struct in_addr *, const struct interface *);
+
 int if_route(unsigned char, const struct rt *rt);
 int if_initrt(struct interface *);
 #endif
Index: src/external/bsd/dhcpcd/dist/ipv4.h
diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.9 src/external/bsd/dhcpcd/dist/ipv4.h:1.10
--- src/external/bsd/dhcpcd/dist/ipv4.h:1.9	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv4.h	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv4.h,v 1.9 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: ipv4.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -32,6 +32,11 @@
 
 #include "dhcpcd.h"
 
+#ifdef IN_IFF_TENTATIVE
+#define IN_IFF_NOTUSEABLE \
+        (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED | IN_IFF_DETACHED)
+#endif
+
 struct rt {
 	TAILQ_ENTRY(rt) next;
 	struct in_addr dest;
@@ -42,7 +47,7 @@ struct rt {
 	unsigned int metric;
 #endif
 	struct in_addr src;
-	uint8_t flags;
+	unsigned int flags;
 };
 TAILQ_HEAD(rt_head, rt);
 
@@ -52,6 +57,7 @@ struct ipv4_addr {
 	struct in_addr net;
 	struct in_addr dst;
 	struct interface *iface;
+	int addr_flags;
 };
 TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
 
@@ -77,6 +83,9 @@ int ipv4_addrexists(struct dhcpcd_ctx *,
 #define STATE_FAKE		0x02
 
 void ipv4_buildroutes(struct dhcpcd_ctx *);
+void ipv4_finaliseaddr(struct interface *);
+int ipv4_deladdr(struct interface *ifp, const struct in_addr *,
+    const struct in_addr *);
 void ipv4_applyaddr(void *);
 int ipv4_handlert(struct dhcpcd_ctx *, int, struct rt *);
 void ipv4_freerts(struct rt_head *);
@@ -86,7 +95,8 @@ struct ipv4_addr *ipv4_iffindaddr(struct
 struct ipv4_addr *ipv4_iffindlladdr(struct interface *);
 struct ipv4_addr *ipv4_findaddr(struct dhcpcd_ctx *, const struct in_addr *);
 void ipv4_handleifa(struct dhcpcd_ctx *, int, struct if_head *, const char *,
-    const struct in_addr *, const struct in_addr *, const struct in_addr *);
+    const struct in_addr *, const struct in_addr *, const struct in_addr *,
+    int);
 
 void ipv4_freeroutes(struct rt_head *);
 
Index: src/external/bsd/dhcpcd/dist/ipv4ll.c
diff -u src/external/bsd/dhcpcd/dist/ipv4ll.c:1.9 src/external/bsd/dhcpcd/dist/ipv4ll.c:1.10
--- src/external/bsd/dhcpcd/dist/ipv4ll.c:1.9	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv4ll.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4ll.c,v 1.9 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: ipv4ll.c,v 1.10 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -108,11 +108,17 @@ static void
 ipv4ll_probed(struct arp_state *astate)
 {
 	struct dhcp_state *state = D_STATE(astate->iface);
-	struct dhcp_message *offer;
+
+	if (state->state == DHS_IPV4LL_BOUND) {
+		ipv4_finaliseaddr(astate->iface);
+		return;
+	}
 
 	if (state->state != DHS_BOUND) {
+		struct dhcp_message *offer;
+
 		/* A DHCP lease could have already been offered.
-		 * Backup and replace once the IPv4LL addres is bound */
+		 * Backup and replace once the IPv4LL address is bound */
 		offer = state->offer;
 		state->offer = ipv4ll_make_lease(astate->addr.s_addr);
 		if (state->offer == NULL)
@@ -136,7 +142,11 @@ static void
 ipv4ll_probe(void *arg)
 {
 
+#ifdef IN_IFF_TENTATIVE
+	ipv4ll_probed(arg);
+#else
 	arp_probe(arg);
+#endif
 }
 
 static void
@@ -147,13 +157,14 @@ ipv4ll_conflicted(struct arp_state *asta
 
 	fail = 0;
 	/* RFC 3927 2.2.1, Probe Conflict Detection */
-	if (amsg->sip.s_addr == astate->addr.s_addr ||
-	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr))
+	if (amsg == NULL ||
+	    (amsg->sip.s_addr == astate->addr.s_addr ||
+	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr)))
 		fail = astate->addr.s_addr;
 
 	/* RFC 3927 2.5, Conflict Defense */
 	if (IN_LINKLOCAL(htonl(state->addr.s_addr)) &&
-	    amsg->sip.s_addr == state->addr.s_addr)
+	    amsg && amsg->sip.s_addr == state->addr.s_addr)
 		fail = state->addr.s_addr;
 
 	if (fail == 0)
@@ -221,7 +232,7 @@ ipv4ll_start(void *arg)
 		initstate(seed, state->randomstate, sizeof(state->randomstate));
 	}
 
-	if ((astate = arp_new(ifp)) == NULL)
+	if ((astate = arp_new(ifp, NULL)) == NULL)
 		return;
 
 	state->arp_ipv4ll = astate;
@@ -257,7 +268,11 @@ ipv4ll_start(void *arg)
 	}
 	if (astate->addr.s_addr == INADDR_ANY)
 		astate->addr.s_addr = ipv4ll_pick_addr(astate);
+#ifdef IN_IFF_TENTATIVE
+	ipv4ll_probed(astate);
+#else
 	arp_probe(astate);
+#endif
 }
 
 void

Index: src/external/bsd/dhcpcd/dist/if-options.c
diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.22 src/external/bsd/dhcpcd/dist/if-options.c:1.23
--- src/external/bsd/dhcpcd/dist/if-options.c:1.22	Fri Mar 27 11:33:46 2015
+++ src/external/bsd/dhcpcd/dist/if-options.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-options.c,v 1.22 2015/03/27 11:33:46 roy Exp $");
+ __RCSID("$NetBSD: if-options.c,v 1.23 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -31,6 +31,7 @@
 #define _WITH_GETLINE /* Stop FreeBSD bitching */
 
 #include <sys/param.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <arpa/inet.h>
@@ -100,6 +101,8 @@
 #define O_IPV6RA_AUTOCONF	O_BASE + 38
 #define O_IPV6RA_NOAUTOCONF	O_BASE + 39
 #define O_REJECT		O_BASE + 40
+#define O_IPV6RA_ACCEPT_NOPUBLIC	O_BASE + 41
+#define O_BOOTP			O_BASE + 42
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -159,6 +162,7 @@ const struct option cf_options[] = {
 	{"ipv6ra_fork",     no_argument,       NULL, O_IPV6RA_FORK},
 	{"ipv6ra_own",      no_argument,       NULL, O_IPV6RA_OWN},
 	{"ipv6ra_own_default", no_argument,    NULL, O_IPV6RA_OWN_D},
+	{"ipv6ra_accept_nopublic", no_argument, NULL, O_IPV6RA_ACCEPT_NOPUBLIC},
 	{"ipv4only",        no_argument,       NULL, '4'},
 	{"ipv6only",        no_argument,       NULL, '6'},
 	{"ipv4",            no_argument,       NULL, O_IPV4},
@@ -191,6 +195,7 @@ const struct option cf_options[] = {
 	{"gateway",         no_argument,       NULL, O_GATEWAY},
 	{"ia_pd_mix",       no_argument,       NULL, O_PFXDLGMIX},
 	{"reject",          required_argument, NULL, O_REJECT},
+	{"bootp",           no_argument,       NULL, O_BOOTP},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -1237,6 +1242,9 @@ parse_option(struct dhcpcd_ctx *ctx, con
 	case O_IPV6RA_OWN_D:
 		ifo->options |= DHCPCD_IPV6RA_OWN_DEFAULT;
 		break;
+	case O_IPV6RA_ACCEPT_NOPUBLIC:
+		ifo->options |= DHCPCD_IPV6RA_ACCEPT_NOPUBLIC;
+		break;
 	case O_IPV6RA_AUTOCONF:
 		ifo->options |= DHCPCD_IPV6RA_AUTOCONF;
 		break;
@@ -1955,6 +1963,9 @@ err_sla:
 	case O_PFXDLGMIX:
 		ifo->options |= DHCPCD_PFXDLGMIX;
 		break;
+	case O_BOOTP:
+		ifo->options |= DHCPCD_BOOTP;
+		break;
 	default:
 		return 0;
 	}
@@ -2033,6 +2044,7 @@ read_config(struct dhcpcd_ctx *ctx,
 {
 	struct if_options *ifo;
 	FILE *fp;
+	struct stat sb;
 	char *line, *buf, *option, *p;
 	size_t buflen;
 	ssize_t vlen;
@@ -2189,6 +2201,8 @@ read_config(struct dhcpcd_ctx *ctx,
 		free(buf);
 		return ifo;
 	}
+	if (stat(ctx->cffile, &sb) == 0)
+		ifo->mtime = sb.st_mtime;
 
 	ldop = edop = NULL;
 	while ((line = get_line(&buf, &buflen, fp))) {
Index: src/external/bsd/dhcpcd/dist/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.22 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.23
--- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.22	Sat Mar 28 14:16:52 2015
+++ src/external/bsd/dhcpcd/dist/ipv6nd.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6nd.c,v 1.22 2015/03/28 14:16:52 christos Exp $");
+ __RCSID("$NetBSD: ipv6nd.c,v 1.23 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -57,9 +57,6 @@
 /* Debugging Router Solicitations is a lot of spam, so disable it */
 //#define DEBUG_RS
 
-#define RTR_SOLICITATION_INTERVAL       4 /* seconds */
-#define MAX_RTR_SOLICITATIONS           3 /* times */
-
 #ifndef ND_OPT_RDNSS
 #define ND_OPT_RDNSS			25
 struct nd_opt_rdnss {           /* RDNSS option RFC 6106 */
@@ -298,7 +295,7 @@ ipv6nd_sendrsprobe(void *arg)
 	cm->cmsg_type = IPV6_PKTINFO;
 	cm->cmsg_len = CMSG_LEN(sizeof(pi));
 	memset(&pi, 0, sizeof(pi));
-	pi.ipi6_ifindex = CAST_IPI6_IFINDEX(ifp->index);
+	pi.ipi6_ifindex = ifp->index;
 	memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
 
 	logger(ifp->ctx, LOG_DEBUG,
@@ -314,9 +311,48 @@ ipv6nd_sendrsprobe(void *arg)
 	if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
 		eloop_timeout_add_sec(ifp->ctx->eloop,
 		    RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
-	else
+	else {
 		logger(ifp->ctx, LOG_WARNING,
 		    "%s: no IPv6 Routers available", ifp->name);
+		ipv6nd_drop(ifp);
+		dhcp6_drop(ifp, "EXPIRE6");
+	}
+}
+
+void
+ipv6nd_expire(struct interface *ifp, uint32_t seconds)
+{
+	struct ra *rap;
+	struct timespec now;
+
+	get_monotonic(&now);
+
+	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
+		if (rap->iface == ifp) {
+			rap->received = now;
+			rap->expired = seconds ? 0 : 1;
+			if (seconds) {
+				struct ra_opt *rao;
+				struct ipv6_addr *ap;
+
+				rap->lifetime = seconds;
+				TAILQ_FOREACH(ap, &rap->addrs, next) {
+					if (ap->prefix_vltime) {
+						ap->prefix_vltime = seconds;
+						ap->prefix_pltime = seconds / 2;
+					}
+				}
+				ipv6_addaddrs(&rap->addrs);
+				TAILQ_FOREACH(rao, &rap->options, next) {
+					timespecclear(&rao->expire);
+				}
+			}
+		}
+	}
+	if (seconds)
+		ipv6nd_expirera(ifp);
+	else
+		ipv6_buildroutes(ifp->ctx);
 }
 
 static void
@@ -410,7 +446,6 @@ void ipv6nd_freedrop_ra(struct ra *rap, 
 	ipv6nd_free_opts(rap);
 	free(rap->data);
 	free(rap);
-
 }
 
 ssize_t
@@ -676,6 +711,19 @@ try_script:
 	}
 }
 
+static int
+ipv6nd_ra_has_public_addr(const struct ra *rap)
+{
+	const struct ipv6_addr *ia;
+
+	TAILQ_FOREACH(ia, &rap->addrs, next) {
+		if (ia->flags & IPV6_AF_AUTOCONF &&
+		    ipv6_publicaddr(ia))
+			return 1;
+	}
+	return 0;
+}
+
 static void
 ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
     struct icmp6_hdr *icp, size_t len)
@@ -763,6 +811,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		if (rap) {
 			free(rap->data);
 			rap->data_len = 0;
+			rap->no_public_warned = 0;
 		}
 		new_data = 1;
 	} else
@@ -836,7 +885,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		}
 		if (olen > len) {
 			logger(ifp->ctx, LOG_ERR,
-			    "%s: Option length exceeds message", ifp->name);
+			    "%s: option length exceeds message", ifp->name);
 			break;
 		}
 
@@ -1061,8 +1110,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 						    STRING | ARRAY | DOMAIN,
 						    (const uint8_t *)tmp, l);
 					} else
-						logger(ifp->ctx, LOG_ERR, "%s: %m",
-						    __func__);
+						logger(ifp->ctx, LOG_ERR,
+						    "%s: %m", __func__);
 					free(tmp);
 				}
 			}
@@ -1123,6 +1172,19 @@ extra_opt:
 
 	if (new_rap)
 		add_router(ifp->ctx->ipv6, rap);
+	if (!ipv6nd_ra_has_public_addr(rap) &&
+	    !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
+	    (!(rap->flags & ND_RA_FLAG_MANAGED) ||
+	    !dhcp6_has_public_addr(rap->iface)))
+	{
+		logger(rap->iface->ctx,
+		    rap->no_public_warned ? LOG_DEBUG : LOG_WARNING,
+		    "%s: ignoring RA from %s"
+		    " (no public prefix, no managed address)",
+		    rap->iface->name, rap->sfrom);
+		rap->no_public_warned = 1;
+		return;
+	}
 	if (ifp->ctx->options & DHCPCD_TEST) {
 		script_runreason(ifp, "TEST");
 		goto handle_flag;
@@ -1170,6 +1232,34 @@ nodhcp6:
 	ipv6nd_expirera(ifp);
 }
 
+/* Run RA's we ignored becuase they had no public addresses
+ * This should only be called when DHCPv6 applies a public address */
+void
+ipv6nd_runignoredra(struct interface *ifp)
+{
+	struct ra *rap;
+
+	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
+		if (rap->iface == ifp &&
+		    !rap->expired &&
+		    rap->no_public_warned)
+		{
+			rap->no_public_warned = 0;
+			logger(rap->iface->ctx, LOG_INFO,
+			    "%s: applying ignored RA from %s",
+			    rap->iface->name, rap->sfrom);
+			if (ifp->ctx->options & DHCPCD_TEST) {
+				script_runreason(ifp, "TEST");
+				continue;
+			}
+			if (ipv6nd_scriptrun(rap))
+				return;
+			eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+			eloop_timeout_delete(ifp->ctx->eloop, NULL, rap);
+		}
+	}
+}
+
 int
 ipv6nd_hasra(const struct interface *ifp)
 {
@@ -1336,13 +1426,14 @@ ipv6nd_expirera(void *arg)
 	struct ra *rap, *ran;
 	struct ra_opt *rao, *raon;
 	struct timespec now, lt, expire, next;
-	int expired, valid;
+	uint8_t expired, valid, validone;
 
 	ifp = arg;
 	get_monotonic(&now);
 	expired = 0;
 	timespecclear(&next);
 
+	validone = 0;
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) {
 		if (rap->iface != ifp)
 			continue;
@@ -1358,6 +1449,7 @@ ipv6nd_expirera(void *arg)
 					    "%s: %s: router expired",
 					    ifp->name, rap->sfrom);
 					rap->expired = expired = 1;
+					rap->lifetime = 0;
 				}
 			} else {
 				valid = 1;
@@ -1410,6 +1502,8 @@ ipv6nd_expirera(void *arg)
 		 * as well punt it. */
 		if (!valid && TAILQ_FIRST(&rap->addrs) == NULL)
 			ipv6nd_free_ra(rap);
+		else
+			validone = 1;
 	}
 
 	if (timespecisset(&next))
@@ -1419,13 +1513,17 @@ ipv6nd_expirera(void *arg)
 		ipv6_buildroutes(ifp->ctx);
 		script_runreason(ifp, "ROUTERADVERT");
 	}
+
+	/* No valid routers? Kill any DHCPv6. */
+	if (!validone)
+		dhcp6_drop(ifp, "EXPIRE6");
 }
 
 void
 ipv6nd_drop(struct interface *ifp)
 {
 	struct ra *rap;
-	int expired = 0;
+	uint8_t expired = 0;
 	TAILQ_HEAD(rahead, ra) rtrs;
 
 	if (ifp->ctx->ipv6 == NULL)

Index: src/external/bsd/dhcpcd/dist/if.c
diff -u src/external/bsd/dhcpcd/dist/if.c:1.12 src/external/bsd/dhcpcd/dist/if.c:1.13
--- src/external/bsd/dhcpcd/dist/if.c:1.12	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/if.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if.c,v 1.12 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: if.c,v 1.13 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -163,6 +163,67 @@ if_hasconf(struct dhcpcd_ctx *ctx, const
 	return 0;
 }
 
+static void if_learnaddrs1(struct dhcpcd_ctx *ctx, struct if_head *ifs,
+    struct ifaddrs *ifaddrs)
+{
+	struct ifaddrs *ifa;
+	struct interface *ifp;
+#ifdef INET
+	const struct sockaddr_in *addr, *net, *dst;
+#endif
+#ifdef INET6
+	struct sockaddr_in6 *sin6, *net6;
+#endif
+	int ifa_flags;
+
+
+	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+		if (ifa->ifa_addr == NULL)
+			continue;
+		if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL)
+			continue;
+		switch(ifa->ifa_addr->sa_family) {
+#ifdef INET
+		case AF_INET:
+			addr = (const struct sockaddr_in *)
+			    (void *)ifa->ifa_addr;
+			net = (const struct sockaddr_in *)
+			    (void *)ifa->ifa_netmask;
+			if (ifa->ifa_flags & IFF_POINTOPOINT)
+				dst = (const struct sockaddr_in *)
+				    (void *)ifa->ifa_dstaddr;
+			else
+				dst = NULL;
+			ifa_flags = if_addrflags(&addr->sin_addr, ifp);
+			ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
+				&addr->sin_addr,
+				&net->sin_addr,
+				dst ? &dst->sin_addr : NULL, ifa_flags);
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
+			net6 = (struct sockaddr_in6 *)(void *)ifa->ifa_netmask;
+#ifdef __KAME__
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+				/* Remove the scope from the address */
+				sin6->sin6_addr.s6_addr[2] =
+				    sin6->sin6_addr.s6_addr[3] = '\0';
+#endif
+			ifa_flags = if_addrflags6(&sin6->sin6_addr, ifp);
+			if (ifa_flags != -1)
+				ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
+				    ifa->ifa_name,
+				    &sin6->sin6_addr,
+				    ipv6_prefixlen(&net6->sin6_addr),
+				    ifa_flags);
+			break;
+#endif
+		}
+	}
+}
+
 struct if_head *
 if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
 {
@@ -174,15 +235,6 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 #ifdef __linux__
 	char ifn[IF_NAMESIZE];
 #endif
-#ifdef INET
-	const struct sockaddr_in *addr;
-	const struct sockaddr_in *net;
-	const struct sockaddr_in *dst;
-#endif
-#ifdef INET6
-	struct sockaddr_in6 *sin6, *net6;
-	int ifa_flags;
-#endif
 #ifdef AF_LINK
 	const struct sockaddr_dl *sdl;
 #ifdef SIOCGIFPRIORITY
@@ -478,55 +530,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
-	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
-		if (ifa->ifa_addr == NULL)
-			continue;
-		switch(ifa->ifa_addr->sa_family) {
-#ifdef INET
-		case AF_INET:
-			addr = (const struct sockaddr_in *)
-			    (void *)ifa->ifa_addr;
-			net = (const struct sockaddr_in *)
-			    (void *)ifa->ifa_netmask;
-			if (ifa->ifa_flags & IFF_POINTOPOINT)
-				dst = (const struct sockaddr_in *)
-				    (void *)ifa->ifa_dstaddr;
-			else
-				dst = NULL;
-			ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
-				&addr->sin_addr,
-				&net->sin_addr,
-				dst ? &dst->sin_addr : NULL);
-			break;
-#endif
-#ifdef INET6
-		case AF_INET6:
-			TAILQ_FOREACH(ifp, ifs, next) {
-				if (strcmp(ifp->name, ifa->ifa_name) == 0)
-					break;
-			}
-			if (ifp == NULL)
-				break; /* Should be impossible */
-			sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
-			net6 = (struct sockaddr_in6 *)(void *)ifa->ifa_netmask;
-#ifdef __KAME__
-			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
-				/* Remove the scope from the address */
-				sin6->sin6_addr.s6_addr[2] =
-				    sin6->sin6_addr.s6_addr[3] = '\0';
-#endif
-			ifa_flags = if_addrflags6(&sin6->sin6_addr, ifp);
-			if (ifa_flags != -1)
-				ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
-				    ifa->ifa_name,
-				    &sin6->sin6_addr,
-				    ipv6_prefixlen(&net6->sin6_addr),
-				    ifa_flags);
-			break;
-#endif
-		}
-	}
-
+	if_learnaddrs1(ctx, ifs, ifaddrs);
 	freeifaddrs(ifaddrs);
 
 #ifdef SIOCGIFPRIORITY
@@ -540,12 +544,13 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 }
 
 static struct interface *
-if_findindexname(struct dhcpcd_ctx *ctx, unsigned int idx, const char *name)
+if_findindexname(struct if_head *ifaces, unsigned int idx, const char *name)
 {
-	struct interface *ifp;
 
-	if (ctx != NULL && ctx->ifaces != NULL) {
-		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+	if (ifaces != NULL) {
+		struct interface *ifp;
+
+		TAILQ_FOREACH(ifp, ifaces, next) {
 			if ((ifp->options == NULL ||
 			    !(ifp->options->options & DHCPCD_PFXDLGONLY)) &&
 			    ((name && strcmp(ifp->name, name) == 0) ||
@@ -556,21 +561,23 @@ if_findindexname(struct dhcpcd_ctx *ctx,
 				return ifp;
 		}
 	}
+
+	errno = ESRCH;
 	return NULL;
 }
 
 struct interface *
-if_find(struct dhcpcd_ctx *ctx, const char *name)
+if_find(struct if_head *ifaces, const char *name)
 {
 
-	return if_findindexname(ctx, 0, name);
+	return if_findindexname(ifaces, 0, name);
 }
 
 struct interface *
-if_findindex(struct dhcpcd_ctx *ctx, unsigned int idx)
+if_findindex(struct if_head *ifaces, unsigned int idx)
 {
 
-	return if_findindexname(ctx, idx, NULL);
+	return if_findindexname(ifaces, idx, NULL);
 }
 
 int
@@ -607,6 +614,12 @@ if_cmp(const struct interface *si, const
 	    !(ti->options->options & DHCPCD_PFXDLGONLY))
 		return 1;
 
+	/* Check carrier status first */
+	if (si->carrier > ti->carrier)
+		return -1;
+	if (si->carrier < ti->carrier)
+		return 1;
+
 	if (D_STATE_RUNNING(si) && !D_STATE_RUNNING(ti))
 		return -1;
 	if (!D_STATE_RUNNING(si) && D_STATE_RUNNING(ti))
@@ -621,16 +634,11 @@ if_cmp(const struct interface *si, const
 		return 1;
 
 #ifdef INET
-	/* Special attention needed hereto due take states and IPv4LL. */
+	/* Special attention needed here due to states and IPv4LL. */
 	if ((r = ipv4_ifcmp(si, ti)) != 0)
 		return r;
 #endif
 
-	/* Then carrier status. */
-	if (si->carrier > ti->carrier)
-		return -1;
-	if (si->carrier < ti->carrier)
-		return 1;
 	/* Finally, metric */
 	if (si->metric < ti->metric)
 		return -1;

Index: src/external/bsd/dhcpcd/dist/ipv4.c
diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.13 src/external/bsd/dhcpcd/dist/ipv4.c:1.14
--- src/external/bsd/dhcpcd/dist/ipv4.c:1.13	Fri Mar 27 11:33:46 2015
+++ src/external/bsd/dhcpcd/dist/ipv4.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4.c,v 1.13 2015/03/27 11:33:46 roy Exp $");
+ __RCSID("$NetBSD: ipv4.c,v 1.14 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -255,8 +255,8 @@ find_route(struct rt_head *rts, const st
 	TAILQ_FOREACH(rt, rts, next) {
 		if (rt->dest.s_addr == r->dest.s_addr &&
 #ifdef HAVE_ROUTE_METRIC
-		    (srt || (!rt->iface ||
-			rt->iface->metric == r->iface->metric)) &&
+		    (srt || (r->iface == NULL || rt->iface == NULL ||
+		    rt->iface->metric == r->iface->metric)) &&
 #endif
                     (!srt || srt != rt) &&
 		    rt->net.s_addr == r->net.s_addr)
@@ -273,18 +273,18 @@ desc_route(const char *cmd, const struct
 	const char *ifname = rt->iface ? rt->iface->name : NULL;
 
 	strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr));
-	if (rt->gate.s_addr == INADDR_ANY)
-		logger(ctx, LOG_INFO, "%s: %s route to %s/%d",
-		    ifname, cmd, addr, inet_ntocidr(rt->net));
-	else if (rt->gate.s_addr == rt->dest.s_addr &&
-	    rt->net.s_addr == INADDR_BROADCAST)
+	if (rt->net.s_addr == htonl(INADDR_BROADCAST) &&
+	    rt->gate.s_addr == htonl(INADDR_ANY))
 		logger(ctx, LOG_INFO, "%s: %s host route to %s",
 		    ifname, cmd, addr);
-	else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
-	    rt->net.s_addr == INADDR_BROADCAST)
+	else if (rt->net.s_addr == htonl(INADDR_BROADCAST))
 		logger(ctx, LOG_INFO, "%s: %s host route to %s via %s",
 		    ifname, cmd, addr, inet_ntoa(rt->gate));
-	else if (rt->dest.s_addr == INADDR_ANY && rt->net.s_addr == INADDR_ANY)
+	else if (rt->gate.s_addr == htonl(INADDR_ANY))
+		logger(ctx, LOG_INFO, "%s: %s route to %s/%d",
+		    ifname, cmd, addr, inet_ntocidr(rt->net));
+	else if (rt->dest.s_addr == htonl(INADDR_ANY) &&
+	    rt->net.s_addr == htonl(INADDR_ANY))
 		logger(ctx, LOG_INFO, "%s: %s default route via %s",
 		    ifname, cmd, inet_ntoa(rt->gate));
 	else
@@ -335,12 +335,6 @@ ipv4_handlert(struct dhcpcd_ctx *ctx, in
 	if (ctx->ipv4_kroutes == NULL)
 		return 0;
 
-	/* DHCP host routes have a gateway of the destination.
-	 * We need to emulate that */
-	if (rt->gate.s_addr == INADDR_ANY &&
-	    rt->net.s_addr == INADDR_BROADCAST)
-		rt->gate = rt->dest;
-
 	f = ipv4_findrt(ctx, rt, 1);
 	switch (cmd) {
 	case RTM_ADD:
@@ -443,38 +437,34 @@ d_route(struct rt *rt)
 	return retval;
 }
 
-static struct rt *
-make_subnet_route(const struct interface *ifp)
+static struct rt_head *
+add_subnet_route(struct rt_head *rt, const struct interface *ifp)
 {
 	const struct dhcp_state *s;
 	struct rt *r;
 
-	s = D_CSTATE(ifp);
-	if (s->net.s_addr == INADDR_BROADCAST ||
-	    s->net.s_addr == INADDR_ANY)
+	if (rt == NULL) /* earlier malloc failed */
 		return NULL;
 
-	r = malloc(sizeof(*r));
-	if (r == NULL) {
+	s = D_CSTATE(ifp);
+	/* Don't create a subnet route for these addresses */
+	if (s->net.s_addr == INADDR_ANY)
+		return rt;
+#ifndef BSD
+	/* BSD adds a route in this instance */
+	if (s->net.s_addr == INADDR_BROADCAST)
+		return rt;
+#endif
+
+	if ((r = malloc(sizeof(*r))) == NULL) {
 		logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+		ipv4_freeroutes(rt);
 		return NULL;
 	}
 	r->dest.s_addr = s->addr.s_addr & s->net.s_addr;
 	r->net.s_addr = s->net.s_addr;
 	r->gate.s_addr = INADDR_ANY;
-	return r;
-}
-
-static struct rt_head *
-add_subnet_route(struct rt_head *rt, const struct interface *ifp)
-{
-	struct rt *r;
 
-	if (rt == NULL) /* earlier malloc failed */
-		return NULL;
-
-	if ((r = make_subnet_route(ifp)) == NULL)
-		return NULL;
 	TAILQ_INSERT_HEAD(rt, r, next);
 	return rt;
 }
@@ -535,8 +525,8 @@ get_routes(struct interface *ifp)
 }
 
 /* Some DHCP servers add set host routes by setting the gateway
- * to the assinged IP address. This differs from our notion of a host route
- * where the gateway is the destination address, so we fix it. */
+ * to the assigned IP address or the destination address.
+ * We need to change this. */
 static struct rt_head *
 massage_host_routes(struct rt_head *rt, const struct interface *ifp)
 {
@@ -544,14 +534,18 @@ massage_host_routes(struct rt_head *rt, 
 
 	if (rt) {
 		TAILQ_FOREACH(r, rt, next) {
-			if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr &&
-			    r->net.s_addr == INADDR_BROADCAST)
-				r->gate.s_addr = r->dest.s_addr;
+			if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr ||
+			    r->gate.s_addr == r->dest.s_addr)
+			{
+				r->gate.s_addr = htonl(INADDR_ANY);
+				r->net.s_addr = htonl(INADDR_BROADCAST);
+			}
 		}
 	}
 	return rt;
 }
 
+
 static struct rt_head *
 add_destination_route(struct rt_head *rt, const struct interface *ifp)
 {
@@ -641,8 +635,8 @@ add_router_host_route(struct rt_head *rt
 			return NULL;
 		}
 		rtn->dest.s_addr = rtp->gate.s_addr;
-		rtn->net.s_addr = INADDR_BROADCAST;
-		rtn->gate.s_addr = rtp->gate.s_addr;
+		rtn->net.s_addr = htonl(INADDR_BROADCAST);
+		rtn->gate.s_addr = htonl(INADDR_ANY);
 		TAILQ_INSERT_BEFORE(rtp, rtn, next);
 	}
 	return rt;
@@ -729,32 +723,45 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
 	}
 
 	/* Remove old routes we used to manage */
-	TAILQ_FOREACH(rt, ctx->ipv4_routes, next) {
-		if (find_route(nrs, rt, NULL) == NULL &&
-		    (rt->iface->options->options &
-		    (DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
-		    (DHCPCD_EXITING | DHCPCD_PERSISTENT))
-			d_route(rt);
+	if (ctx->ipv4_routes) {
+		TAILQ_FOREACH(rt, ctx->ipv4_routes, next) {
+			if (find_route(nrs, rt, NULL) == NULL &&
+			    (rt->iface->options->options &
+			    (DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
+			    (DHCPCD_EXITING | DHCPCD_PERSISTENT))
+				d_route(rt);
+		}
 	}
 	ipv4_freeroutes(ctx->ipv4_routes);
 	ctx->ipv4_routes = nrs;
 }
 
-static int
-delete_address1(struct interface *ifp,
+int
+ipv4_deladdr(struct interface *ifp,
     const struct in_addr *addr, const struct in_addr *net)
 {
+	struct dhcp_state *dstate;
 	int r;
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
 
 	logger(ifp->ctx, LOG_DEBUG, "%s: deleting IP address %s/%d",
 	    ifp->name, inet_ntoa(*addr), inet_ntocidr(*net));
+
 	r = if_deladdress(ifp, addr, net);
 	if (r == -1 && errno != EADDRNOTAVAIL && errno != ENXIO &&
 	    errno != ENODEV)
 		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
 
+	dstate = D_STATE(ifp);
+	if (dstate->addr.s_addr == addr->s_addr &&
+	    dstate->net.s_addr == net->s_addr)
+	{
+		dstate->added = 0;
+		dstate->addr.s_addr = 0;
+		dstate->net.s_addr = 0;
+	}
+
 	state = IPV4_STATE(ifp);
 	TAILQ_FOREACH(ap, &state->addrs, next) {
 		if (ap->addr.s_addr == addr->s_addr &&
@@ -780,10 +787,7 @@ delete_address(struct interface *ifp)
 	if (ifo->options & DHCPCD_INFORM ||
 	    (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
 		return 0;
-	r = delete_address1(ifp, &state->addr, &state->net);
-	state->added = 0;
-	state->addr.s_addr = 0;
-	state->net.s_addr = 0;
+	r = ipv4_deladdr(ifp, &state->addr, &state->net);
 	return r;
 }
 
@@ -809,26 +813,82 @@ ipv4_getstate(struct interface *ifp)
 static int
 ipv4_addaddr(struct interface *ifp, const struct dhcp_lease *lease)
 {
-	int r;
+	struct ipv4_state *state;
+	struct ipv4_addr *ia;
 
+	if ((state = ipv4_getstate(ifp)) == NULL) {
+		logger(ifp->ctx, LOG_ERR, "%s: ipv4_getstate: %m", __func__);
+		return -1;
+	}
 	if (ifp->options->options & DHCPCD_NOALIAS) {
-		struct ipv4_state *state;
-		struct ipv4_addr *ap, *apn;
+		struct ipv4_addr *ian;
 
-		state = IPV4_STATE(ifp);
-		TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) {
-			if (ap->addr.s_addr != lease->addr.s_addr)
-				delete_address1(ifp, &ap->addr, &ap->net);
+		TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ian) {
+			if (ia->addr.s_addr != lease->addr.s_addr)
+				ipv4_deladdr(ifp, &ia->addr, &ia->net);
 		}
 	}
 
+	if ((ia = malloc(sizeof(*ia))) == NULL) {
+		logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+		return -1;
+	}
+
 	logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s/%d",
 	    ifp->name, inet_ntoa(lease->addr),
 	    inet_ntocidr(lease->net));
-	r = if_addaddress(ifp, &lease->addr, &lease->net, &lease->brd);
-	if (r == -1 && errno != EEXIST)
-		logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m", __func__);
-	return r;
+	if (if_addaddress(ifp, &lease->addr, &lease->net, &lease->brd) == -1) {
+		if (errno != EEXIST)
+			logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
+			    __func__);
+		free(ia);
+		return -1;
+	}
+
+	ia->iface = ifp;
+	ia->addr = lease->addr;
+	ia->net = lease->net;
+#ifdef IN_IFF_TENTATIVE
+	ia->addr_flags = IN_IFF_TENTATIVE;
+#endif
+	TAILQ_INSERT_TAIL(&state->addrs, ia, next);
+	return 0;
+}
+
+static void
+ipv4_finalisert(struct interface *ifp)
+{
+	const struct dhcp_state *state = D_CSTATE(ifp);
+
+	/* Find any freshly added routes, such as the subnet route.
+	 * We do this because we cannot rely on recieving the kernel
+	 * notification right now via our link socket. */
+	if_initrt(ifp);
+	ipv4_buildroutes(ifp->ctx);
+	script_runreason(ifp, state->reason);
+
+	dhcpcd_daemonise(ifp->ctx);
+}
+
+void
+ipv4_finaliseaddr(struct interface *ifp)
+{
+	struct dhcp_state *state = D_STATE(ifp);
+	struct dhcp_lease *lease;
+
+	lease = &state->lease;
+
+	/* Delete the old address if different */
+	if (state->addr.s_addr != lease->addr.s_addr &&
+	    state->addr.s_addr != 0 &&
+	    ipv4_iffindaddr(ifp, &lease->addr, NULL))
+		delete_address(ifp);
+
+	state->added = STATE_ADDED;
+	state->defend = 0;
+	state->addr.s_addr = lease->addr.s_addr;
+	state->net.s_addr = lease->net.s_addr;
+	ipv4_finalisert(ifp);
 }
 
 void
@@ -840,7 +900,6 @@ ipv4_applyaddr(void *arg)
 	struct dhcp_lease *lease;
 	struct if_options *ifo = ifp->options;
 	struct ipv4_addr *ap;
-	struct ipv4_state *istate = NULL;
 	int r;
 
 	if (state == NULL)
@@ -902,13 +961,13 @@ ipv4_applyaddr(void *arg)
 				    ifn->name);
 				state->addr.s_addr = lease->addr.s_addr;
 				state->net.s_addr = lease->net.s_addr;
-				goto routes;
+				ipv4_finalisert(ifp);
 			}
 			logger(ifp->ctx, LOG_INFO, "%s: preferring %s on %s",
 			    ifn->name,
 			    inet_ntoa(lease->addr),
 			    ifp->name);
-			delete_address1(ifn, &nstate->addr, &nstate->net);
+			ipv4_deladdr(ifn, &nstate->addr, &nstate->net);
 			nstate->added = 0;
 			break;
 		}
@@ -921,14 +980,14 @@ ipv4_applyaddr(void *arg)
 				continue;
 			ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
 			if (ap)
-				delete_address1(ifn, &ap->addr, &ap->net);
+				ipv4_deladdr(ifn, &ap->addr, &ap->net);
 		}
 	}
 
 	/* If the netmask is different, delete the addresss */
 	ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
 	if (ap && ap->net.s_addr != lease->net.s_addr)
-		delete_address1(ifp, &ap->addr, &ap->net);
+		ipv4_deladdr(ifp, &ap->addr, &ap->net);
 
 	if (ipv4_iffindaddr(ifp, &lease->addr, &lease->net))
 		logger(ifp->ctx, LOG_DEBUG,
@@ -939,40 +998,26 @@ ipv4_applyaddr(void *arg)
 		r = ipv4_addaddr(ifp, lease);
 		if (r == -1 && errno != EEXIST)
 			return;
-		istate = ipv4_getstate(ifp);
-		ap = malloc(sizeof(*ap));
-		ap->iface = ifp;
-		ap->addr = lease->addr;
-		ap->net = lease->net;
-		ap->dst.s_addr = INADDR_ANY;
-		TAILQ_INSERT_TAIL(&istate->addrs, ap, next);
 	}
 
-	/* Now delete the old address if different */
-	if (state->addr.s_addr != lease->addr.s_addr &&
-	    state->addr.s_addr != 0 &&
-	    ipv4_iffindaddr(ifp, &lease->addr, NULL))
-		delete_address(ifp);
-
-	state->added = STATE_ADDED;
-	state->defend = 0;
-	state->addr.s_addr = lease->addr.s_addr;
-	state->net.s_addr = lease->net.s_addr;
+#ifdef IN_IFF_NOTUSEABLE
+	ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+	if (ap == NULL) {
+		logger(ifp->ctx, LOG_ERR, "%s: added address vanished",
+		    ifp->name);
+		return;
+	} else if (ap->addr_flags & IN_IFF_NOTUSEABLE)
+		return;
+#endif
 
-routes:
-	/* Find any freshly added routes, such as the subnet route.
-	 * We do this because we cannot rely on recieving the kernel
-	 * notification right now via our link socket. */
-	if_initrt(ifp);
-	ipv4_buildroutes(ifp->ctx);
-	script_runreason(ifp, state->reason);
+	ipv4_finaliseaddr(ifp);
 }
 
 void
 ipv4_handleifa(struct dhcpcd_ctx *ctx,
-    int type, struct if_head *ifs, const char *ifname,
+    int cmd, struct if_head *ifs, const char *ifname,
     const struct in_addr *addr, const struct in_addr *net,
-    const struct in_addr *dst)
+    const struct in_addr *dst, int flags)
 {
 	struct interface *ifp;
 	struct ipv4_state *state;
@@ -988,44 +1033,39 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
 		errno = EINVAL;
 		return;
 	}
-
-	TAILQ_FOREACH(ifp, ifs, next) {
-		if (strcmp(ifp->name, ifname) == 0)
-			break;
-	}
-	if (ifp == NULL) {
-		errno = ESRCH;
+	if ((ifp = if_find(ifs, ifname)) == NULL)
 		return;
-	}
-	state = ipv4_getstate(ifp);
-	if (state == NULL) {
+	if ((state = ipv4_getstate(ifp)) == NULL) {
 		errno = ENOENT;
 		return;
 	}
 
 	ap = ipv4_iffindaddr(ifp, addr, net);
-	if (type == RTM_NEWADDR && ap == NULL) {
-		ap = malloc(sizeof(*ap));
+	if (cmd == RTM_NEWADDR) {
 		if (ap == NULL) {
-			logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
-			return;
+			if ((ap = malloc(sizeof(*ap))) == NULL) {
+				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+				return;
+			}
+			ap->iface = ifp;
+			ap->addr = *addr;
+			ap->net = *net;
+			if (dst)
+				ap->dst.s_addr = dst->s_addr;
+			else
+				ap->dst.s_addr = INADDR_ANY;
+			TAILQ_INSERT_TAIL(&state->addrs, ap, next);
+		}
+		ap->addr_flags = flags;
+	} else if (cmd == RTM_DELADDR) {
+		if (ap) {
+			TAILQ_REMOVE(&state->addrs, ap, next);
+			free(ap);
 		}
-		ap->iface = ifp;
-		ap->addr.s_addr = addr->s_addr;
-		ap->net.s_addr = net->s_addr;
-		if (dst)
-			ap->dst.s_addr = dst->s_addr;
-		else
-			ap->dst.s_addr = INADDR_ANY;
-		TAILQ_INSERT_TAIL(&state->addrs, ap, next);
-	} else if (type == RTM_DELADDR) {
-		if (ap == NULL)
-			return;
-		TAILQ_REMOVE(&state->addrs, ap, next);
-		free(ap);
 	}
 
-	dhcp_handleifa(type, ifp, addr, net, dst);
+	dhcp_handleifa(cmd, ifp, addr, net, dst, flags);
+	arp_handleifa(cmd, ifp, addr, flags);
 }
 
 void

Index: src/external/bsd/dhcpcd/dist/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.10 src/external/bsd/dhcpcd/dist/ipv6.c:1.11
--- src/external/bsd/dhcpcd/dist/ipv6.c:1.10	Fri Mar 27 11:33:46 2015
+++ src/external/bsd/dhcpcd/dist/ipv6.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6.c,v 1.10 2015/03/27 11:33:46 roy Exp $");
+ __RCSID("$NetBSD: ipv6.c,v 1.11 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -748,6 +748,14 @@ ipv6_addaddr(struct ipv6_addr *ap, const
 	return 0;
 }
 
+int
+ipv6_publicaddr(const struct ipv6_addr *ia)
+{
+	return (ia->prefix_pltime &&
+	    (ia->addr.s6_addr[0] & 0xfe) != 0xc &&
+	    !(ia->addr_flags & IN6_IFF_NOTUSEABLE));
+}
+
 struct ipv6_addr *
 ipv6_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr, short flags)
 {
@@ -1963,7 +1971,7 @@ static void
 ipv6_build_ra_routes(struct ipv6_ctx *ctx, struct rt6_head *dnr, int expired)
 {
 	struct rt6 *rt;
-	const struct ra *rap;
+	struct ra *rap;
 	const struct ipv6_addr *addr;
 
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
@@ -1977,7 +1985,8 @@ ipv6_build_ra_routes(struct ipv6_ctx *ct
 			}
 		}
 		if (rap->lifetime && rap->iface->options->options &
-		    (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT))
+		    (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT) &&
+		    !rap->no_public_warned)
 		{
 			rt = make_router(rap);
 			if (rt)
Index: src/external/bsd/dhcpcd/dist/ipv6nd.h
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.h:1.10 src/external/bsd/dhcpcd/dist/ipv6nd.h:1.11
--- src/external/bsd/dhcpcd/dist/ipv6nd.h:1.10	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6nd.h	Sat May  2 15:18:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6nd.h,v 1.10 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: ipv6nd.h,v 1.11 2015/05/02 15:18:37 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -58,7 +58,8 @@ struct ra {
 	uint32_t mtu;
 	struct ipv6_addrhead addrs;
 	TAILQ_HEAD(, ra_opt) options;
-	int expired;
+	uint8_t expired;
+	uint8_t no_public_warned;
 };
 
 TAILQ_HEAD(ra_head, ra);
@@ -74,6 +75,14 @@ struct rs_state {
 
 #define MAX_RTR_SOLICITATION_DELAY	1	/* seconds */
 #define MAX_UNICAST_SOLICIT		3	/* 3 transmissions */
+#define RTR_SOLICITATION_INTERVAL	4	/* seconds */
+#define MAX_RTR_SOLICITATIONS		3	/* times */
+
+/* On carrier up, expire known routers after RTR_CARRIER_EXPIRE seconds. */
+#define RTR_CARRIER_EXPIRE		\
+    (MAX_RTR_SOLICITATION_DELAY +	\
+    (MAX_RTR_SOLICITATIONS + 1) *	\
+    RTR_SOLICITATION_INTERVAL)
 
 #define MAX_REACHABLE_TIME		3600000	/* milliseconds */
 #define REACHABLE_TIME			30000	/* milliseconds */
@@ -95,9 +104,11 @@ ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
 int ipv6nd_hasra(const struct interface *);
 int ipv6nd_hasradhcp(const struct interface *);
+void ipv6nd_runignoredra(struct interface *);
 void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
     const char *, const struct in6_addr *, int);
 int ipv6nd_dadcompleted(const struct interface *);
+void ipv6nd_expire(struct interface *, uint32_t);
 void ipv6nd_drop(struct interface *);
 void ipv6nd_neighbour(struct dhcpcd_ctx *, struct in6_addr *, int);
 #else

Index: src/external/bsd/dhcpcd/dist/script.c
diff -u src/external/bsd/dhcpcd/dist/script.c:1.18 src/external/bsd/dhcpcd/dist/script.c:1.19
--- src/external/bsd/dhcpcd/dist/script.c:1.18	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/script.c	Sat May  2 15:18:37 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: script.c,v 1.18 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: script.c,v 1.19 2015/05/02 15:18:37 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -89,14 +89,8 @@ if_printoptions(void)
 		printf(" -  %s\n", *p);
 }
 
-#ifdef USE_SIGNALS
-#define U
-#else
-#define U __unused
-#endif
 static int
-exec_script(U const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
-#undef U
+exec_script(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
 {
 	pid_t pid;
 	posix_spawnattr_t attr;
@@ -104,6 +98,8 @@ exec_script(U const struct dhcpcd_ctx *c
 #ifdef USE_SIGNALS
 	short flags;
 	sigset_t defsigs;
+#else
+	UNUSED(ctx);
 #endif
 
 	/* posix_spawn is a safe way of executing another image

Reply via email to