Module Name:    src
Committed By:   roy
Date:           Fri Jun 17 19:42:32 UTC 2016

Modified Files:
        src/external/bsd/dhcpcd/dist: arp.c arp.h bpf-filter.h defs.h
            dhcp-common.c dhcp.c dhcp.h dhcp6.c dhcp6.h dhcpcd.c
            dhcpcd.conf.5.in dhcpcd.h if-bsd.c if-options.c if.c if.h ipv4.c
            ipv4.h ipv4ll.c ipv4ll.h ipv6.c ipv6.h ipv6nd.c script.c
        src/external/bsd/dhcpcd/dist/dhcpcd-hooks: 20-resolv.conf 30-hostname

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/arp.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/arp.h \
    src/external/bsd/dhcpcd/dist/dhcp6.h
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/bpf-filter.h
cvs rdiff -u -r1.27 -r1.28 src/external/bsd/dhcpcd/dist/defs.h \
    src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/dhcp-common.c \
    src/external/bsd/dhcpcd/dist/dhcpcd.h src/external/bsd/dhcpcd/dist/ipv4.h
cvs rdiff -u -r1.42 -r1.43 src/external/bsd/dhcpcd/dist/dhcp.c
cvs rdiff -u -r1.16 -r1.17 src/external/bsd/dhcpcd/dist/dhcp.h \
    src/external/bsd/dhcpcd/dist/if.h src/external/bsd/dhcpcd/dist/ipv4ll.c
cvs rdiff -u -r1.21 -r1.22 src/external/bsd/dhcpcd/dist/dhcp6.c \
    src/external/bsd/dhcpcd/dist/if.c
cvs rdiff -u -r1.34 -r1.35 src/external/bsd/dhcpcd/dist/dhcpcd.c
cvs rdiff -u -r1.30 -r1.31 src/external/bsd/dhcpcd/dist/if-bsd.c
cvs rdiff -u -r1.33 -r1.34 src/external/bsd/dhcpcd/dist/if-options.c
cvs rdiff -u -r1.22 -r1.23 src/external/bsd/dhcpcd/dist/ipv4.c
cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/ipv4ll.h
cvs rdiff -u -r1.18 -r1.19 src/external/bsd/dhcpcd/dist/ipv6.c \
    src/external/bsd/dhcpcd/dist/ipv6.h
cvs rdiff -u -r1.29 -r1.30 src/external/bsd/dhcpcd/dist/ipv6nd.c
cvs rdiff -u -r1.26 -r1.27 src/external/bsd/dhcpcd/dist/script.c
cvs rdiff -u -r1.8 -r1.9 \
    src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf
cvs rdiff -u -r1.7 -r1.8 \
    src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname

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.19 src/external/bsd/dhcpcd/dist/arp.c:1.20
--- src/external/bsd/dhcpcd/dist/arp.c:1.19	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/arp.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: arp.c,v 1.19 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: arp.c,v 1.20 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -65,6 +65,7 @@ arp_request(const struct interface *ifp,
 	struct arphdr ar;
 	size_t len;
 	uint8_t *p;
+	const struct iarp_state *state;
 
 	ar.ar_hrd = htons(ifp->family);
 	ar.ar_pro = htons(ETHERTYPE_IP);
@@ -91,7 +92,9 @@ arp_request(const struct interface *ifp,
 	APPEND(&sip, sizeof(sip));
 	ZERO(ifp->hwlen);
 	APPEND(&tip, sizeof(tip));
-	return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
+
+	state = ARP_CSTATE(ifp);
+	return if_sendraw(ifp, state->fd, ETHERTYPE_ARP, arp_buffer, len);
 
 eexit:
 	errno = ENOBUFS;
@@ -123,7 +126,7 @@ arp_packet(void *arg)
 {
 	struct interface *ifp = arg;
 	const struct interface *ifn;
-	uint8_t arp_buffer[ARP_LEN];
+	uint8_t buf[ARP_LEN];
 	struct arphdr ar;
 	struct arp_msg arm;
 	ssize_t bytes;
@@ -134,65 +137,62 @@ arp_packet(void *arg)
 
 	state = ARP_STATE(ifp);
 	flags = 0;
-	while (!(flags & RAW_EOF)) {
-		bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
-		    arp_buffer, sizeof(arp_buffer), &flags);
-		if (bytes == -1) {
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: arp if_readrawpacket: %m", ifp->name);
-			arp_close(ifp);
-			return;
-		}
-		/* We must have a full ARP header */
-		if ((size_t)bytes < sizeof(ar))
-			continue;
-		memcpy(&ar, arp_buffer, sizeof(ar));
-		/* Families must match */
-		if (ar.ar_hrd != htons(ifp->family))
-			continue;
+	bytes = if_readraw(ifp, state->fd, buf, sizeof(buf), &flags);
+	if (bytes == -1) {
+		logger(ifp->ctx, LOG_ERR,
+		    "%s: arp if_readrawpacket: %m", ifp->name);
+		arp_close(ifp);
+		return;
+	}
+	/* We must have a full ARP header */
+	if ((size_t)bytes < sizeof(ar))
+		return;
+	memcpy(&ar, buf, sizeof(ar));
+	/* Families must match */
+	if (ar.ar_hrd != htons(ifp->family))
+		return;
 #if 0
-		/* These checks are enforced in the BPF filter. */
-		/* Protocol must be IP. */
-		if (ar.ar_pro != htons(ETHERTYPE_IP))
-			continue;
-		/* Only these types are recognised */
-		if (ar.ar_op != htons(ARPOP_REPLY) &&
-		    ar.ar_op != htons(ARPOP_REQUEST))
-			continue;
+	/* These checks are enforced in the BPF filter. */
+	/* Protocol must be IP. */
+	if (ar.ar_pro != htons(ETHERTYPE_IP))
+		continue;
+	/* Only these types are recognised */
+	if (ar.ar_op != htons(ARPOP_REPLY) &&
+	    ar.ar_op != htons(ARPOP_REQUEST))
+		continue;
 #endif
-		if (ar.ar_pln != sizeof(arm.sip.s_addr))
-			continue;
+	if (ar.ar_pln != sizeof(arm.sip.s_addr))
+		return;
 
-		/* Get pointers to the hardware addreses */
-		hw_s = arp_buffer + sizeof(ar);
-		hw_t = hw_s + ar.ar_hln + ar.ar_pln;
-		/* Ensure we got all the data */
-		if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
-			continue;
-		/* Ignore messages from ourself */
-		TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
-			if (ar.ar_hln == ifn->hwlen &&
-			    memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
-				break;
-		}
-		if (ifn) {
+	/* Get pointers to the hardware addreses */
+	hw_s = buf + sizeof(ar);
+	hw_t = hw_s + ar.ar_hln + ar.ar_pln;
+	/* Ensure we got all the data */
+	if ((hw_t + ar.ar_hln + ar.ar_pln) - buf > bytes)
+		return;
+	/* Ignore messages from ourself */
+	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
+		if (ar.ar_hln == ifn->hwlen &&
+		    memcmp(hw_s, ifn->hwaddr, ifn->hwlen) == 0)
+			break;
+	}
+	if (ifn) {
 #if 0
-			logger(ifp->ctx, LOG_DEBUG,
-			    "%s: ignoring ARP from self", ifp->name);
+		logger(ifp->ctx, LOG_DEBUG,
+		    "%s: ignoring ARP from self", ifp->name);
 #endif
-			continue;
-		}
-		/* Copy out the HW and IP addresses */
-		memcpy(&arm.sha, hw_s, ar.ar_hln);
-		memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
-		memcpy(&arm.tha, hw_t, ar.ar_hln);
-		memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
-
-		/* Run the conflicts */
-		TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
-			if (astate->conflicted_cb)
-				astate->conflicted_cb(astate, &arm);
-		}
+		return;
+	}
+	/* Copy out the HW and IP addresses */
+	memcpy(&arm.sha, hw_s, ar.ar_hln);
+	memcpy(&arm.sip.s_addr, hw_s + ar.ar_hln, ar.ar_pln);
+	memcpy(&arm.tha, hw_t, ar.ar_hln);
+	memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
+
+	/* Run the conflicts */
+	TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
+		if (astate->conflicted_cb)
+			astate->conflicted_cb(astate, &arm);
 	}
 }
 
@@ -203,7 +203,7 @@ arp_open(struct interface *ifp)
 
 	state = ARP_STATE(ifp);
 	if (state->fd == -1) {
-		state->fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
+		state->fd = if_openraw(ifp, ETHERTYPE_ARP);
 		if (state->fd == -1) {
 			logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
 			    __func__, ifp->name);
@@ -391,7 +391,7 @@ arp_free(struct arp_state *astate)
 		    TAILQ_FIRST(&state->arp_states) == NULL)
 		{
 			eloop_event_delete(ifp->ctx->eloop, state->fd);
-			close(state->fd);
+			if_closeraw(ifp, state->fd);
 			free(state);
 			ifp->if_data[IF_DATA_ARP] = NULL;
 		}
@@ -428,22 +428,21 @@ arp_close(struct interface *ifp)
 }
 
 void
-arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
-    int flags)
+arp_handleifa(int cmd, struct ipv4_addr *addr)
 {
 #ifdef IN_IFF_DUPLICATED
 	struct iarp_state *state;
 	struct arp_state *astate, *asn;
 
-	if (cmd != RTM_NEWADDR || (state = ARP_STATE(ifp)) == NULL)
+	if (cmd != RTM_NEWADDR || (state = ARP_STATE(addr->iface)) == 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->addr.s_addr == addr->addr.s_addr) {
+			if (addr->addr_flags & IN_IFF_DUPLICATED) {
 				if (astate->conflicted_cb)
 					astate->conflicted_cb(astate, NULL);
-			} else if (!(flags & IN_IFF_NOTUSEABLE)) {
+			} else if (!(addr->addr_flags & IN_IFF_NOTUSEABLE)) {
 				if (astate->probed_cb)
 					astate->probed_cb(astate);
 			}
@@ -451,8 +450,6 @@ arp_handleifa(int cmd, struct interface 
 	}
 #else
 	UNUSED(cmd);
-	UNUSED(ifp);
 	UNUSED(addr);
-	UNUSED(flags);
 #endif
 }

Index: src/external/bsd/dhcpcd/dist/arp.h
diff -u src/external/bsd/dhcpcd/dist/arp.h:1.13 src/external/bsd/dhcpcd/dist/arp.h:1.14
--- src/external/bsd/dhcpcd/dist/arp.h:1.13	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/arp.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: arp.h,v 1.13 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: arp.h,v 1.14 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -43,6 +43,7 @@
 #define DEFEND_INTERVAL		10
 
 #include "dhcpcd.h"
+#include "if.h"
 
 struct arp_msg {
 	uint16_t op;
@@ -91,7 +92,7 @@ void arp_free_but(struct arp_state *);
 struct arp_state *arp_find(struct interface *, const struct in_addr *);
 void arp_close(struct interface *);
 
-void arp_handleifa(int, struct interface *, const struct in_addr *, int);
+void arp_handleifa(int, struct ipv4_addr *);
 #else
 #define arp_close(a) {}
 #endif
Index: src/external/bsd/dhcpcd/dist/dhcp6.h
diff -u src/external/bsd/dhcpcd/dist/dhcp6.h:1.13 src/external/bsd/dhcpcd/dist/dhcp6.h:1.14
--- src/external/bsd/dhcpcd/dist/dhcp6.h:1.13	Sun Apr 10 21:00:53 2016
+++ src/external/bsd/dhcpcd/dist/dhcp6.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp6.h,v 1.13 2016/04/10 21:00:53 roy Exp $ */
+/* $NetBSD: dhcp6.h,v 1.14 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -250,6 +250,7 @@ void dhcp6_handleifa(struct dhcpcd_ctx *
     const struct in6_addr *addr, int);
 int dhcp6_dadcompleted(const struct interface *);
 void dhcp6_drop(struct interface *, const char *);
+void dhcp6_dropnondelegates(struct interface *ifp);
 int dhcp6_dump(struct interface *);
 #else
 #define dhcp6_find_delegates(a) {}

Index: src/external/bsd/dhcpcd/dist/bpf-filter.h
diff -u src/external/bsd/dhcpcd/dist/bpf-filter.h:1.10 src/external/bsd/dhcpcd/dist/bpf-filter.h:1.11
--- src/external/bsd/dhcpcd/dist/bpf-filter.h:1.10	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/bpf-filter.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf-filter.h,v 1.10 2016/01/07 20:09:43 roy Exp $ */
+/* $NetBSD: bpf-filter.h,v 1.11 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -51,7 +51,7 @@ static const struct bpf_insn arp_bpf_fil
 	/* Otherwise, drop it. */
 	BPF_STMT(BPF_RET + BPF_K, 0),
 };
-#define arp_bpf_filter_len sizeof(arp_bpf_filter) / sizeof(arp_bpf_filter[0])
+#define arp_bpf_filter_len __arraycount(arp_bpf_filter)
 
 
 /* dhcp_bpf_filter taken from bpf.c in dhcp-3.1.0
@@ -78,7 +78,7 @@ static const struct bpf_insn arp_bpf_fil
  *   http://www.isc.org/
  */
 
-static const struct bpf_insn dhcp_bpf_filter [] = {
+static const struct bpf_insn bootp_bpf_filter [] = {
 #ifndef BPF_SKIPTYPE
 	/* Make sure this is an IP packet... */
 	BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
@@ -94,10 +94,10 @@ static const struct bpf_insn dhcp_bpf_fi
 	BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 + BPF_ETHCOOK),
 	/* Make sure it's to the right port... */
 	BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 + BPF_ETHCOOK),
-	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_CLIENT_PORT, 0, 1),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTPC, 0, 1),
 	/* If we passed all the tests, ask for the whole packet. */
 	BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET),
 	/* Otherwise, drop it. */
 	BPF_STMT(BPF_RET + BPF_K, 0),
 };
-#define dhcp_bpf_filter_len sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0])
+#define bootp_bpf_filter_len __arraycount(bootp_bpf_filter)

Index: src/external/bsd/dhcpcd/dist/defs.h
diff -u src/external/bsd/dhcpcd/dist/defs.h:1.27 src/external/bsd/dhcpcd/dist/defs.h:1.28
--- src/external/bsd/dhcpcd/dist/defs.h:1.27	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/defs.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: defs.h,v 1.27 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: defs.h,v 1.28 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,7 +30,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"6.11.0"
+#define VERSION			"6.11.1"
 
 #ifndef CONFIG
 # define CONFIG			SYSCONFDIR "/" PACKAGE ".conf"
Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.27 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.28
--- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.27	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.conf.5.in,v 1.27 2016/05/09 10:15:59 roy Exp $
+.\"     $NetBSD: dhcpcd.conf.5.in,v 1.28 2016/06/17 19:42:31 roy Exp $
 .\" Copyright (c) 2006-2016 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 April 21, 2016
+.Dd June 14, 2016
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -156,7 +156,7 @@ should use with
 .Ic env
 .Va wpa_supplicant_driver=nl80211
 .Pp
-If the hostname is set, will be will set to the FQDN if possible as per
+If the hostname is set, it will be will set to the FQDN if possible as per
 RFC 4702 section 3.1.
 If the FQDN option is missing,
 .Nm dhcpcd
@@ -262,14 +262,14 @@ You can use this option to stop this fro
 Fallback to using this profile if DHCP fails.
 This allows you to configure a static profile instead of using ZeroConf.
 .It Ic hostname Ar name
-Sends
-.Ar hostname
+Sends the hostname
+.Ar name
 to the DHCP server so it can be registered in DNS.
 If
-.Ar hostname
+.Ar name
 is an empty string then the current system hostname is sent.
 If
-.Ar hostname
+.Ar name
 is a FQDN (ie, contains a .) then it will be encoded as such.
 .It Ic hostname_short
 Sends the short hostname to the DHCP server instead of the FQDN.
@@ -523,6 +523,12 @@ to handle ND options, but this only work
 and
 .Ic require
 options.
+.Pp
+To see a list of options you can use, call
+.Nm dhcpcd
+with the
+.Fl V , Fl Fl variables
+argument.
 .It Ic nooption Ar option
 Remove the option from the message before it's processed.
 .It Ic require Ar option

Index: src/external/bsd/dhcpcd/dist/dhcp-common.c
diff -u src/external/bsd/dhcpcd/dist/dhcp-common.c:1.17 src/external/bsd/dhcpcd/dist/dhcp-common.c:1.18
--- src/external/bsd/dhcpcd/dist/dhcp-common.c:1.17	Wed Jun  8 01:33:08 2016
+++ src/external/bsd/dhcpcd/dist/dhcp-common.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp-common.c,v 1.17 2016/06/08 01:33:08 christos Exp $");
+ __RCSID("$NetBSD: dhcp-common.c,v 1.18 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -833,7 +833,7 @@ int
 dhcp_set_leasefile(char *leasefile, size_t len, int family,
     const struct interface *ifp)
 {
-	char ssid[1 + (IF_SSIDLEN * 4) + 1];
+	char ssid[1 + (IF_SSIDLEN * 4) + 1]; /* - prefix and NUL terminated. */
 
 	if (ifp->name[0] == '\0') {
 		strlcpy(leasefile, ifp->ctx->pidfile, len);
Index: src/external/bsd/dhcpcd/dist/dhcpcd.h
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.h:1.17 src/external/bsd/dhcpcd/dist/dhcpcd.h:1.18
--- src/external/bsd/dhcpcd/dist/dhcpcd.h:1.17	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/dhcpcd.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcpcd.h,v 1.17 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: dhcpcd.h,v 1.18 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -200,7 +200,7 @@ int dhcpcd_handleargs(struct dhcpcd_ctx 
 void dhcpcd_handlecarrier(struct dhcpcd_ctx *, int, unsigned int, const char *);
 int dhcpcd_handleinterface(void *, int, const char *);
 void dhcpcd_handlehwaddr(struct dhcpcd_ctx *, const char *,
-    const unsigned char *, uint8_t);
+    const void *, uint8_t);
 void dhcpcd_dropinterface(struct interface *, const char *);
 int dhcpcd_selectprofile(struct interface *, const char *);
 
Index: src/external/bsd/dhcpcd/dist/ipv4.h
diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.17 src/external/bsd/dhcpcd/dist/ipv4.h:1.18
--- src/external/bsd/dhcpcd/dist/ipv4.h:1.17	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/ipv4.h	Fri Jun 17 19:42:32 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv4.h,v 1.17 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: ipv4.h,v 1.18 2016/06/17 19:42:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -57,7 +57,7 @@
 struct rt {
 	TAILQ_ENTRY(rt) next;
 	struct in_addr dest;
-	struct in_addr net;
+	struct in_addr mask;
 	struct in_addr gate;
 	const struct interface *iface;
 #ifdef HAVE_ROUTE_METRIC
@@ -73,13 +73,20 @@ TAILQ_HEAD(rt_head, rt);
 struct ipv4_addr {
 	TAILQ_ENTRY(ipv4_addr) next;
 	struct in_addr addr;
-	struct in_addr net;
+	struct in_addr mask;
 	struct in_addr brd;
 	struct interface *iface;
 	int addr_flags;
+	char saddr[INET_ADDRSTRLEN + 3];
 };
 TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
 
+#define	IPV4_ADDR_EQ(a1, a2)	((a1) && (a1)->addr.s_addr == (a2)->addr.s_addr)
+#define	IPV4_MASK1_EQ(a1, a2)	((a1) && (a1)->mask.s_addr == (a2)->mask.s_addr)
+#define	IPV4_MASK_EQ(a1, a2)	(IPV4_ADDR_EQ(a1, a2) && IPV4_MASK1_EQ(a1, a2))
+#define	IPV4_BRD1_EQ(a1, a2)	((a1) && (a1)->brd.s_addr == (a2)->brd.s_addr)
+#define	IPV4_BRD_EQ(a1, a2)	(IPV4_MASK_EQ(a1, a2) && IPV4_BRD1_EQ(a1, a2))
+
 struct ipv4_state {
 	struct ipv4_addrhead addrs;
 	struct rt_head routes;
@@ -87,7 +94,7 @@ struct ipv4_state {
 #ifdef BSD
 	/* Buffer for BPF */
 	size_t buffer_size, buffer_len, buffer_pos;
-	uint8_t *buffer;
+	char *buffer;
 #endif
 };
 
@@ -99,7 +106,6 @@ struct ipv4_state {
 #ifdef INET
 struct ipv4_state *ipv4_getstate(struct interface *);
 int ipv4_init(struct dhcpcd_ctx *);
-int ipv4_protocol_fd(const struct interface *, uint16_t);
 int ipv4_ifcmp(const struct interface *, const struct interface *);
 uint8_t inet_ntocidr(struct in_addr);
 int inet_cidrtoaddr(int, struct in_addr *);
@@ -110,8 +116,7 @@ int ipv4_hasaddr(const struct interface 
 #define STATE_FAKE		0x02
 
 void ipv4_buildroutes(struct dhcpcd_ctx *);
-int ipv4_deladdr(struct interface *, const struct in_addr *,
-    const struct in_addr *, int);
+int ipv4_deladdr(struct ipv4_addr *, int);
 int ipv4_preferanother(struct interface *);
 struct ipv4_addr *ipv4_addaddr(struct interface *,
     const struct in_addr *, const struct in_addr *, const struct in_addr *);

Index: src/external/bsd/dhcpcd/dist/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.42 src/external/bsd/dhcpcd/dist/dhcp.c:1.43
--- src/external/bsd/dhcpcd/dist/dhcp.c:1.42	Thu May 26 09:09:47 2016
+++ src/external/bsd/dhcpcd/dist/dhcp.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp.c,v 1.42 2016/05/26 09:09:47 prlw1 Exp $");
+ __RCSID("$NetBSD: dhcp.c,v 1.43 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -434,7 +434,7 @@ decode_rfc3442_rt(struct dhcpcd_ctx *ctx
 		if (ocets > 0) {
 			memcpy(&rt->dest.s_addr, p, ocets);
 			p += ocets;
-			rt->net.s_addr = htonl(~0U << (32 - cidr));
+			rt->mask.s_addr = htonl(~0U << (32 - cidr));
 		}
 
 		/* Finally, snag the router */
@@ -629,9 +629,9 @@ get_option_routes(struct interface *ifp,
 			    route->gate.s_addr == bootp->yiaddr)
 			{
 				route->gate.s_addr = htonl(INADDR_ANY);
-				route->net.s_addr = htonl(INADDR_BROADCAST);
+				route->mask.s_addr = htonl(INADDR_BROADCAST);
 			} else
-				route->net.s_addr =
+				route->mask.s_addr =
 				    route_netmask(route->dest.s_addr);
 			TAILQ_INSERT_TAIL(routes, route, next);
 		}
@@ -671,7 +671,7 @@ dhcp_get_mtu(const struct interface *ifp
 	if ((state = D_CSTATE(ifp)) == NULL ||
 	    has_option_mask(ifp->options->nomask, DHO_MTU) ||
 	    get_option_uint16(ifp->ctx, &mtu,
-		    	      state->new, state->new_len, DHO_MTU) == -1)
+			      state->new, state->new_len, DHO_MTU) == -1)
 		return 0;
 	return mtu;
 }
@@ -763,18 +763,14 @@ make_message(struct bootp **bootpm, cons
 		return -1;
 	*bootpm = bootp;
 
-	if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
-	    (type == DHCP_REQUEST && state->net.s_addr == lease->net.s_addr &&
+	if (state->addr != NULL &&
+	    (type == DHCP_INFORM || type == DHCP_RELEASE ||
+	    (type == DHCP_REQUEST &&
+	    state->addr->mask.s_addr == lease->mask.s_addr &&
 	    (state->new == NULL || IS_DHCP(state->new)))))
-	{
-		/* In-case we haven't actually configured the address yet */
-		if (type == DHCP_INFORM && state->addr.s_addr == 0)
-			bootp->ciaddr = lease->addr.s_addr;
-		else
-			bootp->ciaddr = state->addr.s_addr;
-	}
+		bootp->ciaddr = state->addr->addr.s_addr;
 
-	bootp->op = DHCP_BOOTREQUEST;
+	bootp->op = BOOTREQUEST;
 	bootp->htype = (uint8_t)ifp->family;
 	switch (ifp->family) {
 	case ARPHRD_ETHER:
@@ -789,7 +785,7 @@ make_message(struct bootp **bootpm, cons
 	    type != DHCP_DECLINE &&
 	    type != DHCP_RELEASE)
 		bootp->flags = htons(BROADCAST_FLAG);
-#if 0
+
 	if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
 		struct timespec tv;
 
@@ -800,7 +796,7 @@ make_message(struct bootp **bootpm, cons
 		else
 			bootp->secs = htons((uint16_t)tv.tv_sec);
 	}
-#endif
+
 	bootp->xid = htonl(state->xid);
 
 	if (ifo->options & DHCPCD_BOOTP)
@@ -838,7 +834,8 @@ make_message(struct bootp **bootpm, cons
 	if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
 		if (type == DHCP_DECLINE ||
 		    (type == DHCP_REQUEST &&
-			lease->addr.s_addr != state->addr.s_addr))
+		    (state->addr == NULL ||
+		    lease->addr.s_addr != state->addr->addr.s_addr)))
 		{
 			PUT_ADDR(DHO_IPADDRESS, &lease->addr);
 			if (lease->server.s_addr)
@@ -1171,7 +1168,12 @@ read_lease(struct interface *ifp, struct
 		return 0;
 	}
 
-	if (bytes < sizeof(**bootp)) {
+	/* Ensure the packet is at lease BOOTP sized
+	 * with a vendor area of 4 octets
+	 * (it should be more, and our read packet enforces this so this
+	 * code should not be needed, but of course people could
+	 * scribble whatever in the stored lease file. */
+	if (bytes < offsetof(struct bootp, vend) + 4) {
 		free(lease);
 		logger(ifp->ctx, LOG_ERR, "%s: truncated lease", __func__);
 		return 0;
@@ -1429,19 +1431,40 @@ dhcp_env(char **env, const char *prefix,
 }
 
 static void
-get_lease(struct dhcpcd_ctx *ctx,
+get_lease(struct interface *ifp,
     struct dhcp_lease *lease, const struct bootp *bootp, size_t len)
 {
+	struct dhcpcd_ctx *ctx;
 
 	assert(bootp != NULL);
 
 	memcpy(&lease->cookie, bootp->vend, sizeof(lease->cookie));
 	/* BOOTP does not set yiaddr for replies when ciaddr is set. */
 	lease->addr.s_addr = bootp->yiaddr ? bootp->yiaddr : bootp->ciaddr;
-	if (get_option_addr(ctx, &lease->net, bootp, len, DHO_SUBNETMASK) == -1)
-		lease->net.s_addr = ipv4_getnetmask(lease->addr.s_addr);
-	if (get_option_addr(ctx, &lease->brd, bootp, len, DHO_BROADCAST) == -1)
-		lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
+	ctx = ifp->ctx;
+	if (ifp->options->options & (DHCPCD_STATIC | DHCPCD_INFORM)) {
+		if (ifp->options->req_addr.s_addr != INADDR_ANY) {
+			lease->mask = ifp->options->req_mask;
+			lease->brd.s_addr =
+			    lease->addr.s_addr | ~lease->mask.s_addr;
+		} else {
+			const struct ipv4_addr *ia;
+
+			ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+			assert(ia != NULL);
+			lease->mask = ia->mask;
+			lease->brd = ia->brd;
+		}
+	} else {
+		if (get_option_addr(ctx, &lease->mask, bootp, len,
+		    DHO_SUBNETMASK) == -1)
+			lease->mask.s_addr =
+			    ipv4_getnetmask(lease->addr.s_addr);
+		if (get_option_addr(ctx, &lease->brd, bootp, len,
+		    DHO_BROADCAST) == -1)
+			lease->brd.s_addr =
+			    lease->addr.s_addr | ~lease->mask.s_addr;
+	}
 	if (get_option_uint32(ctx, &lease->leasetime,
 	    bootp, len, DHO_LEASETIME) != 0)
 		lease->leasetime = ~0U; /* Default to infinite lease */
@@ -1502,7 +1525,7 @@ dhcp_close(struct interface *ifp)
 
 	if (state->raw_fd != -1) {
 		eloop_event_delete(ifp->ctx->eloop, state->raw_fd);
-		close(state->raw_fd);
+		if_closeraw(ifp, state->raw_fd);
 		state->raw_fd = -1;
 	}
 
@@ -1542,12 +1565,12 @@ dhcp_openudp(struct interface *ifp)
 #endif
 	memset(&sin, 0, sizeof(sin));
 	sin.sin_family = AF_INET;
-	sin.sin_port = htons(DHCP_CLIENT_PORT);
+	sin.sin_port = htons(BOOTPC);
 	if (ifp) {
 		state = D_STATE(ifp);
-		sin.sin_addr.s_addr = state->addr.s_addr;
-	} else
-		state = NULL; /* appease gcc */
+		if (state->addr)
+			sin.sin_addr.s_addr = state->addr->addr.s_addr;
+	}
 	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
 		goto eexit;
 
@@ -1610,8 +1633,8 @@ dhcp_makeudppacket(size_t *sz, const uin
 	else
 		ip->ip_dst.s_addr = dest.s_addr;
 
-	udp->uh_sport = htons(DHCP_CLIENT_PORT);
-	udp->uh_dport = htons(DHCP_SERVER_PORT);
+	udp->uh_sport = htons(BOOTPC);
+	udp->uh_dport = htons(BOOTPS);
 	udp->uh_ulen = htons((uint16_t)(sizeof(*udp) + length));
 	ip->ip_len = udp->uh_ulen;
 	udp->uh_sum = checksum(udpp, sizeof(*ip) +  sizeof(*udp) + length);
@@ -1638,7 +1661,7 @@ send_message(struct interface *ifp, uint
 	size_t len;
 	ssize_t r;
 	struct in_addr from, to;
-	in_addr_t a = INADDR_ANY;
+	struct ipv4_addr *iap;
 	struct timespec tv;
 	int s;
 #ifdef IN_IFF_NOTUSEABLE
@@ -1681,11 +1704,11 @@ send_message(struct interface *ifp, uint
 	if (dhcp_open(ifp) == -1)
 		return;
 
+	iap = state->addr;
 	if (state->added && !(state->added & STATE_FAKE) &&
-	    state->addr.s_addr != INADDR_ANY &&
-	    state->new != NULL &&
+	    state->addr != NULL && state->new != NULL &&
 #ifdef IN_IFF_NOTUSEABLE
-	    ((ia = ipv4_iffindaddr(ifp, &state->addr, NULL)) &&
+	    ((ia = ipv4_iffindaddr(ifp, &state->addr->addr, NULL)) &&
 	    !(ia->addr_flags & IN_IFF_NOTUSEABLE)) &&
 #endif
 	    (state->lease.server.s_addr ||
@@ -1698,14 +1721,12 @@ send_message(struct interface *ifp, uint
 				logger(ifp->ctx, LOG_ERR,
 				    "%s: dhcp_openudp: %m", ifp->name);
 			/* We cannot renew */
-			a = state->addr.s_addr;
-			state->addr.s_addr = INADDR_ANY;
+			state->addr = NULL;
 		}
 	}
 
 	r = make_message(&bootp, ifp, type);
-	if (a != INADDR_ANY)
-		state->addr.s_addr = a;
+	state->addr = iap;
 	if (r == -1)
 		goto fail;
 	len = (size_t)r;
@@ -1720,7 +1741,7 @@ send_message(struct interface *ifp, uint
 		memset(&sin, 0, sizeof(sin));
 		sin.sin_family = AF_INET;
 		sin.sin_addr.s_addr = to.s_addr;
-		sin.sin_port = htons(DHCP_SERVER_PORT);
+		sin.sin_port = htons(BOOTPS);
 		r = sendto(s, (uint8_t *)bootp, len, 0,
 		    (struct sockaddr *)&sin, sizeof(sin));
 		if (r == -1)
@@ -1730,12 +1751,12 @@ send_message(struct interface *ifp, uint
 		size_t ulen;
 
 		r = 0;
-		udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from, to);
+		udp = dhcp_makeudppacket(&ulen, (uint8_t *)bootp, len, from,to);
 		if (udp == NULL) {
 			logger(ifp->ctx, LOG_ERR, "dhcp_makeudppacket: %m");
 		} else {
-			r = if_sendrawpacket(ifp, ETHERTYPE_IP,
-			    (uint8_t *)udp, ulen);
+			r = if_sendraw(ifp, state->raw_fd,
+			    ETHERTYPE_IP, (uint8_t *)udp, ulen);
 			free(udp);
 		}
 		/* If we failed to send a raw packet this normally means
@@ -1745,7 +1766,7 @@ send_message(struct interface *ifp, uint
 		 * stopping the interface. */
 		if (r == -1) {
 			logger(ifp->ctx, LOG_ERR,
-			    "%s: if_sendrawpacket: %m", ifp->name);
+			    "%s: if_sendraw: %m", ifp->name);
 			switch(errno) {
 			case ENETDOWN:
 			case ENETRESET:
@@ -1994,7 +2015,7 @@ dhcp_arp_probed(struct arp_state *astate
 		len = state->new_len;
 		state->new = state->offer;
 		state->new_len = state->offer_len;
-		get_lease(astate->iface->ctx, &state->lease,
+		get_lease(astate->iface, &state->lease,
 		    state->new, state->new_len);
 		ipv4_applyaddr(astate->iface);
 		state->new = bootp;
@@ -2073,9 +2094,8 @@ dhcp_arp_conflicted(struct arp_state *as
 		    !state->lease.frominfo)
 			dhcp_decline(ifp);
 #ifdef IN_IFF_DUPLICATED
-		ia = ipv4_iffindaddr(ifp, &astate->addr, NULL);
-		if (ia)
-			ipv4_deladdr(ifp, &ia->addr, &ia->net, 1);
+		if ((ia = ipv4_iffindaddr(ifp, &astate->addr, NULL)) != NULL)
+			ipv4_deladdr(ia, 1);
 #endif
 		arp_free(astate);
 		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -2085,11 +2105,12 @@ dhcp_arp_conflicted(struct arp_state *as
 	}
 
 	/* Bound address */
-	if (amsg &&
-	    (amsg->sip.s_addr == state->addr.s_addr ||
-	    (amsg->sip.s_addr == 0 && amsg->tip.s_addr == state->addr.s_addr)))
+	if (amsg && state->addr &&
+	    (amsg->sip.s_addr == state->addr->addr.s_addr ||
+	    (amsg->sip.s_addr == 0 &&
+	    amsg->tip.s_addr == state->addr->addr.s_addr)))
 	{
-		astate->failed = state->addr;
+		astate->failed = state->addr->addr;
 		arp_report_conflicted(astate, amsg);
 		if (state->state == DHS_BOUND) {
 			/* For now, just report the duplicated address */
@@ -2120,11 +2141,11 @@ dhcp_bind(struct interface *ifp)
 		state->offer = NULL;
 		state->offer_len = 0;
 	}
-	get_lease(ifp->ctx, lease, state->new, state->new_len);
+	get_lease(ifp, lease, state->new, state->new_len);
 	if (ifo->options & DHCPCD_STATIC) {
 		logger(ifp->ctx, LOG_INFO, "%s: using static address %s/%d",
 		    ifp->name, inet_ntoa(lease->addr),
-		    inet_ntocidr(lease->net));
+		    inet_ntocidr(lease->mask));
 		lease->leasetime = ~0U;
 		state->reason = "STATIC";
 	} else if (ifo->options & DHCPCD_INFORM) {
@@ -2171,7 +2192,8 @@ dhcp_bind(struct interface *ifp)
 				    ifp->name, lease->renewaltime);
 			}
 			logger(ifp->ctx,
-			    lease->addr.s_addr == state->addr.s_addr &&
+			    state->addr &&
+			    lease->addr.s_addr == state->addr->addr.s_addr &&
 			    !(state->added & STATE_FAKE) ?
 			    LOG_DEBUG : LOG_INFO,
 			    "%s: leased %s for %"PRIu32" seconds", ifp->name,
@@ -2227,6 +2249,9 @@ dhcp_lastlease(void *arg)
 	struct interface *ifp = arg;
 	struct dhcp_state *state = D_STATE(ifp);
 
+	logger(ifp->ctx, LOG_INFO,
+	    "%s: timed out contacting a DHCP server, using last lease",
+	    ifp->name);
 	dhcp_bind(ifp);
 	/* If we forked, stop here. */
 	if (ifp->ctx->options & DHCPCD_FORKED)
@@ -2256,10 +2281,10 @@ dhcp_message_new(struct bootp **bootp,
 	p = (*bootp)->vend;
 
 	cookie = htonl(MAGIC_COOKIE);
-	memcpy(&cookie, p, sizeof(cookie));
+	memcpy(p, &cookie, sizeof(cookie));
 	p += sizeof(cookie);
 
-	if (mask && mask->s_addr != INADDR_ANY) {
+	if (mask->s_addr != INADDR_ANY) {
 		*p++ = DHO_SUBNETMASK;
 		*p++ = sizeof(mask->s_addr);
 		memcpy(p, &mask->s_addr, sizeof(mask->s_addr));
@@ -2297,9 +2322,9 @@ dhcp_arp_address(struct interface *ifp)
 		if (ia == NULL) {
 			struct dhcp_lease l;
 
-			get_lease(ifp->ctx, &l, state->offer, state->offer_len);
+			get_lease(ifp, &l, state->offer, state->offer_len);
 			/* Add the address now, let the kernel handle DAD. */
-			ipv4_addaddr(ifp, &l.addr, &l.net, &l.brd);
+			ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd);
 		} else
 			logger(ifp->ctx, LOG_INFO, "%s: waiting for DAD on %s",
 			    ifp->name, inet_ntoa(addr));
@@ -2309,9 +2334,9 @@ dhcp_arp_address(struct interface *ifp)
 	if (ifp->options->options & DHCPCD_ARP && ia == NULL) {
 		struct dhcp_lease l;
 
-		get_lease(ifp->ctx, &l, state->offer, state->offer_len);
+		get_lease(ifp, &l, state->offer, state->offer_len);
 		logger(ifp->ctx, LOG_INFO, "%s: probing address %s/%d",
-		    ifp->name, inet_ntoa(l.addr), inet_ntocidr(l.net));
+		    ifp->name, inet_ntoa(l.addr), inet_ntocidr(l.mask));
 		if ((astate = arp_new(ifp, &addr)) != NULL) {
 			astate->probed_cb = dhcp_arp_probed;
 			astate->conflicted_cb = dhcp_arp_conflicted;
@@ -2358,7 +2383,7 @@ dhcp_static(struct interface *ifp)
 
 	state->offer_len = dhcp_message_new(&state->offer,
 	    ia ? &ia->addr : &ifo->req_addr,
-	    ia ? &ia->net : &ifo->req_mask);
+	    ia ? &ia->mask : &ifo->req_mask);
 	if (state->offer_len)
 		dhcp_arp_bind(ifp);
 }
@@ -2398,6 +2423,10 @@ dhcp_inform(struct interface *ifp)
 				    ifp->name);
 				return;
 			}
+			ia = ipv4_iffindaddr(ifp, &ifo->req_addr, NULL);
+			if (ia != NULL)
+				/* Netmask must be different, delete it. */
+				ipv4_deladdr(ia, 1);
 			state->offer_len = dhcp_message_new(&state->offer,
 			    &ifo->req_addr, &ifo->req_mask);
 			if (dhcp_arp_address(ifp) == 0)
@@ -2408,11 +2437,12 @@ dhcp_inform(struct interface *ifp)
 		}
 	}
 
-	state->offer_len = dhcp_message_new(&state->offer, &ia->addr, &ia->net);
+	state->addr = ia;
+	state->offer_len = dhcp_message_new(&state->offer,
+	    &ia->addr, &ia->mask);
 	if (state->offer_len) {
 		state->xid = dhcp_xid(ifp);
-		get_lease(ifp->ctx, &state->lease,
-		    state->offer, state->offer_len);
+		get_lease(ifp, &state->lease, state->offer, state->offer_len);
 		send_inform(ifp);
 	}
 }
@@ -2427,7 +2457,8 @@ dhcp_reboot_newopts(struct interface *if
 		return;
 	ifo = ifp->options;
 	if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
-		state->addr.s_addr != ifo->req_addr.s_addr) ||
+		(state->addr == NULL ||
+		state->addr->addr.s_addr != ifo->req_addr.s_addr)) ||
 	    (oldopts & (DHCPCD_INFORM | DHCPCD_STATIC) &&
 		!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
 	{
@@ -2672,6 +2703,12 @@ dhcp_handledhcp(struct interface *ifp, s
 #define LOGDHCP(l, m) \
 	log_dhcp((l), (m), ifp, bootp, bootp_len, from, 1)
 
+	if (bootp->op != BOOTREPLY) {
+		logger(ifp->ctx, LOG_DEBUG, "%s: op (%d) is not BOOTREPLY",
+		    ifp->name, bootp->op);
+		return;
+	}
+
 	/* Ensure packet is for us */
 	if (ifp->hwlen <= sizeof(bootp->chaddr) &&
 	    memcmp(bootp->chaddr, ifp->hwaddr, ifp->hwlen))
@@ -2901,7 +2938,7 @@ dhcp_handledhcp(struct interface *ifp, s
 		LOGDHCP(LOG_WARNING, "declined duplicate address");
 		if (type)
 			dhcp_decline(ifp);
-		ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
+		ipv4_deladdr(ia, 0);
 		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 		eloop_timeout_add_sec(ifp->ctx->eloop,
 		    DHCP_RAND_MAX, dhcp_discover, ifp);
@@ -3103,69 +3140,59 @@ dhcp_handlepacket(void *arg)
 	/* Need this API due to BPF */
 	flags = 0;
 	bootp = NULL;
-	while (!(flags & RAW_EOF)) {
-		bytes = (size_t)if_readrawpacket(ifp, ETHERTYPE_IP,
-		    buf, sizeof(buf), &flags);
-		if ((ssize_t)bytes == -1) {
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: dhcp if_readrawpacket: %m", ifp->name);
-			dhcp_close(ifp);
-			arp_close(ifp);
-			break;
-		}
-		if (valid_udp_packet(buf, bytes,
-		    &from, flags & RAW_PARTIALCSUM) == -1)
-		{
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: invalid UDP packet from %s",
-			    ifp->name, inet_ntoa(from));
-			continue;
-		}
-		i = whitelisted_ip(ifp->options, from.s_addr);
-		if (i == 0) {
-			logger(ifp->ctx, LOG_WARNING,
-			    "%s: non whitelisted DHCP packet from %s",
-			    ifp->name, inet_ntoa(from));
-			continue;
-		} else if (i != 1 &&
-		    blacklisted_ip(ifp->options, from.s_addr) == 1)
-		{
-			logger(ifp->ctx, LOG_WARNING,
-			    "%s: blacklisted DHCP packet from %s",
-			    ifp->name, inet_ntoa(from));
-			continue;
-		}
-		if (ifp->flags & IFF_POINTOPOINT &&
-		    state->brd.s_addr != from.s_addr)
-		{
-			logger(ifp->ctx, LOG_WARNING,
-			    "%s: server %s is not destination",
-			    ifp->name, inet_ntoa(from));
-		}
-		/*
-		 * DHCP has a variable option area rather than a fixed
-		 * vendor area.
-		 * Because DHCP uses the BOOTP protocol it should
-		 * still send BOOTP sized packets to be RFC compliant.
-		 * However some servers send a truncated vendor area.
-		 * dhcpcd can work fine without the vendor area being sent.
-		 */
-		bytes = get_udp_data(&bootp, buf);
-		if (bytes < offsetof(struct bootp, vend)) {
-			logger(ifp->ctx, LOG_ERR,
-			    "%s: truncated packet (%zu) from %s",
-			    ifp->name, bytes, inet_ntoa(from));
-			continue;
-		}
-		/* But to make our IS_DHCP macro easy, ensure the vendor
-		 * area has at least 4 octets. */
-		while (bytes < offsetof(struct bootp, vend) + 4)
-			bootp[bytes++] = '\0';
-
-		dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from);
-		if (state->raw_fd == -1)
-			break;
+	bytes = (size_t)if_readraw(ifp, state->raw_fd,buf, sizeof(buf), &flags);
+	if ((ssize_t)bytes == -1) {
+		logger(ifp->ctx, LOG_ERR,
+		    "%s: dhcp if_readrawpacket: %m", ifp->name);
+		dhcp_close(ifp);
+		arp_close(ifp);
+		return;
+	}
+	if (valid_udp_packet(buf, bytes, &from, flags & RAW_PARTIALCSUM) == -1)
+	{
+		logger(ifp->ctx, LOG_ERR, "%s: invalid UDP packet from %s",
+		    ifp->name, inet_ntoa(from));
+		return;
+	}
+	i = whitelisted_ip(ifp->options, from.s_addr);
+	if (i == 0) {
+		logger(ifp->ctx, LOG_WARNING,
+		    "%s: non whitelisted DHCP packet from %s",
+		    ifp->name, inet_ntoa(from));
+		return;
+	} else if (i != 1 && blacklisted_ip(ifp->options, from.s_addr) == 1) {
+		logger(ifp->ctx, LOG_WARNING,
+		    "%s: blacklisted DHCP packet from %s",
+		    ifp->name, inet_ntoa(from));
+		return;
+	}
+	if (ifp->flags & IFF_POINTOPOINT &&
+	    (state->addr == NULL || state->addr->brd.s_addr != from.s_addr))
+	{
+		logger(ifp->ctx, LOG_WARNING,
+		    "%s: server %s is not destination",
+		    ifp->name, inet_ntoa(from));
+	}
+	/*
+	 * DHCP has a variable option area rather than a fixed vendor area.
+	 * Because DHCP uses the BOOTP protocol it should still send BOOTP
+	 * sized packets to be RFC compliant.
+	 * However some servers send a truncated vendor area.
+	 * dhcpcd can work fine without the vendor area being sent.
+	 */
+	bytes = get_udp_data(&bootp, buf);
+	if (bytes < offsetof(struct bootp, vend)) {
+		logger(ifp->ctx, LOG_ERR,
+		    "%s: truncated packet (%zu) from %s",
+		    ifp->name, bytes, inet_ntoa(from));
+		return;
 	}
+	/* But to make our IS_DHCP macro easy, ensure the vendor
+	 * area has at least 4 octets. */
+	while (bytes < offsetof(struct bootp, vend) + 4)
+		bootp[bytes++] = '\0';
+
+	dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from);
 }
 
 static void
@@ -3193,7 +3220,7 @@ dhcp_open(struct interface *ifp)
 
 	state = D_STATE(ifp);
 	if (state->raw_fd == -1) {
-		state->raw_fd = if_openrawsocket(ifp, ETHERTYPE_IP);
+		state->raw_fd = if_openraw(ifp, ETHERTYPE_IP);
 		if (state->raw_fd == -1) {
 			if (errno == ENOENT) {
 				logger(ifp->ctx, LOG_ERR,
@@ -3293,7 +3320,7 @@ dhcp_init(struct interface *ifp)
 		state->raw_fd = -1;
 
 		/* Now is a good time to find IPv4 routes */
-		if_initrt(ifp);
+		if_initrt(ifp->ctx);
 	}
 
 	state->state = DHS_INIT;
@@ -3455,11 +3482,13 @@ dhcp_start1(void *arg)
 		}
 	}
 	if (state->offer) {
-		get_lease(ifp->ctx, &state->lease,
-		    state->offer, state->offer_len);
+		struct ipv4_addr *ia;
+
+		get_lease(ifp, &state->lease, state->offer, state->offer_len);
 		state->lease.frominfo = 1;
 		if (state->new == NULL &&
-		    ipv4_iffindaddr(ifp, &state->lease.addr, &state->lease.net))
+		    (ia = ipv4_iffindaddr(ifp,
+		    &state->lease.addr, &state->lease.mask)) != NULL)
 		{
 			/* We still have the IP address from the last lease.
 			 * Fake add the address and routes from it so the lease
@@ -3468,19 +3497,17 @@ dhcp_start1(void *arg)
 			if (state->new) {
 				memcpy(state->new,
 				    state->offer, state->offer_len);
-				state->addr = state->lease.addr;
-				state->net = state->lease.net;
+				state->new_len = state->offer_len;
+				state->addr = ia;
 				state->added |= STATE_ADDED | STATE_FAKE;
 				ipv4_buildroutes(ifp->ctx);
 			} else
 				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
 		}
 		if (!IS_DHCP(state->offer)) {
-			if (state->offer->yiaddr == state->addr.s_addr) {
-				free(state->offer);
-				state->offer = NULL;
-				state->offer_len = 0;
-			}
+			free(state->offer);
+			state->offer = NULL;
+			state->offer_len = 0;
 		} else if (!(ifo->options & DHCPCD_LASTLEASE_EXTEND) &&
 		    state->lease.leasetime != ~0U &&
 		    stat(state->leasefile, &st) == 0)
@@ -3543,6 +3570,13 @@ dhcp_start(struct interface *ifp)
 	if (!(ifp->options->options & DHCPCD_IPV4))
 		return;
 
+	/* If we haven't been given a netmask for our requested address,
+	 * set it now. */
+	if (ifp->options->req_addr.s_addr != INADDR_ANY &&
+	    ifp->options->req_mask.s_addr == INADDR_ANY)
+		ifp->options->req_mask.s_addr =
+		    ipv4_getnetmask(ifp->options->req_addr.s_addr);
+
 	/* If we haven't specified a ClientID and our hardware address
 	 * length is greater than BOOTP CHADDR then we enforce a ClientID
 	 * of the hardware address family and the hardware address.
@@ -3594,29 +3628,22 @@ dhcp_abort(struct interface *ifp)
 }
 
 void
-dhcp_handleifa(int cmd, struct interface *ifp,
-	const struct in_addr *addr,
-	const struct in_addr *net,
-	const struct in_addr *brd,
-	int flags)
+dhcp_handleifa(int cmd, struct ipv4_addr *ia)
 {
+	struct interface *ifp;
 	struct dhcp_state *state;
 	struct if_options *ifo;
 	uint8_t i;
 
+	ifp = ia->iface;
 	state = D_STATE(ifp);
 	if (state == NULL)
 		return;
 
 	if (cmd == RTM_DELADDR) {
-		if (state->addr.s_addr == addr->s_addr &&
-		    state->net.s_addr == net->s_addr &&
-		    state->brd.s_addr == brd->s_addr)
-		{
+		if (IPV4_BRD_EQ(state->addr, ia)) {
 			logger(ifp->ctx, LOG_INFO,
-			    "%s: removing IP address %s/%d",
-			    ifp->name, inet_ntoa(state->addr),
-			    inet_ntocidr(state->net));
+			    "%s: removing IP address %s", ifp->name, ia->saddr);
 			dhcp_drop(ifp, "EXPIRE");
 		}
 		return;
@@ -3626,10 +3653,8 @@ dhcp_handleifa(int cmd, struct interface
 		return;
 
 #ifdef IN_IFF_NOTUSEABLE
-	if (flags & IN_IFF_NOTUSEABLE)
+	if (ia->addr_flags & IN_IFF_NOTUSEABLE)
 		return;
-#else
-	UNUSED(flags);
 #endif
 
 	ifo = ifp->options;
@@ -3646,14 +3671,13 @@ dhcp_handleifa(int cmd, struct interface
 
 	free(state->old);
 	state->old = state->new;
-	state->new_len = dhcp_message_new(&state->new, addr, net);
+	state->new_len = dhcp_message_new(&state->new, &ia->addr, &ia->mask);
 	if (state->new == NULL)
 		return;
-	state->brd = *brd;
 	if (ifp->flags & IFF_POINTOPOINT) {
 		for (i = 1; i < 255; i++)
 			if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
-				dhcp_message_add_addr(state->new, i, *brd);
+				dhcp_message_add_addr(state->new, i, ia->brd);
 	}
 	state->reason = "STATIC";
 	ipv4_buildroutes(ifp->ctx);
@@ -3661,9 +3685,8 @@ dhcp_handleifa(int cmd, struct interface
 	if (ifo->options & DHCPCD_INFORM) {
 		state->state = DHS_INFORM;
 		state->xid = dhcp_xid(ifp);
-		state->lease.server = *brd;
-		state->addr = *addr;
-		state->net = *net;
+		state->lease.server.s_addr = INADDR_ANY;
+		state->addr = ia;
 		dhcp_inform(ifp);
 	}
 }

Index: src/external/bsd/dhcpcd/dist/dhcp.h
diff -u src/external/bsd/dhcpcd/dist/dhcp.h:1.16 src/external/bsd/dhcpcd/dist/dhcp.h:1.17
--- src/external/bsd/dhcpcd/dist/dhcp.h:1.16	Thu May 26 09:09:47 2016
+++ src/external/bsd/dhcpcd/dist/dhcp.h	Fri Jun 17 19:42:31 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp.h,v 1.16 2016/05/26 09:09:47 prlw1 Exp $ */
+/* $NetBSD: dhcp.h,v 1.17 2016/06/17 19:42:31 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -40,27 +40,27 @@
 #include "auth.h"
 #include "dhcp-common.h"
 
-/* UDP port numbers for DHCP */
-#define DHCP_SERVER_PORT    67
-#define DHCP_CLIENT_PORT    68
-
-#define MAGIC_COOKIE        0x63825363
-#define BROADCAST_FLAG      0x8000
-
-/* DHCP message OP code */
-#define DHCP_BOOTREQUEST    1
-#define DHCP_BOOTREPLY      2
+/* UDP port numbers for BOOTP */
+#define BOOTPS			67
+#define BOOTPC			68
+
+#define MAGIC_COOKIE		0x63825363
+#define BROADCAST_FLAG		0x8000
+
+/* BOOTP message OP code */
+#define BOOTREQUEST		1
+#define BOOTREPLY		2
 
 /* DHCP message type */
-#define DHCP_DISCOVER       1
-#define DHCP_OFFER          2
-#define DHCP_REQUEST        3
-#define DHCP_DECLINE        4
-#define DHCP_ACK            5
-#define DHCP_NAK            6
-#define DHCP_RELEASE        7
-#define DHCP_INFORM         8
-#define DHCP_FORCERENEW     9
+#define DHCP_DISCOVER		1
+#define DHCP_OFFER		2
+#define DHCP_REQUEST		3
+#define DHCP_DECLINE		4
+#define DHCP_ACK		5
+#define DHCP_NAK		6
+#define DHCP_RELEASE		7
+#define DHCP_INFORM		8
+#define DHCP_FORCERENEW		9
 
 /* Constants taken from RFC 2131. */
 #define T1			0.5
@@ -173,7 +173,7 @@ struct bootp {
 
 struct dhcp_lease {
 	struct in_addr addr;
-	struct in_addr net;
+	struct in_addr mask;
 	struct in_addr brd;
 	uint32_t leasetime;
 	uint32_t renewaltime;
@@ -215,9 +215,7 @@ struct dhcp_state {
 	int socket;
 
 	int raw_fd;
-	struct in_addr addr;
-	struct in_addr net;
-	struct in_addr brd;
+	struct ipv4_addr *addr;
 	uint8_t added;
 
 	char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4)];
@@ -253,10 +251,7 @@ struct rt_head *dhcp_get_routes(struct i
 ssize_t dhcp_env(char **, const char *, const struct bootp *, size_t,
     const struct interface *);
 
-void dhcp_handleifa(int, struct interface *,
-    const struct in_addr *, const struct in_addr *, const struct in_addr *,
-    int);
-
+void dhcp_handleifa(int, struct ipv4_addr *);
 void dhcp_drop(struct interface *, const char *);
 void dhcp_start(struct interface *);
 void dhcp_abort(struct interface *);
Index: src/external/bsd/dhcpcd/dist/if.h
diff -u src/external/bsd/dhcpcd/dist/if.h:1.16 src/external/bsd/dhcpcd/dist/if.h:1.17
--- src/external/bsd/dhcpcd/dist/if.h:1.16	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/if.h	Fri Jun 17 19:42:32 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.16 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: if.h,v 1.17 2016/06/17 19:42:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -82,13 +82,14 @@
 	    ((addr & IN_CLASSB_NET) == 0xc0a80000))
 #endif
 
-#define RAW_EOF			1 << 0
-#define RAW_PARTIALCSUM		2 << 0
+#define RAW_PARTIALCSUM		1 << 0
 
 #ifdef __sun
-/* platform does not supply AF_LINK with getifaddrs. */
+/* Solaris getifaddrs is very un-suitable for dhcpcd.
+ * See if-sun.c for details why. */
 struct ifaddrs;
 int if_getifaddrs(struct ifaddrs **);
+#define	getifaddrs	if_getifaddrs
 #else
 #define GETIFADDRS_AFLINK
 #endif
@@ -114,7 +115,7 @@ int if_opensockets(struct dhcpcd_ctx *);
 int if_opensockets_os(struct dhcpcd_ctx *);
 void if_closesockets(struct dhcpcd_ctx *);
 void if_closesockets_os(struct dhcpcd_ctx *);
-int if_managelink(struct dhcpcd_ctx *);
+int if_handlelink(struct dhcpcd_ctx *);
 
 /* dhcpcd uses the same routing flags as BSD.
  * If the platform doesn't use these flags,
@@ -141,23 +142,17 @@ int if_managelink(struct dhcpcd_ctx *);
 
 #ifdef INET
 extern const char *if_pfname;
-int if_openrawsocket(struct interface *, uint16_t);
-ssize_t if_sendrawpacket(const struct interface *,
-    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 *,
-    const struct in_addr *, int);
-#define if_addaddress(ifp, addr, net, brd)	\
-	if_address(ifp, addr, net, brd, 1)
-#define if_deladdress(ifp, addr, net)		\
-	if_address(ifp, addr, net, NULL, -1)
+int if_openraw(struct interface *, uint16_t);
+ssize_t if_sendraw(const struct interface *, int, uint16_t,
+    const void *, size_t);
+ssize_t if_readraw(struct interface *, int, void *, size_t, int *);
+void if_closeraw(struct interface *, int);
 
+int if_address(unsigned char, const struct ipv4_addr *);
 int if_addrflags(const struct in_addr *, const struct interface *);
 
 int if_route(unsigned char, const struct rt *rt);
-int if_initrt(struct interface *);
+int if_initrt(struct dhcpcd_ctx *);
 #endif
 
 #ifdef INET6
@@ -170,15 +165,12 @@ int ip6_temp_valid_lifetime(const char *
 #define ip6_use_tempaddr(a) (0)
 #endif
 
-int if_address6(const struct ipv6_addr *, int);
-#define if_addaddress6(a) if_address6(a, 1)
-#define if_deladdress6(a) if_address6(a, -1)
-
+int if_address6(unsigned char, const struct ipv6_addr *);
 int if_addrflags6(const struct in6_addr *, const struct interface *);
 int if_getlifetime6(struct ipv6_addr *);
 
 int if_route6(unsigned char, const struct rt6 *rt);
-int if_initrt6(struct interface *);
+int if_initrt6(struct dhcpcd_ctx *);
 #else
 #define if_checkipv6(a, b, c) (-1)
 #endif
Index: src/external/bsd/dhcpcd/dist/ipv4ll.c
diff -u src/external/bsd/dhcpcd/dist/ipv4ll.c:1.16 src/external/bsd/dhcpcd/dist/ipv4ll.c:1.17
--- src/external/bsd/dhcpcd/dist/ipv4ll.c:1.16	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/ipv4ll.c	Fri Jun 17 19:42:32 2016
@@ -1,9 +1,9 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4ll.c,v 1.16 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: ipv4ll.c,v 1.17 2016/06/17 19:42:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <r...@marples.name>
+ * Copyright (c) 2006-2016 Roy Marples <r...@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -48,11 +48,15 @@
 #include "ipv4ll.h"
 #include "script.h"
 
-const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
-const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
+static const struct in_addr inaddr_llmask = {
+	.s_addr = HTONL(LINKLOCAL_MASK)
+};
+static const struct in_addr inaddr_llbcast = {
+	.s_addr = HTONL(LINKLOCAL_BCAST)
+};
 
 static in_addr_t
-ipv4ll_pick_addr(const struct arp_state *astate)
+ipv4ll_pickaddr(struct arp_state *astate)
 {
 	struct in_addr addr;
 	struct ipv4ll_state *istate;
@@ -78,8 +82,7 @@ ipv4ll_pick_addr(const struct arp_state 
 	} while (ipv4_findaddr(astate->iface->ctx, &addr) != NULL);
 
 	/* Restore the original random state */
-	setstate(astate->iface->ctx->randomstate);
-
+	setstate(istate->arp->iface->ctx->randomstate);
 	return addr.s_addr;
 }
 
@@ -91,7 +94,7 @@ ipv4ll_subnet_route(const struct interfa
 
 	assert(ifp != NULL);
 	if ((state = IPV4LL_CSTATE(ifp)) == NULL ||
-	    state->addr.s_addr == INADDR_ANY)
+	    state->addr == NULL)
 		return NULL;
 
 	if ((rt = calloc(1, sizeof(*rt))) == NULL) {
@@ -99,10 +102,10 @@ ipv4ll_subnet_route(const struct interfa
 		return NULL;
 	}
 	rt->iface = ifp;
-	rt->dest.s_addr = state->addr.s_addr & inaddr_llmask.s_addr;
-	rt->net = inaddr_llmask;
+	rt->dest.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
+	rt->mask.s_addr = state->addr->mask.s_addr;
 	rt->gate.s_addr = INADDR_ANY;
-	rt->src = state->addr;
+	rt->src = state->addr->addr;
 	return rt;
 }
 
@@ -114,7 +117,7 @@ ipv4ll_default_route(const struct interf
 
 	assert(ifp != NULL);
 	if ((state = IPV4LL_CSTATE(ifp)) == NULL ||
-	    state->addr.s_addr == INADDR_ANY)
+	    state->addr == NULL)
 		return NULL;
 
 	if ((rt = calloc(1, sizeof(*rt))) == NULL) {
@@ -123,9 +126,9 @@ ipv4ll_default_route(const struct interf
 	}
 	rt->iface = ifp;
 	rt->dest.s_addr = INADDR_ANY;
-	rt->net.s_addr = INADDR_ANY;
+	rt->mask.s_addr = INADDR_ANY;
 	rt->gate.s_addr = INADDR_ANY;
-	rt->src = state->addr;
+	rt->src = state->addr->addr;
 	return rt;
 }
 
@@ -145,18 +148,18 @@ ipv4ll_env(char **env, const char *prefi
 
 	/* Emulate a DHCP environment */
 	if (asprintf(&env[0], "%s%sip_address=%s",
-	    prefix, pf, inet_ntoa(state->addr)) == -1)
+	    prefix, pf, inet_ntoa(state->addr->addr)) == -1)
 		return -1;
 	if (asprintf(&env[1], "%s%ssubnet_mask=%s",
-	    prefix, pf, inet_ntoa(inaddr_llmask)) == -1)
+	    prefix, pf, inet_ntoa(state->addr->mask)) == -1)
 		return -1;
 	if (asprintf(&env[2], "%s%ssubnet_cidr=%d",
-	    prefix, pf, inet_ntocidr(inaddr_llmask)) == -1)
+	    prefix, pf, inet_ntocidr(state->addr->mask)) == -1)
 		return -1;
 	if (asprintf(&env[3], "%s%sbroadcast_address=%s",
-	    prefix, pf, inet_ntoa(inaddr_llbcast)) == -1)
+	    prefix, pf, inet_ntoa(state->addr->brd)) == -1)
 		return -1;
-	netnum.s_addr = state->addr.s_addr & inaddr_llmask.s_addr;
+	netnum.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
 	if (asprintf(&env[4], "%s%snetwork_number=%s",
 	    prefix, pf, inet_ntoa(netnum)) == -1)
 		return -1;
@@ -198,14 +201,14 @@ ipv4ll_probed(struct arp_state *astate)
 	    ifp->name, inet_ntoa(astate->addr));
 #endif
 test:
-	state->addr = astate->addr;
+	state->addr = ia;
 	if (ifp->ctx->options & DHCPCD_TEST) {
 		script_runreason(ifp, "TEST");
 		eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
 		return;
 	}
 	timespecclear(&state->defend);
-	if_initrt(ifp);
+	if_initrt(ifp->ctx);
 	ipv4_buildroutes(ifp->ctx);
 	arp_announce(astate);
 	script_runreason(ifp, "IPV4LL");
@@ -244,6 +247,7 @@ ipv4ll_conflicted(struct arp_state *asta
 	ifp = astate->iface;
 	state = IPV4LL_STATE(ifp);
 	assert(state != NULL);
+	assert(state->addr != NULL);
 
 	fail = 0;
 	/* RFC 3927 2.2.1, Probe Conflict Detection */
@@ -253,9 +257,9 @@ ipv4ll_conflicted(struct arp_state *asta
 		fail = astate->addr.s_addr;
 
 	/* RFC 3927 2.5, Conflict Defense */
-	if (IN_LINKLOCAL(ntohl(state->addr.s_addr)) &&
-	    amsg && amsg->sip.s_addr == state->addr.s_addr)
-		fail = state->addr.s_addr;
+	if (IN_LINKLOCAL(ntohl(state->addr->addr.s_addr)) &&
+	    amsg && amsg->sip.s_addr == state->addr->addr.s_addr)
+		fail = state->addr->addr.s_addr;
 
 	if (fail == 0)
 		return;
@@ -263,7 +267,7 @@ ipv4ll_conflicted(struct arp_state *asta
 	astate->failed.s_addr = fail;
 	arp_report_conflicted(astate, amsg);
 
-	if (astate->failed.s_addr == state->addr.s_addr) {
+	if (astate->failed.s_addr == state->addr->addr.s_addr) {
 		struct timespec now, defend;
 
 		/* RFC 3927 Section 2.5 says a defence should
@@ -280,24 +284,23 @@ ipv4ll_conflicted(struct arp_state *asta
 		if (timespeccmp(&defend, &now, >))
 			logger(ifp->ctx, LOG_WARNING,
 			    "%s: IPv4LL %d second defence failed for %s",
-			    ifp->name, DEFEND_INTERVAL,
-			    inet_ntoa(state->addr));
+			    ifp->name, DEFEND_INTERVAL, state->addr->saddr);
 		else if (arp_request(ifp,
-		    state->addr.s_addr, state->addr.s_addr) == -1)
+		    state->addr->addr.s_addr, state->addr->addr.s_addr) == -1)
 			logger(ifp->ctx, LOG_ERR,
 			    "%s: arp_request: %m", __func__);
 		else {
 			logger(ifp->ctx, LOG_DEBUG,
 			    "%s: defended IPv4LL address %s",
-			    ifp->name, inet_ntoa(state->addr));
+			    ifp->name, state->addr->saddr);
 			state->defend = now;
 			return;
 		}
 
-		ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
+		ipv4_deladdr(state->addr, 1);
 		state->down = 1;
+		state->addr = NULL;
 		script_runreason(ifp, "IPV4LL");
-		state->addr.s_addr = INADDR_ANY;
 	}
 
 	arp_cancel(astate);
@@ -305,7 +308,7 @@ ipv4ll_conflicted(struct arp_state *asta
 		logger(ifp->ctx, LOG_ERR,
 		    "%s: failed to acquire an IPv4LL address",
 		    ifp->name);
-	astate->addr.s_addr = ipv4ll_pick_addr(astate);
+	astate->addr.s_addr = ipv4ll_pickaddr(astate);
 	eloop_timeout_add_sec(ifp->ctx->eloop,
 		state->conflicts >= MAX_CONFLICTS ?
 		RATE_LIMIT_INTERVAL : PROBE_WAIT,
@@ -338,8 +341,6 @@ ipv4ll_start(void *arg)
 			syslog(LOG_ERR, "%s: calloc %m", __func__);
 			return;
 		}
-
-		state->addr.s_addr = INADDR_ANY;
 	}
 
 	if (state->arp != NULL)
@@ -384,7 +385,7 @@ ipv4ll_start(void *arg)
 	ia = ipv4_iffindlladdr(ifp);
 #ifdef IN_IFF_TENTATIVE
 	if (ia != NULL && ia->addr_flags & IN_IFF_DUPLICATED) {
-		ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
+		ipv4_deladdr(ia, 0);
 		ia = NULL;
 	}
 #endif
@@ -398,7 +399,7 @@ ipv4ll_start(void *arg)
 			return;
 		}
 		logger(ifp->ctx, LOG_INFO, "%s: using IPv4LL address %s",
-		  ifp->name, inet_ntoa(astate->addr));
+		  ifp->name, ia->saddr);
 #endif
 		ipv4ll_probed(astate);
 		return;
@@ -406,7 +407,7 @@ ipv4ll_start(void *arg)
 
 	logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
 	    ifp->name);
-	astate->addr.s_addr = ipv4ll_pick_addr(astate);
+	astate->addr.s_addr = ipv4ll_pickaddr(astate);
 #ifdef IN_IFF_TENTATIVE
 	ipv4ll_probed(astate);
 #else
@@ -434,9 +435,9 @@ ipv4ll_freedrop(struct interface *ifp, i
 	if (drop && (ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP) {
 		struct ipv4_state *istate;
 
-		if (state && state->addr.s_addr != INADDR_ANY) {
-			ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
-			state->addr.s_addr = INADDR_ANY;
+		if (state && state->addr != NULL) {
+			ipv4_deladdr(state->addr, 1);
+			state->addr = NULL;
 			dropped = 1;
 		}
 
@@ -446,8 +447,7 @@ ipv4ll_freedrop(struct interface *ifp, i
 
 			TAILQ_FOREACH_SAFE(ia, &istate->addrs, next, ian) {
 				if (IN_LINKLOCAL(ntohl(ia->addr.s_addr))) {
-					ipv4_deladdr(ifp, &ia->addr,
-					    &ia->net, 0);
+					ipv4_deladdr(ia, 0);
 					dropped = 1;
 				}
 			}
@@ -479,12 +479,11 @@ ipv4ll_handlert(struct dhcpcd_ctx *ctx, 
 
 	/* If any interface is running IPv4LL, rebuild our routing table. */
 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-		if (IPV4LL_STATE_RUNNING(ifp))
+		if (IPV4LL_STATE_RUNNING(ifp)) {
+			if_initrt(ifp->ctx);
+			ipv4_buildroutes(ifp->ctx);
 			break;
-	}
-	if (ifp != NULL) {
-		if_initrt(ifp);
-		ipv4_buildroutes(ctx);
+		}
 	}
 
 	return 0;

Index: src/external/bsd/dhcpcd/dist/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.21 src/external/bsd/dhcpcd/dist/dhcp6.c:1.22
--- src/external/bsd/dhcpcd/dist/dhcp6.c:1.21	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/dhcp6.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp6.c,v 1.21 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: dhcp6.c,v 1.22 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -64,10 +64,6 @@
 #include "compat/bitops.h"
 #endif
 
-#ifndef __UNCONST
-#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
-#endif
-
 /* DHCPCD Project has been assigned an IANA PEN of 40712 */
 #define DHCPCD_IANA_PEN 40712
 
@@ -320,7 +316,7 @@ dhcp6_updateelapsed(struct interface *if
 	if (co == NULL)
 		return -1;
 
-	o = __UNCONST(co);
+	o = UNCONST(co);
 	state = D6_STATE(ifp);
 	clock_gettime(CLOCK_MONOTONIC, &tv);
 	if (state->RTC == 0) {
@@ -408,14 +404,29 @@ dhcp6_delegateaddr(struct in6_addr *addr
 	}
 
 	if (sla == NULL || sla->sla_set == 0) {
+		/* No SLA set, so make an assumption of
+		 * desired SLA and prefix length. */
 		asla.sla = ifp->index;
 		asla.prefix_len = 0;
+		asla.sla_set = 0;
+		sla = &asla;
+	} else if (sla->sla == 0 && sla->prefix_len == 0) {
+		/* An SLA of 0 was set with no prefix length specified.
+		 * This means we delegate the whole prefix. */
+		asla.sla = sla->sla;
+		asla.prefix_len = prefix->prefix_len;
+		asla.sla_set = 0;
 		sla = &asla;
 	} else if (sla->prefix_len == 0) {
+		/* An SLA was given, but prefix length was not.
+		 * We need to work out a suitable prefix length for
+		 * potentially more than one interface. */
 		asla.sla = sla->sla;
 		asla.prefix_len = 0;
+		asla.sla_set = 0;
 		sla = &asla;
 	}
+
 	if (sla->prefix_len == 0) {
 		uint32_t sla_max;
 		int bits;
@@ -954,7 +965,7 @@ dhcp6_update_auth(struct interface *ifp,
 	if (co == NULL)
 		return -1;
 
-	o = __UNCONST(co);
+	o = UNCONST(co);
 	state = D6_STATE(ifp);
 
 	return dhcp_auth_encode(&ifp->options->auth, state->auth.token,
@@ -2393,7 +2404,7 @@ dhcp6_ifdelegateaddr(struct interface *i
 		ia->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
 		ia->dadcallback = dhcp6_dadcallback;
 		memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid));
-		ia->created = ia->acquired = prefix->acquired;
+		ia->created = prefix->acquired;
 		ia->addr = daddr;
 
 		TAILQ_INSERT_TAIL(&state->addrs, ia, next);
@@ -2402,6 +2413,7 @@ dhcp6_ifdelegateaddr(struct interface *i
 	ia->delegating_prefix = prefix;
 	ia->prefix = addr;
 	ia->prefix_len = (uint8_t)pfxlen;
+	ia->acquired = prefix->acquired;
 	ia->prefix_pltime = prefix->prefix_pltime;
 	ia->prefix_vltime = prefix->prefix_vltime;
 
@@ -2468,6 +2480,11 @@ dhcp6_delegate_prefix(struct interface *
 	ifo = ifp->options;
 	state = D6_STATE(ifp);
 
+	/* Clear the logged flag. */
+	TAILQ_FOREACH(ap, &state->addrs, next) {
+		ap->flags &= ~IPV6_AF_DELEGATEDLOG;
+	}
+
 	TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
 		if (!ifd->active)
 			continue;
@@ -2476,11 +2493,15 @@ dhcp6_delegate_prefix(struct interface *
 		TAILQ_FOREACH(ap, &state->addrs, next) {
 			if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
 				continue;
-			if (ap->flags & IPV6_AF_NEW) {
-				ap->flags &= ~IPV6_AF_NEW;
-				logger(ifp->ctx, LOG_DEBUG,
+			if (!(ap->flags & IPV6_AF_DELEGATEDLOG)) {
+				/* We only want to log this the once as we loop
+				 * through many interfaces first. */
+				ap->flags |= IPV6_AF_DELEGATEDLOG;
+				logger(ifp->ctx,
+				    ap->flags & IPV6_AF_NEW ?LOG_INFO:LOG_DEBUG,
 				    "%s: delegated prefix %s",
 				    ifp->name, ap->saddr);
+				ap->flags &= ~IPV6_AF_NEW;
 			}
 			for (i = 0; i < ifo->ia_len; i++) {
 				ia = &ifo->ia[i];
@@ -2527,7 +2548,7 @@ dhcp6_delegate_prefix(struct interface *
 		if (k && !carrier_warned) {
 			ifd_state = D6_STATE(ifd);
 			ipv6_addaddrs(&ifd_state->addrs);
-			if_initrt6(ifd);
+			if_initrt6(ifd->ctx);
 			ipv6_buildroutes(ifd->ctx);
 			dhcp6_script_try_run(ifd, 1);
 		}
@@ -2594,7 +2615,7 @@ dhcp6_find_delegates(struct interface *i
 		state = D6_STATE(ifp);
 		state->state = DH6S_DELEGATED;
 		ipv6_addaddrs(&state->addrs);
-		if_initrt6(ifp);
+		if_initrt6(ifp->ctx);
 		ipv6_buildroutes(ifp->ctx);
 		dhcp6_script_try_run(ifp, 1);
 	}
@@ -2955,7 +2976,12 @@ dhcp6_handledata(void *arg)
 	case DHCP6_ADVERTISE:
 		if (state->state == DH6S_REQUEST) /* rapid commit */
 			break;
-		ap = TAILQ_FIRST(&state->addrs);
+		TAILQ_FOREACH(ap, &state->addrs, next) {
+			if (!(ap->flags & IPV6_AF_REQUEST))
+				break;
+		}
+		if (ap == NULL)
+			ap = TAILQ_FIRST(&state->addrs);
 		logger(ifp->ctx, LOG_INFO, "%s: ADV %s from %s",
 		    ifp->name, ap->saddr, ctx->sfrom);
 		if (ifp->ctx->options & DHCPCD_TEST)
@@ -3095,7 +3121,7 @@ recv:
 		else if (state->expire == 0)
 			logger(ifp->ctx, has_new ? LOG_INFO : LOG_DEBUG,
 			    "%s: will expire", ifp->name);
-		if_initrt6(ifp);
+		if_initrt6(ifp->ctx);
 		ipv6_buildroutes(ifp->ctx);
 		dhcp6_writelease(ifp);
 		dhcp6_delegate_prefix(ifp);
@@ -3426,6 +3452,20 @@ dhcp6_free(struct interface *ifp)
 	dhcp6_freedrop(ifp, 0, NULL);
 }
 
+void dhcp6_dropnondelegates(struct interface *ifp)
+{
+	struct dhcp6_state *state;
+	struct ipv6_addr *ia;
+
+	if ((state = D6_STATE(ifp)) == NULL)
+		return;
+	TAILQ_FOREACH(ia, &state->addrs, next) {
+		if (ia->flags & (IPV6_AF_DELEGATED | IPV6_AF_DELEGATEDPFX))
+			return;
+	}
+	dhcp6_drop(ifp, "EXPIRE6");
+}
+
 void
 dhcp6_handleifa(struct dhcpcd_ctx *ctx, int cmd, const char *ifname,
     const struct in6_addr *addr, int flags)
Index: src/external/bsd/dhcpcd/dist/if.c
diff -u src/external/bsd/dhcpcd/dist/if.c:1.21 src/external/bsd/dhcpcd/dist/if.c:1.22
--- src/external/bsd/dhcpcd/dist/if.c:1.21	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/if.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if.c,v 1.21 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: if.c,v 1.22 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -214,14 +214,13 @@ static void if_learnaddrs(struct dhcpcd_
 			addr = (void *)ifa->ifa_addr;
 			net = (void *)ifa->ifa_netmask;
 			if (ifa->ifa_flags & IFF_POINTOPOINT)
-				brd = (const struct sockaddr_in *)
-				    (void *)ifa->ifa_dstaddr;
+				brd = (void *)ifa->ifa_dstaddr;
 			else
 				brd = (void *)ifa->ifa_broadaddr;
 			ifa_flags = if_addrflags(&addr->sin_addr, ifp);
 			ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
-				&addr->sin_addr, &net->sin_addr, &brd->sin_addr,
-				ifa_flags);
+				&addr->sin_addr, &net->sin_addr,
+				brd ? &brd->sin_addr : NULL, ifa_flags);
 			break;
 #endif
 #ifdef INET6
@@ -274,16 +273,11 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 	const struct sockaddr_ll *sll;
 #endif
 
-#ifdef GETIFADDRS_AFLINK
 	if (getifaddrs(&ifaddrs) == -1)
 		return NULL;
-#else
-	if (if_getifaddrs(&ifaddrs) == -1)
-		return NULL;
-#endif
-	ifs = malloc(sizeof(*ifs));
-	if (ifs == NULL)
-		return NULL;
+
+	if ((ifs = malloc(sizeof(*ifs))) == NULL)
+		goto failed;
 	TAILQ_INIT(ifs);
 
 	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
@@ -469,7 +463,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 			}
 			ifp->hwlen = sdl->sdl_alen;
 #ifndef CLLADDR
-#  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
+#  define CLLADDR(s) (const void *)((s)->sdl_data + (s)->sdl_nlen)
 #endif
 			memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
 #elif AF_PACKET
@@ -557,16 +551,9 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
-#ifdef GETIFADDRS_AFLINK
-	{
-#else
+	if_learnaddrs(ctx, ifs, ifaddrs);
+failed:
 	freeifaddrs(ifaddrs);
-	if (getifaddrs(&ifaddrs) != -1) {
-#endif
-		if_learnaddrs(ctx, ifs, ifaddrs);
-		freeifaddrs(ifaddrs);
-	}
-
 	return ifs;
 }
 

Index: src/external/bsd/dhcpcd/dist/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.34 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.35
--- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.34	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/dhcpcd.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd.c,v 1.34 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd.c,v 1.35 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -423,14 +423,17 @@ configure_interface1(struct interface *i
 	if (ifo->options & DHCPCD_RELEASE)
 		ifo->options &= ~DHCPCD_PERSISTENT;
 
-	if (ifp->flags & IFF_POINTOPOINT && !(ifo->options & DHCPCD_INFORM))
-		ifo->options |= DHCPCD_STATIC;
+	if (ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) {
+		ifo->options &= ~DHCPCD_ARP;
+		if (!(ifp->flags & IFF_MULTICAST))
+			ifo->options &= ~DHCPCD_IPV6RS;
+		if (!(ifo->options & DHCPCD_INFORM))
+			ifo->options |= DHCPCD_STATIC;
+	}
 	if (ifp->flags & IFF_NOARP ||
+	    !(ifo->options & DHCPCD_ARP) ||
 	    ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
 		ifo->options &= ~DHCPCD_IPV4LL;
-	if (ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK) ||
-	    !(ifp->flags & IFF_MULTICAST))
-		ifo->options &= ~DHCPCD_IPV6RS;
 
 	if (ifo->metric != -1)
 		ifp->metric = (unsigned int)ifo->metric;
@@ -989,13 +992,13 @@ dhcpcd_activateinterface(struct interfac
 }
 
 static void
-handle_link(void *arg)
+dhcpcd_handlelink(void *arg)
 {
 	struct dhcpcd_ctx *ctx;
 
 	ctx = arg;
-	if (if_managelink(ctx) == -1) {
-		logger(ctx, LOG_ERR, "if_managelink: %m");
+	if (if_handlelink(ctx) == -1) {
+		logger(ctx, LOG_ERR, "if_handlelink: %m");
 		eloop_event_delete(ctx->eloop, ctx->link_fd);
 		close(ctx->link_fd);
 		ctx->link_fd = -1;
@@ -1089,7 +1092,7 @@ dhcpcd_handleinterface(void *arg, int ac
 
 void
 dhcpcd_handlehwaddr(struct dhcpcd_ctx *ctx, const char *ifname,
-    const uint8_t *hwaddr, uint8_t hwlen)
+    const void *hwaddr, uint8_t hwlen)
 {
 	struct interface *ifp;
 	char buf[sizeof(ifp->hwaddr) * 3];
@@ -1831,7 +1834,7 @@ printpidfile:
 
 	/* Start handling kernel messages for interfaces, addreses and
 	 * routes. */
-	eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx);
+	eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
 
 	/* Start any dev listening plugin which may want to
 	 * change the interface name provided by the kernel */

Index: src/external/bsd/dhcpcd/dist/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.30 src/external/bsd/dhcpcd/dist/if-bsd.c:1.31
--- src/external/bsd/dhcpcd/dist/if-bsd.c:1.30	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/if-bsd.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-bsd.c,v 1.30 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: if-bsd.c,v 1.31 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -96,16 +96,18 @@
 
 #define COPYOUT(sin, sa) do {						      \
 	if ((sa) && ((sa)->sa_family == AF_INET || (sa)->sa_family == 255))   \
-		(sin) = ((struct sockaddr_in *)(void *)(sa))->sin_addr;	      \
+		(sin) = ((const struct sockaddr_in *)(const void *)	      \
+		    (sa))->sin_addr;	      \
 	} while (0)
 
 #define COPYOUT6(sin, sa) do {						      \
 	if ((sa) && ((sa)->sa_family == AF_INET6 || (sa)->sa_family == 255))  \
-		(sin) = ((struct sockaddr_in6 *)(void *)(sa))->sin6_addr;     \
+		(sin) = ((const struct sockaddr_in6 *)(const void *)	      \
+		    (sa))->sin6_addr;     \
 	} while (0)
 
 #ifndef CLLADDR
-#  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
+#  define CLLADDR(s) (const void *)((s)->sdl_data + (s)->sdl_nlen)
 #endif
 
 struct priv {
@@ -145,7 +147,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx
 #endif
 
 #define SOCK_FLAGS	(SOCK_CLOEXEC | SOCK_NONBLOCK)
-	ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW | SOCK_FLAGS, 0);
+	ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW | SOCK_FLAGS, AF_UNSPEC);
 #undef SOCK_FLAGS
 	return ctx->link_fd == -1 ? -1 : 0;
 }
@@ -174,7 +176,7 @@ if_linkaddr(struct sockaddr_dl *sdl, con
 #endif
 
 static int
-if_getssid1(int s, const char *ifname, uint8_t *ssid)
+if_getssid1(int s, const char *ifname, void *ssid)
 {
 	int retval = -1;
 #if defined(SIOCG80211NWID)
@@ -266,13 +268,15 @@ if_vimaster(const struct dhcpcd_ctx *ctx
 }
 
 static void
-get_addrs(int type, char *cp, struct sockaddr **sa)
+get_addrs(int type, const void *data, const struct sockaddr **sa)
 {
+	const char *cp;
 	int i;
 
+	cp = data;
 	for (i = 0; i < RTAX_MAX; i++) {
 		if (type & (1 << i)) {
-			sa[i] = (struct sockaddr *)cp;
+			sa[i] = (const struct sockaddr *)cp;
 			RT_ADVANCE(cp, sa[i]);
 		} else
 			sa[i] = NULL;
@@ -362,8 +366,15 @@ if_findsa(struct dhcpcd_ctx *ctx, const 
 #ifdef INET
 const char *if_pfname = "Berkley Packet Filter";
 
+void
+if_closeraw(__unused struct interface *ifp, int fd)
+{
+
+	close(fd);
+}
+
 int
-if_openrawsocket(struct interface *ifp, uint16_t protocol)
+if_openraw(struct interface *ifp, uint16_t protocol)
 {
 	struct ipv4_state *state;
 	int fd = -1;
@@ -443,14 +454,14 @@ if_openrawsocket(struct interface *ifp, 
 		goto eexit;
 #endif
 
-	/* Install the DHCP filter */
+	/* Install the filter. */
 	memset(&pf, 0, sizeof(pf));
 	if (protocol == ETHERTYPE_ARP) {
 		pf.bf_insns = UNCONST(arp_bpf_filter);
 		pf.bf_len = arp_bpf_filter_len;
 	} else {
-		pf.bf_insns = UNCONST(dhcp_bpf_filter);
-		pf.bf_len = dhcp_bpf_filter_len;
+		pf.bf_insns = UNCONST(bootp_bpf_filter);
+		pf.bf_len = bootp_bpf_filter_len;
 	}
 	if (ioctl(fd, BIOCSETF, &pf) == -1)
 		goto eexit;
@@ -465,12 +476,11 @@ eexit:
 }
 
 ssize_t
-if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
+if_sendraw(__unused const struct interface *ifp, int fd, uint16_t protocol,
     const void *data, size_t len)
 {
 	struct iovec iov[2];
 	struct ether_header hw;
-	int fd;
 
 	memset(&hw, 0, ETHER_HDR_LEN);
 	memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
@@ -479,25 +489,20 @@ if_sendrawpacket(const struct interface 
 	iov[0].iov_len = ETHER_HDR_LEN;
 	iov[1].iov_base = UNCONST(data);
 	iov[1].iov_len = len;
-	fd = ipv4_protocol_fd(ifp, protocol);
 	return writev(fd, iov, 2);
 }
 
 /* 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, uint16_t protocol,
-    void *data, size_t len, int *flags)
+if_readraw(struct interface *ifp, int fd, void *data, size_t len, int *flags)
 {
-	int fd;
 	struct bpf_hdr packet;
 	ssize_t bytes;
-	const unsigned char *payload;
+	const char *payload;
 	struct ipv4_state *state;
 
 	state = IPV4_STATE(ifp);
-	fd = ipv4_protocol_fd(ifp, protocol);
-
 	*flags = 0;
 	for (;;) {
 		if (state->buffer_len == 0) {
@@ -524,10 +529,8 @@ if_readrawpacket(struct interface *ifp, 
 next:
 		state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
 		    packet.bh_caplen);
-		if (state->buffer_pos >= state->buffer_len) {
+		if (state->buffer_pos >= state->buffer_len)
 			state->buffer_len = state->buffer_pos = 0;
-			*flags |= RAW_EOF;
-		}
 		if (bytes != -1)
 			return bytes;
 	}
@@ -535,40 +538,36 @@ next:
 
 
 int
-if_address(const struct interface *ifp, const struct in_addr *address,
-    const struct in_addr *netmask, const struct in_addr *broadcast,
-    int action)
+if_address(unsigned char cmd, const struct ipv4_addr *ia)
 {
 	int r;
 	struct in_aliasreq ifra;
 
 	memset(&ifra, 0, sizeof(ifra));
-	strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name));
+	strlcpy(ifra.ifra_name, ia->iface->name, sizeof(ifra.ifra_name));
 
 #define ADDADDR(var, addr) do {						      \
 		(var)->sin_family = AF_INET;				      \
 		(var)->sin_len = sizeof(*(var));			      \
 		(var)->sin_addr = *(addr);				      \
 	} while (/*CONSTCOND*/0)
-	ADDADDR(&ifra.ifra_addr, address);
-	ADDADDR(&ifra.ifra_mask, netmask);
-	if (action >= 0 && broadcast)
-		ADDADDR(&ifra.ifra_broadaddr, broadcast);
+	ADDADDR(&ifra.ifra_addr, &ia->addr);
+	ADDADDR(&ifra.ifra_mask, &ia->mask);
+	if (cmd == RTM_NEWADDR && ia->brd.s_addr != INADDR_ANY)
+		ADDADDR(&ifra.ifra_broadaddr, &ia->brd);
 #undef ADDADDR
 
-	r = ioctl(ifp->ctx->pf_inet_fd,
-	    action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
+	r = ioctl(ia->iface->ctx->pf_inet_fd,
+	    cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
 	return r;
 }
 
 static int
-if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
+if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
 {
-	char *cp;
-	struct sockaddr *sa, *rti_info[RTAX_MAX];
+	const struct sockaddr *sa, *rti_info[RTAX_MAX];
 
-	cp = (void *)(rtm + 1);
-	sa = (void *)cp;
+	sa = (const void *)(rtm + 1);
 	if (sa->sa_family != AF_INET)
 		return -1;
 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
@@ -586,14 +585,14 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 		return -1;
 #endif
 
-	get_addrs(rtm->rtm_addrs, cp, rti_info);
+	get_addrs(rtm->rtm_addrs, sa, rti_info);
 	memset(rt, 0, sizeof(*rt));
 	rt->flags = (unsigned int)rtm->rtm_flags;
 	COPYOUT(rt->dest, rti_info[RTAX_DST]);
 	if (rtm->rtm_addrs & RTA_NETMASK)
-		COPYOUT(rt->net, rti_info[RTAX_NETMASK]);
+		COPYOUT(rt->mask, rti_info[RTAX_NETMASK]);
 	else
-		rt->net.s_addr = INADDR_BROADCAST;
+		rt->mask.s_addr = INADDR_BROADCAST;
 	COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
 	COPYOUT(rt->src, rti_info[RTAX_IFA]);
 	rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
@@ -692,7 +691,7 @@ if_route(unsigned char cmd, const struct
 		if (subnet == -1) /* unikely */
 			rtm.hdr.rtm_addrs &= ~RTA_IFA;
 	}
-	if (rt->net.s_addr == htonl(INADDR_BROADCAST) &&
+	if (rt->mask.s_addr == htonl(INADDR_BROADCAST) &&
 	    rt->gate.s_addr == htonl(INADDR_ANY))
 	{
 #ifdef RTF_CLONING
@@ -708,7 +707,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 == htonl(INADDR_BROADCAST))
+	    rt->mask.s_addr == htonl(INADDR_BROADCAST))
 	{
 		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
 		/* Going via lo0 so remove the interface flags */
@@ -718,7 +717,7 @@ if_route(unsigned char cmd, const struct
 		rtm.hdr.rtm_addrs |= RTA_NETMASK;
 		if (rtm.hdr.rtm_flags & RTF_STATIC)
 			rtm.hdr.rtm_flags |= RTF_GATEWAY;
-		if (rt->net.s_addr == htonl(INADDR_BROADCAST))
+		if (rt->mask.s_addr == htonl(INADDR_BROADCAST))
 			rtm.hdr.rtm_flags |= RTF_HOST;
 	}
 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
@@ -744,7 +743,7 @@ if_route(unsigned char cmd, const struct
 	}
 
 	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
-		ADDADDR(&rt->net);
+		ADDADDR(&rt->mask);
 
 	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
 	    (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)))
@@ -775,7 +774,7 @@ if_route(unsigned char cmd, const struct
 }
 
 int
-if_initrt(struct interface *ifp)
+if_initrt(struct dhcpcd_ctx *ctx)
 {
 	struct rt_msghdr *rtm;
 	int mib[6];
@@ -783,7 +782,7 @@ if_initrt(struct interface *ifp)
 	char *buf, *p, *end;
 	struct rt rt;
 
-	ipv4_freerts(ifp->ctx->ipv4_kroutes);
+	ipv4_freerts(ctx->ipv4_kroutes);
 
 	mib[0] = CTL_NET;
 	mib[1] = PF_ROUTE;
@@ -806,17 +805,17 @@ if_initrt(struct interface *ifp)
 	end = buf + needed;
 	for (p = buf; p < end; p += rtm->rtm_msglen) {
 		rtm = (void *)p;
-		if (if_copyrt(ifp->ctx, &rt, rtm) == 0)
-			ipv4_handlert(ifp->ctx, RTM_ADD, &rt, 1);
+		if (if_copyrt(ctx, &rt, rtm) == 0)
+			ipv4_handlert(ctx, RTM_ADD, &rt, 1);
 	}
 	free(buf);
 	return 0;
 }
 
-#ifdef SIOCGIFAFLAG_IN
 int
 if_addrflags(const struct in_addr *addr, const struct interface *ifp)
 {
+#ifdef SIOCGIFAFLAG_IN
 	struct ifreq ifr;
 	struct sockaddr_in *sin;
 
@@ -828,17 +827,12 @@ if_addrflags(const struct in_addr *addr,
 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
 		return -1;
 	return ifr.ifr_addrflags;
-}
 #else
-int
-if_addrflags(__unused const struct in_addr *addr,
-    __unused const struct interface *ifp)
-{
-
-	errno = ENOTSUP;
+	UNUSED(addr);
+	UNUSED(ifp);
 	return 0;
-}
 #endif
+}
 #endif /* INET */
 
 #ifdef INET6
@@ -873,7 +867,7 @@ ifa_scope(struct sockaddr_in6 *sin, unsi
 #endif
 
 int
-if_address6(const struct ipv6_addr *ia, int action)
+if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 {
 	struct in6_aliasreq ifa;
 	struct in6_addr mask;
@@ -914,18 +908,15 @@ if_address6(const struct ipv6_addr *ia, 
 
 	priv = (struct priv *)ia->iface->ctx->priv;
 	return ioctl(priv->pf_inet6_fd,
-	    action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
+	    cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
 }
 
-
 static int
-if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
+if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, const struct rt_msghdr *rtm)
 {
-	char *cp;
-	struct sockaddr *sa, *rti_info[RTAX_MAX];
+	const struct sockaddr *sa, *rti_info[RTAX_MAX];
 
-	cp = (void *)(rtm + 1);
-	sa = (void *)cp;
+	sa = (const void *)(rtm + 1);
 	if (sa->sa_family != AF_INET6)
 		return -1;
 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
@@ -942,7 +933,7 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 		return -1;
 #endif
 
-	get_addrs(rtm->rtm_addrs, cp, rti_info);
+	get_addrs(rtm->rtm_addrs, sa, rti_info);
 	memset(rt, 0, sizeof(*rt));
 	rt->flags = (unsigned int)rtm->rtm_flags;
 	COPYOUT6(rt->dest, rti_info[RTAX_DST]);
@@ -955,12 +946,12 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 		 * a kernel bug or actually used for something.
 		 * Either way it needs to be zeroed out.
 		 */
-		struct sockaddr_in6 *sin6;
+		const struct sockaddr_in6 *sin6;
 		size_t e, i, final = 0, illegal = 0;
 		const unsigned char *p;
 
-		sin6 = (void *)rti_info[RTAX_NETMASK];
-		rt->net = sin6->sin6_addr;
+		sin6 = (const void *)rti_info[RTAX_NETMASK];
+		rt->mask = sin6->sin6_addr;
 		e = sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr);
 		if (e > sizeof(struct in6_addr))
 			e = sizeof(struct in6_addr);
@@ -970,7 +961,7 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 		{
 			if (final && *p) {
 				illegal = 1;
-				rt->net.s6_addr[i++] = 0x00;
+				rt->mask.s6_addr[i++] = 0x00;
 				continue;
 			}
 			switch (*p & 0xff) {
@@ -991,14 +982,14 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 				break;
 			}
 			if (!illegal)
-				rt->net.s6_addr[i++] &= *p;
+				rt->mask.s6_addr[i++] &= *p;
 			else
-				rt->net.s6_addr[i++] = 0x00;
+				rt->mask.s6_addr[i++] = 0x00;
 		}
-		while (i < sizeof(rt->net.s6_addr))
-			rt->net.s6_addr[i++] = 0x00;
+		while (i < sizeof(rt->mask.s6_addr))
+			rt->mask.s6_addr[i++] = 0x00;
 	} else
-		ipv6_mask(&rt->net, 128);
+		ipv6_mask(&rt->mask, 128);
 	COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
 	DESCOPE(&rt->gate);
 	rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
@@ -1107,7 +1098,7 @@ if_route6(unsigned char cmd, const struc
 	}
 
 	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
-		ADDADDR(&rt->net);
+		ADDADDR(&rt->mask);
 
 	if (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)) {
 		rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
@@ -1142,7 +1133,7 @@ if_route6(unsigned char cmd, const struc
 }
 
 int
-if_initrt6(struct interface *ifp)
+if_initrt6(struct dhcpcd_ctx *ctx)
 {
 	struct rt_msghdr *rtm;
 	int mib[6];
@@ -1150,7 +1141,7 @@ if_initrt6(struct interface *ifp)
 	char *buf, *p, *end;
 	struct rt6 rt;
 
-	ipv6_freerts(&ifp->ctx->ipv6->kroutes);
+	ipv6_freerts(&ctx->ipv6->kroutes);
 
 	mib[0] = CTL_NET;
 	mib[1] = PF_ROUTE;
@@ -1173,8 +1164,8 @@ if_initrt6(struct interface *ifp)
 	end = buf + needed;
 	for (p = buf; p < end; p += rtm->rtm_msglen) {
 		rtm = (void *)p;
-		if (if_copyrt6(ifp->ctx, &rt, rtm) == 0)
-			ipv6_handlert(ifp->ctx, RTM_ADD, &rt);
+		if (if_copyrt6(ctx, &rt, rtm) == 0)
+			ipv6_handlert(ctx, RTM_ADD, &rt);
 	}
 	free(buf);
 	return 0;
@@ -1237,215 +1228,252 @@ if_getlifetime6(struct ipv6_addr *ia)
 }
 #endif
 
-int
-if_managelink(struct dhcpcd_ctx *ctx)
+static void
+if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan)
+{
+
+	switch(ifan->ifan_what) {
+	case IFAN_ARRIVAL:
+		dhcpcd_handleinterface(ctx, 1, ifan->ifan_name);
+		break;
+	case IFAN_DEPARTURE:
+		dhcpcd_handleinterface(ctx, -1, ifan->ifan_name);
+		break;
+	}
+}
+
+static void
+if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
 {
-	/* route and ifwatchd like a msg buf size of 2048 */
-	char msg[2048], *p, *e, *cp;
-	ssize_t bytes;
-	struct rt_msghdr *rtm;
-	struct if_announcemsghdr *ifan;
-	struct if_msghdr *ifm;
-	struct ifa_msghdr *ifam;
-	struct sockaddr *sa, *rti_info[RTAX_MAX];
-	int len;
-	struct sockaddr_dl sdl;
 	struct interface *ifp;
+	int state;
+
+	if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
+		return;
+	switch (ifm->ifm_data.ifi_link_state) {
+	case LINK_STATE_DOWN:
+		state = LINK_DOWN;
+		break;
+	case LINK_STATE_UP:
+		state = LINK_UP;
+		break;
+	default:
+		/* handle_carrier will re-load the interface flags and check for
+		 * IFF_RUNNING as some drivers that don't handle link state also
+		 * don't set IFF_RUNNING when this routing message is generated.
+		 * As such, it is a race ...*/
+		state = LINK_UNKNOWN;
+		break;
+	}
+	dhcpcd_handlecarrier(ctx, state,
+	    (unsigned int)ifm->ifm_flags, ifp->name);
+}
+
+static void
+if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
+{
+	const struct sockaddr *sa;
+
+	/* Ignore messages generated by us */
+	if (rtm->rtm_pid == getpid()) {
+		ctx->options &= ~DHCPCD_RTM_PPID;
+		return;
+	}
+
+	/* Ignore messages sent by the parent after forking */
+	if ((ctx->options &
+	    (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) ==
+	    (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) &&
+	    rtm->rtm_pid == ctx->ppid)
+	{
+		/* If this is the last successful message sent,
+		 * clear the check flag as it's possible another
+		 * process could re-use the same pid and also
+		 * manipulate therouting table. */
+		if (rtm->rtm_seq == ctx->pseq)
+			ctx->options &= ~DHCPCD_RTM_PPID;
+		return;
+	}
+
+	sa = (const void *)(rtm + 1);
+	switch (sa->sa_family) {
 #ifdef INET
-	struct rt rt;
+	case AF_INET:
+	{
+		struct rt rt;
+
+		if (if_copyrt(ctx, &rt, rtm) == 0)
+			ipv4_handlert(ctx, rtm->rtm_type, &rt, 0);
+		break;
+	}
 #endif
 #ifdef INET6
-	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
+	case AF_INET6:
+	{
+		struct rt6 rt6;
 
-	if ((bytes = read(ctx->link_fd, msg, sizeof(msg))) == -1)
-		return -1;
-	e = msg + bytes;
-	for (p = msg; p < e; p += rtm->rtm_msglen) {
-		rtm = (void *)p;
-		switch(rtm->rtm_type) {
-#ifdef RTM_IFANNOUNCE
-		case RTM_IFANNOUNCE:
-			ifan = (void *)p;
-			switch(ifan->ifan_what) {
-			case IFAN_ARRIVAL:
-				dhcpcd_handleinterface(ctx, 1,
-				    ifan->ifan_name);
-				break;
-			case IFAN_DEPARTURE:
-				dhcpcd_handleinterface(ctx, -1,
-				    ifan->ifan_name);
-				break;
-			}
+		if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
 			break;
-#endif
-		case RTM_IFINFO:
-			ifm = (void *)p;
-			ifp = if_findindex(ctx->ifaces, ifm->ifm_index);
-			if (ifp == NULL)
-				break;
-			switch (ifm->ifm_data.ifi_link_state) {
-			case LINK_STATE_DOWN:
-				len = LINK_DOWN;
-				break;
-			case LINK_STATE_UP:
-				len = LINK_UP;
-				break;
-			default:
-				/* handle_carrier will re-load
-				 * the interface flags and check for
-				 * IFF_RUNNING as some drivers that
-				 * don't handle link state also don't
-				 * set IFF_RUNNING when this routing
-				 * message is generated.
-				 * As such, it is a race ...*/
-				len = LINK_UNKNOWN;
-				break;
-			}
-			dhcpcd_handlecarrier(ctx, len,
-			    (unsigned int)ifm->ifm_flags, ifp->name);
+		/*
+		 * BSD announces host routes.
+		 * As such, we should be notified of reachability by its
+		 * existance with a hardware address.
+		 */
+		if (rtm->rtm_flags & (RTF_HOST)) {
+			const struct sockaddr *rti_info[RTAX_MAX];
+			struct in6_addr dst6;
+			struct sockaddr_dl sdl;
+
+			get_addrs(rtm->rtm_addrs, rtm + 1, rti_info);
+			COPYOUT6(dst6, rti_info[RTAX_DST]);
+			DESCOPE(&dst6);
+			if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)
+				memcpy(&sdl, rti_info[RTAX_GATEWAY],
+				    sizeof(sdl));
+			else
+				sdl.sdl_alen = 0;
+			ipv6nd_neighbour(ctx, &dst6,
+			    rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
+			    IPV6ND_REACHABLE : 0);
 			break;
-		case RTM_ADD:
-		case RTM_CHANGE:
-		case RTM_DELETE:
-			/* Ignore messages generated by us */
-			if (rtm->rtm_pid == getpid()) {
-				ctx->options &= ~DHCPCD_RTM_PPID;
-				continue;
-			}
-			/* Ignore messages sent by the parent after forking */
-			if ((ctx->options &
-			    (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) ==
-			    (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) &&
-			    rtm->rtm_pid == ctx->ppid)
-			{
-				/* If this is the last successful message sent,
-				 * clear the check flag as it's possible another
-				 * process could re-use the same pid and also
-				 * manipulate therouting table. */
-				if (rtm->rtm_seq == ctx->pseq)
-					ctx->options &= ~DHCPCD_RTM_PPID;
-				continue;
-			}
-			cp = (void *)(rtm + 1);
-			sa = (void *)cp;
-			switch (sa->sa_family) {
-#ifdef INET
-			case AF_INET:
-				if (if_copyrt(ctx, &rt, rtm) == 0)
-					ipv4_handlert(ctx, rtm->rtm_type,&rt,0);
-				break;
-#endif
-#ifdef INET6
-			case AF_INET6:
-				if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
-					break;
-				/*
-				 * BSD caches host routes in the
-				 * routing table.
-				 * As such, we should be notified of
-				 * reachability by its existance
-				 * with a hardware address
-				 */
-				if (rtm->rtm_flags & (RTF_HOST)) {
-					get_addrs(rtm->rtm_addrs, cp, rti_info);
-					COPYOUT6(ia6, rti_info[RTAX_DST]);
-					DESCOPE(&ia6);
-					if (rti_info[RTAX_GATEWAY]->sa_family
-					    == AF_LINK)
-						memcpy(&sdl,
-						    rti_info[RTAX_GATEWAY],
-						    sizeof(sdl));
-					else
-						sdl.sdl_alen = 0;
-					ipv6nd_neighbour(ctx, &ia6,
-					    rtm->rtm_type != RTM_DELETE &&
-					    sdl.sdl_alen ?
-					    IPV6ND_REACHABLE : 0);
-					break;
-				}
+		}
 
-				if (if_copyrt6(ctx, &rt6, rtm) == 0)
-					ipv6_handlert(ctx, rtm->rtm_type, &rt6);
-				break;
-#endif
-			}
-			break;
-#ifdef RTM_CHGADDR
-		case RTM_CHGADDR:	/* FALLTHROUGH */
+		if (if_copyrt6(ctx, &rt6, rtm) == 0)
+			ipv6_handlert(ctx, rtm->rtm_type, &rt6);
+		break;
+	}
 #endif
-		case RTM_DELADDR:	/* FALLTHROUGH */
-		case RTM_NEWADDR:
-			/* XXX We have no way of knowing who generated these
-			 * messages wich truely sucks because we want to
-			 * avoid listening to our own delete messages. */
-			ifam = (void *)p;
-			ifp = if_findindex(ctx->ifaces, ifam->ifam_index);
-			if (ifp == NULL)
-				break;
-			cp = (void *)(ifam + 1);
-			get_addrs(ifam->ifam_addrs, cp, rti_info);
-			if (rti_info[RTAX_IFA] == NULL)
-				break;
-			switch (rti_info[RTAX_IFA]->sa_family) {
-			case AF_LINK:
+	}
+}
+
+static void
+if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
+{
+	struct interface *ifp;
+	const struct sockaddr *rti_info[RTAX_MAX];
+
+	/* XXX We have no way of knowing who generated these
+	 * messages wich truely sucks because we want to
+	 * avoid listening to our own delete messages. */
+	if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
+		return;
+	get_addrs(ifam->ifam_addrs, ifam + 1, rti_info);
+	if (rti_info[RTAX_IFA] == NULL)
+		return;
+	switch (rti_info[RTAX_IFA]->sa_family) {
+	case AF_LINK:
+	{
+		struct sockaddr_dl sdl;
+
 #ifdef RTM_CHGADDR
-				if (rtm->rtm_type != RTM_CHGADDR)
-					break;
+		if (ifam->ifam_type != RTM_CHGADDR)
+			break;
 #else
-				if (rtm->rtm_type != RTM_NEWADDR)
-					break;
+		if (ifam->ifam_type != RTM_NEWADDR)
+			break;
 #endif
-				memcpy(&sdl, rti_info[RTAX_IFA],
-				    rti_info[RTAX_IFA]->sa_len);
-				dhcpcd_handlehwaddr(ctx, ifp->name,
-				    (const unsigned char*)CLLADDR(&sdl),
-				    sdl.sdl_alen);
-				break;
+		memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len);
+		dhcpcd_handlehwaddr(ctx, ifp->name, CLLADDR(&sdl),sdl.sdl_alen);
+		break;
+	}
 #ifdef INET
-			case AF_INET:
-			case 255: /* FIXME: Why 255? */
-				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, ifa_flags);
+	case AF_INET:
+	case 255: /* FIXME: Why 255? */
+	{
+		const struct sockaddr_in *sin;
+		struct in_addr addr, mask, bcast;
+		int flags;
+
+		sin = (const void *)rti_info[RTAX_IFA];
+		addr.s_addr = sin != NULL && sin->sin_family == AF_INET ?
+		    sin->sin_addr.s_addr : INADDR_ANY;
+		sin = (const void *)rti_info[RTAX_NETMASK];
+		mask.s_addr = sin != NULL && sin->sin_family == AF_INET ?
+		    sin->sin_addr.s_addr : INADDR_ANY;
+		sin = (const void *)rti_info[RTAX_BRD];
+		bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ?
+		    sin->sin_addr.s_addr : INADDR_ANY;
+		if (ifam->ifam_type == RTM_NEWADDR) {
+			if ((flags = if_addrflags(&addr, ifp)) == -1)
 				break;
+		} else
+			flags = 0;
+		ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name,
+		    &addr, &mask, &bcast, flags);
+		break;
+	}
 #endif
 #ifdef INET6
-			case AF_INET6:
-				sin6 = (void *)rti_info[RTAX_IFA];
-				ia6 = sin6->sin6_addr;
-				DESCOPE(&ia6);
-				sin6 = (void *)rti_info[RTAX_NETMASK];
-				net6 = sin6->sin6_addr;
-				DESCOPE(&net6);
-				if (rtm->rtm_type == RTM_NEWADDR) {
-					ifa_flags = if_addrflags6(&ia6, ifp);
-					if (ifa_flags == -1)
-						break;
-				} else
-					ifa_flags = 0;
-				ipv6_handleifa(ctx, rtm->rtm_type, NULL,
-				    ifp->name, &ia6, ipv6_prefixlen(&net6),
-				    ifa_flags);
+	case AF_INET6:
+	{
+		struct in6_addr addr6, mask6;
+		const struct sockaddr_in6 *sin6;
+		int flags;
+
+		sin6 = (const void *)rti_info[RTAX_IFA];
+		addr6 = sin6->sin6_addr;
+		DESCOPE(&addr6);
+		sin6 = (const void *)rti_info[RTAX_NETMASK];
+		mask6 = sin6->sin6_addr;
+		DESCOPE(&mask6);
+		if (ifam->ifam_type == RTM_NEWADDR) {
+			if ((flags = if_addrflags6(&addr6, ifp)) == -1)
 				break;
+		} else
+			flags = 0;
+		ipv6_handleifa(ctx, ifam->ifam_type, NULL,
+		    ifp->name, &addr6, ipv6_prefixlen(&mask6), flags);
+		break;
+	}
 #endif
-			}
-			break;
-		}
+	}
+}
+
+static void
+if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
+{
+
+	switch(rtm->rtm_type) {
+#ifdef RTM_IFANNOUNCE
+	case RTM_IFANNOUNCE:
+		if_announce(ctx, (const void *)rtm);
+		break;
+#endif
+	case RTM_IFINFO:
+		if_ifinfo(ctx, (const void *)rtm);
+		break;
+	case RTM_ADD:		/* FALLTHROUGH */
+	case RTM_CHANGE:	/* FALLTHROUGH */
+	case RTM_DELETE:
+		if_rtm(ctx, (const void *)rtm);
+		break;
+#ifdef RTM_CHGADDR
+	case RTM_CHGADDR:	/* FALLTHROUGH */
+#endif
+	case RTM_DELADDR:	/* FALLTHROUGH */
+	case RTM_NEWADDR:
+		if_ifa(ctx, (const void *)rtm);
+		break;
+	}
+}
+
+int
+if_handlelink(struct dhcpcd_ctx *ctx)
+{
+	/* route and ifwatchd like a msg buf size of 2048 */
+	char buf[2048];
+	const char *p, *e;
+	size_t msglen;
+	ssize_t bytes;
+	const struct rt_msghdr *rtm;
+
+	if ((bytes = read(ctx->link_fd, buf, sizeof(buf))) == -1)
+		return -1;
+	e = buf + bytes;
+	for (p = buf; p < e; p += msglen) {
+		rtm = (const void *)p;
+		msglen = rtm->rtm_msglen;
+		if_dispatch(ctx, rtm);
 	}
 	return 0;
 }

Index: src/external/bsd/dhcpcd/dist/if-options.c
diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.33 src/external/bsd/dhcpcd/dist/if-options.c:1.34
--- src/external/bsd/dhcpcd/dist/if-options.c:1.33	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/if-options.c	Fri Jun 17 19:42:31 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-options.c,v 1.33 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: if-options.c,v 1.34 2016/06/17 19:42:31 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -1093,7 +1093,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				*fp = ' ';
 				return -1;
 			}
-			if (parse_addr(ctx, &rt->dest, &rt->net, p) == -1 ||
+			if (parse_addr(ctx, &rt->dest, &rt->mask, p) == -1 ||
 			    parse_addr(ctx, &rt->gate, NULL, np) == -1)
 			{
 				free(rt);
@@ -1118,7 +1118,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				return -1;
 			}
 			rt->dest.s_addr = INADDR_ANY;
-			rt->net.s_addr = INADDR_ANY;
+			rt->mask.s_addr = INADDR_ANY;
 			if (parse_addr(ctx, &rt->gate, NULL, p) == -1) {
 				free(rt);
 				return -1;

Index: src/external/bsd/dhcpcd/dist/ipv4.c
diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.22 src/external/bsd/dhcpcd/dist/ipv4.c:1.23
--- src/external/bsd/dhcpcd/dist/ipv4.c:1.22	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/ipv4.c	Fri Jun 17 19:42:32 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4.c,v 1.22 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: ipv4.c,v 1.23 2016/06/17 19:42:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -116,7 +116,7 @@ ipv4_getnetmask(uint32_t addr)
 
 struct ipv4_addr *
 ipv4_iffindaddr(struct interface *ifp,
-    const struct in_addr *addr, const struct in_addr *net)
+    const struct in_addr *addr, const struct in_addr *mask)
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
@@ -125,7 +125,7 @@ ipv4_iffindaddr(struct interface *ifp,
 	if (state) {
 		TAILQ_FOREACH(ap, &state->addrs, next) {
 			if ((addr == NULL || ap->addr.s_addr == addr->s_addr) &&
-			    (net == NULL || ap->net.s_addr == net->s_addr))
+			    (mask == NULL || ap->mask.s_addr == mask->s_addr))
 				return ap;
 		}
 	}
@@ -157,8 +157,8 @@ ipv4_iffindmaskaddr(struct interface *if
 	state = IPV4_STATE(ifp);
 	if (state) {
 		TAILQ_FOREACH (ap, &state->addrs, next) {
-			if ((ap->addr.s_addr & ap->net.s_addr) ==
-			    (addr->s_addr & ap->net.s_addr))
+			if ((ap->addr.s_addr & ap->mask.s_addr) ==
+			    (addr->s_addr & ap->mask.s_addr))
 				return ap;
 		}
 	}
@@ -206,31 +206,33 @@ ipv4_srcaddr(const struct rt *rt, struct
 
 	/* Prefer DHCP source address if matching */
 	dstate = D_CSTATE(rt->iface);
-	if (dstate &&
-	    rt->net.s_addr == dstate->net.s_addr &&
-	    rt->dest.s_addr == (dstate->addr.s_addr & dstate->net.s_addr))
+	if (dstate && dstate->addr &&
+	    rt->mask.s_addr == dstate->addr->mask.s_addr &&
+	    rt->dest.s_addr ==
+	    (dstate->addr->addr.s_addr & dstate->addr->mask.s_addr))
 	{
-		*addr = dstate->addr;
+		*addr = dstate->addr->addr;
 		return 1;
 	}
 
 	/* Then IPv4LL source address if matching */
 	istate = IPV4LL_CSTATE(rt->iface);
-	if (istate &&
-	    rt->net.s_addr == inaddr_llmask.s_addr &&
-	    rt->dest.s_addr == (istate->addr.s_addr & inaddr_llmask.s_addr))
+	if (istate && istate->addr &&
+	    rt->mask.s_addr == istate->addr->mask.s_addr &&
+	    rt->dest.s_addr ==
+	    (istate->addr->addr.s_addr & istate->addr->mask.s_addr))
 	{
-		*addr = istate->addr;
+		*addr = istate->addr->addr;
 		return 1;
 	}
 
 	/* If neither match, return DHCP then IPv4LL */
-	if (dstate) {
-		*addr = dstate->addr;
+	if (dstate && dstate->addr) {
+		*addr = dstate->addr->addr;
 		return 0;
 	}
-	if (istate) {
-		*addr = istate->addr;
+	if (istate && istate->addr) {
+		*addr = istate->addr->addr;
 		return 0;
 	}
 
@@ -248,8 +250,8 @@ ipv4_hasaddr(const struct interface *ifp
 	istate = IPV4LL_CSTATE(ifp);
 	return ((dstate &&
 	    dstate->added == STATE_ADDED &&
-	    dstate->addr.s_addr != INADDR_ANY) ||
-	    (istate && istate->addr.s_addr != INADDR_ANY));
+	    dstate->addr != NULL) ||
+	    (istate && istate->addr));
 }
 
 void
@@ -281,25 +283,6 @@ ipv4_init(struct dhcpcd_ctx *ctx)
 	return 0;
 }
 
-int
-ipv4_protocol_fd(const struct interface *ifp, uint16_t protocol)
-{
-
-	if (protocol == ETHERTYPE_ARP) {
-		const struct iarp_state *istate;
-
-		istate = ARP_CSTATE(ifp);
-		assert(istate != NULL);
-		return istate->fd;
-	} else {
-		const struct dhcp_state *dstate;
-
-		dstate = D_CSTATE(ifp);
-		assert(dstate != NULL);
-		return dstate->raw_fd;
-	}
-}
-
 /* Interface comparer for working out ordering. */
 int
 ipv4_ifcmp(const struct interface *si, const struct interface *ti)
@@ -349,7 +332,7 @@ find_route(struct rt_head *rts, const st
 		    rt->iface->metric == r->iface->metric)) &&
 #endif
                     (!srt || srt != rt) &&
-		    rt->net.s_addr == r->net.s_addr)
+		    rt->mask.s_addr == r->mask.s_addr)
 			return rt;
 	}
 	return NULL;
@@ -363,28 +346,28 @@ 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->net.s_addr == htonl(INADDR_BROADCAST) &&
+	if (rt->mask.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->net.s_addr == htonl(INADDR_BROADCAST))
+	else if (rt->mask.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 == htonl(INADDR_ANY) &&
-	    rt->net.s_addr == htonl(INADDR_ANY) &&
+	    rt->mask.s_addr == htonl(INADDR_ANY) &&
 	    rt->gate.s_addr == htonl(INADDR_ANY))
 		logger(ctx, LOG_INFO, "%s: %s default route",
 		    ifname, cmd);
 	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));
+		    ifname, cmd, addr, inet_ntocidr(rt->mask));
 	else if (rt->dest.s_addr == htonl(INADDR_ANY) &&
-	    rt->net.s_addr == htonl(INADDR_ANY))
+	    rt->mask.s_addr == htonl(INADDR_ANY))
 		logger(ctx, LOG_INFO, "%s: %s default route via %s",
 		    ifname, cmd, inet_ntoa(rt->gate));
 	else
 		logger(ctx, LOG_INFO, "%s: %s route to %s/%d via %s",
-		    ifname, cmd, addr, inet_ntocidr(rt->net),
+		    ifname, cmd, addr, inet_ntocidr(rt->mask),
 		    inet_ntoa(rt->gate));
 }
 
@@ -403,7 +386,7 @@ ipv4_findrt(struct dhcpcd_ctx *ctx, cons
 #else
 		    (!flags || rt->iface == r->iface) &&
 #endif
-		    rt->net.s_addr == r->net.s_addr)
+		    rt->mask.s_addr == r->mask.s_addr)
 			return r;
 	}
 	return NULL;
@@ -467,7 +450,7 @@ nc_route(struct rt *ort, struct rt *nrt)
 
 	/* Don't set default routes if not asked to */
 	if (nrt->dest.s_addr == 0 &&
-	    nrt->net.s_addr == 0 &&
+	    nrt->mask.s_addr == 0 &&
 	    !(nrt->iface->options->options & DHCPCD_GATEWAY))
 		return -1;
 
@@ -494,7 +477,7 @@ nc_route(struct rt *ort, struct rt *nrt)
 	    ort->metric == nrt->metric &&
 #endif
 	    ort->dest.s_addr == nrt->dest.s_addr &&
-	    ort->net.s_addr ==  nrt->net.s_addr &&
+	    ort->mask.s_addr ==  nrt->mask.s_addr &&
 	    ort->gate.s_addr == nrt->gate.s_addr)
 	{
 		if (ort->mtu == nrt->mtu)
@@ -562,19 +545,23 @@ d_route(struct rt *rt)
 static struct rt_head *
 add_subnet_route(struct rt_head *rt, const struct interface *ifp)
 {
-	const struct dhcp_state *s;
+	const struct dhcp_state *state;
 	struct rt *r;
 
 	if (rt == NULL) /* earlier malloc failed */
 		return NULL;
 
-	s = D_CSTATE(ifp);
+	/* P2P interfaces don't have subnet routes as such. */
+	if (ifp->flags & IFF_POINTOPOINT)
+		return rt;
+
+	state = D_CSTATE(ifp);
 	/* Don't create a subnet route for these addresses */
-	if (s->net.s_addr == INADDR_ANY)
+	if (state->addr->mask.s_addr == INADDR_ANY)
 		return rt;
 #ifndef BSD
 	/* BSD adds a route in this instance */
-	if (s->net.s_addr == INADDR_BROADCAST)
+	if (state->addr->mask.s_addr == INADDR_BROADCAST)
 		return rt;
 #endif
 
@@ -583,11 +570,11 @@ add_subnet_route(struct rt_head *rt, con
 		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->dest.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
+	r->mask.s_addr = state->addr->mask.s_addr;
 	r->gate.s_addr = INADDR_ANY;
 	r->mtu = dhcp_get_mtu(ifp);
-	r->src = s->addr;
+	r->src = state->addr->addr;
 
 	TAILQ_INSERT_HEAD(rt, r, next);
 	return rt;
@@ -598,13 +585,13 @@ static struct rt_head *
 add_loopback_route(struct rt_head *rt, const struct interface *ifp)
 {
 	struct rt *r;
-	const struct dhcp_state *s;
+	const struct dhcp_state *state;
 
 	if (rt == NULL) /* earlier malloc failed */
 		return NULL;
 
-	s = D_CSTATE(ifp);
-	if (s->addr.s_addr == INADDR_ANY)
+	state = D_CSTATE(ifp);
+	if (state->addr == NULL)
 		return rt;
 
 	if ((r = calloc(1, sizeof(*r))) == NULL) {
@@ -612,11 +599,11 @@ add_loopback_route(struct rt_head *rt, c
 		ipv4_freeroutes(rt);
 		return NULL;
 	}
-	r->dest = s->addr;
-	r->net.s_addr = INADDR_BROADCAST;
+	r->dest = state->addr->addr;
+	r->mask.s_addr = INADDR_BROADCAST;
 	r->gate.s_addr = htonl(INADDR_LOOPBACK);
 	r->mtu = dhcp_get_mtu(ifp);
-	r->src = s->addr;
+	r->src = state->addr->addr;
 	TAILQ_INSERT_HEAD(rt, r, next);
 	return rt;
 }
@@ -651,7 +638,7 @@ get_routes(struct interface *ifp)
 	if (nrt) {
 		state = D_CSTATE(ifp);
 		TAILQ_FOREACH(rt, nrt, next) {
-			rt->src = state->addr;
+			rt->src = state->addr->addr;
 		}
 	}
 
@@ -676,10 +663,10 @@ add_destination_route(struct rt_head *rt
 		return NULL;
 	}
 	r->dest.s_addr = INADDR_ANY;
-	r->net.s_addr = INADDR_ANY;
-	r->gate.s_addr = state->brd.s_addr;
+	r->mask.s_addr = INADDR_ANY;
+	r->gate = state->addr->brd;
 	r->mtu = dhcp_get_mtu(ifp);
-	r->src = state->addr;
+	r->src = state->addr->addr;
 	TAILQ_INSERT_HEAD(rt, r, next);
 	return rt;
 }
@@ -697,6 +684,10 @@ add_router_host_route(struct rt_head *rt
 	if (rt == NULL) /* earlier malloc failed */
 		return NULL;
 
+	/* Don't add a host route for these interfaces. */
+	if (ifp->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+		return rt;
+
 	TAILQ_FOREACH(rtp, rt, next) {
 		if (rtp->dest.s_addr != INADDR_ANY)
 			continue;
@@ -710,8 +701,8 @@ add_router_host_route(struct rt_head *rt
 			/* match subnet */
 			cp = (const char *)&rtp->gate.s_addr;
 			cp2 = (const char *)&rtn->dest.s_addr;
-			cp3 = (const char *)&rtn->net.s_addr;
-			cplim = cp3 + sizeof(rtn->net.s_addr);
+			cp3 = (const char *)&rtn->mask.s_addr;
+			cplim = cp3 + sizeof(rtn->mask.s_addr);
 			while (cp3 < cplim) {
 				if ((*cp++ ^ *cp2++) & *cp3++)
 					break;
@@ -750,10 +741,10 @@ add_router_host_route(struct rt_head *rt
 			return NULL;
 		}
 		rtn->dest.s_addr = rtp->gate.s_addr;
-		rtn->net.s_addr = htonl(INADDR_BROADCAST);
+		rtn->mask.s_addr = htonl(INADDR_BROADCAST);
 		rtn->gate.s_addr = htonl(INADDR_ANY);
 		rtn->mtu = dhcp_get_mtu(ifp);
-		rtn->src = state->addr;
+		rtn->src = state->addr->addr;
 		TAILQ_INSERT_BEFORE(rtp, rtn, next);
 	}
 	return rt;
@@ -906,49 +897,42 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
 }
 
 int
-ipv4_deladdr(struct interface *ifp,
-    const struct in_addr *addr, const struct in_addr *net, int keeparp)
+ipv4_deladdr(struct ipv4_addr *addr, int keeparp)
 {
-	struct dhcp_state *dstate;
 	int r;
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
 	struct arp_state *astate;
-	uint32_t a, n;
 
-	logger(ifp->ctx, LOG_DEBUG,
-	    "%s: deleting IP address %s/%d",
-	    ifp->name, inet_ntoa(*addr), inet_ntocidr(*net));
+	logger(addr->iface->ctx, LOG_DEBUG,
+	    "%s: deleting IP address %s", addr->iface->name, addr->saddr);
 
-	r = if_deladdress(ifp, addr, net);
+	r = if_address(RTM_DELADDR, addr);
 	if (r == -1 && errno != EADDRNOTAVAIL && errno != ENXIO &&
 	    errno != ENODEV)
-		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
+		logger(addr->iface->ctx, LOG_ERR, "%s: %s: %m",
+		    addr->iface->name, __func__);
 
-	if (!keeparp && (astate = arp_find(ifp, addr)) != NULL)
+	if (!keeparp && (astate = arp_find(addr->iface, &addr->addr)) != NULL)
 		arp_free(astate);
 
-	a = addr->s_addr;
-	n = net->s_addr;
-	state = IPV4_STATE(ifp);
+	state = IPV4_STATE(addr->iface);
 	TAILQ_FOREACH(ap, &state->addrs, next) {
-		if (ap->addr.s_addr == addr->s_addr &&
-		    ap->net.s_addr == net->s_addr)
-		{
+		if (IPV4_MASK_EQ(ap, addr)) {
+			struct dhcp_state *dstate;
+
+			dstate = D_STATE(ap->iface);
 			TAILQ_REMOVE(&state->addrs, ap, next);
 			free(ap);
+
+			if (dstate && dstate->addr == ap) {
+				dstate->added = 0;
+				dstate->addr = NULL;
+			}
 			break;
 		}
 	}
 
-	/* Have to do this last incase the function arguments
-	 * were these very pointers. */
-	dstate = D_STATE(ifp);
-	if (dstate && dstate->addr.s_addr == a && dstate->net.s_addr == n) {
-		dstate->added = 0;
-		dstate->addr.s_addr = 0;
-		dstate->net.s_addr = 0;
-	}
 	return r;
 }
 
@@ -964,7 +948,7 @@ delete_address(struct interface *ifp)
 	if (ifo->options & DHCPCD_INFORM ||
 	    (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
 		return 0;
-	r = ipv4_deladdr(ifp, &state->addr, &state->net, 0);
+	r = ipv4_deladdr(state->addr, 0);
 	return r;
 }
 
@@ -997,7 +981,6 @@ ipv4_addaddr(struct interface *ifp, cons
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ia;
-	char bcast_str[INET_ADDRSTRLEN];
 
 	if ((state = ipv4_getstate(ifp)) == NULL) {
 		logger(ifp->ctx, LOG_ERR, "%s: ipv4_getstate: %m", __func__);
@@ -1008,7 +991,7 @@ ipv4_addaddr(struct interface *ifp, cons
 
 		TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ian) {
 			if (ia->addr.s_addr != addr->s_addr)
-				ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
+				ipv4_deladdr(ia, 0);
 		}
 	}
 
@@ -1017,10 +1000,18 @@ ipv4_addaddr(struct interface *ifp, cons
 		return NULL;
 	}
 
-	strlcpy(bcast_str, inet_ntoa(*bcast), sizeof(bcast_str));
-	logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s/%d broadcast %s",
-	    ifp->name, inet_ntoa(*addr), inet_ntocidr(*mask), bcast_str);
-	if (if_addaddress(ifp, addr, mask, bcast) == -1) {
+	ia->iface = ifp;
+	ia->addr = *addr;
+	ia->mask = *mask;
+	ia->brd = *bcast;
+#ifdef IN_IFF_TENTATIVE
+	ia->addr_flags = IN_IFF_TENTATIVE;
+#endif
+	snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
+	    inet_ntoa(*addr), inet_ntocidr(*mask));
+	logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s broadcast %s",
+	    ifp->name, ia->saddr, inet_ntoa(*bcast));
+	if (if_address(RTM_NEWADDR, ia) == -1) {
 		if (errno != EEXIST)
 			logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
 			    __func__);
@@ -1028,13 +1019,6 @@ ipv4_addaddr(struct interface *ifp, cons
 		return NULL;
 	}
 
-	ia->iface = ifp;
-	ia->addr = *addr;
-	ia->net = *mask;
-	ia->brd = *bcast;
-#ifdef IN_IFF_TENTATIVE
-	ia->addr_flags = IN_IFF_TENTATIVE;
-#endif
 	TAILQ_INSERT_TAIL(&state->addrs, ia, next);
 	return ia;
 }
@@ -1043,16 +1027,15 @@ static int
 ipv4_daddaddr(struct interface *ifp, const struct dhcp_lease *lease)
 {
 	struct dhcp_state *state;
+	struct ipv4_addr *ia;
 
-	if (ipv4_addaddr(ifp, &lease->addr, &lease->net, &lease->brd) == NULL)
+	ia = ipv4_addaddr(ifp, &lease->addr, &lease->mask, &lease->brd);
+	if (ia == NULL)
 		return -1;
 
 	state = D_STATE(ifp);
 	state->added = STATE_ADDED;
-
-	state->addr.s_addr = lease->addr.s_addr;
-	state->net.s_addr = lease->net.s_addr;
-
+	state->addr = ia;
 	return 0;
 }
 
@@ -1075,7 +1058,8 @@ ipv4_preferanother(struct interface *ifp
 			break; /* We are already the most preferred */
 		nstate = D_STATE(ifn);
 		if (nstate && !nstate->added &&
-		    nstate->lease.addr.s_addr == state->addr.s_addr)
+		    state->addr != NULL &&
+		    nstate->lease.addr.s_addr == state->addr->addr.s_addr)
 		{
 			preferred = 1;
 			delete_address(ifp);
@@ -1101,7 +1085,7 @@ ipv4_applyaddr(void *arg)
 	struct dhcp_state *state = D_STATE(ifp), *nstate;
 	struct dhcp_lease *lease;
 	struct if_options *ifo = ifp->options;
-	struct ipv4_addr *ap;
+	struct ipv4_addr *ia;
 	int r;
 
 	if (state == NULL)
@@ -1133,7 +1117,8 @@ ipv4_applyaddr(void *arg)
 		}
 		nstate = D_STATE(ifn);
 		if (nstate && nstate->added &&
-		    nstate->addr.s_addr == lease->addr.s_addr)
+		    nstate->addr &&
+		    nstate->addr->addr.s_addr == lease->addr.s_addr)
 		{
 			if (r == 0) {
 				logger(ifp->ctx, LOG_INFO,
@@ -1147,7 +1132,7 @@ ipv4_applyaddr(void *arg)
 			    ifn->name,
 			    inet_ntoa(lease->addr),
 			    ifp->name);
-			ipv4_deladdr(ifn, &nstate->addr, &nstate->net, 0);
+			ipv4_deladdr(nstate->addr, 0);
 			break;
 		}
 	}
@@ -1157,64 +1142,63 @@ ipv4_applyaddr(void *arg)
 		TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
 			if (ifn == ifp)
 				continue;
-			ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
-			if (ap)
-				ipv4_deladdr(ifn, &ap->addr, &ap->net, 0);
+			ia = ipv4_iffindaddr(ifn, &lease->addr, NULL);
+			if (ia != NULL)
+				ipv4_deladdr(ia, 0);
 		}
 	}
 
 	/* If the netmask or broadcast is different, re-add the addresss */
-	ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
-	if (ap &&
-	    ap->net.s_addr == lease->net.s_addr &&
-	    ap->brd.s_addr == lease->brd.s_addr)
+	ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+	if (ia &&
+	    ia->mask.s_addr == lease->mask.s_addr &&
+	    ia->brd.s_addr == lease->brd.s_addr)
 		logger(ifp->ctx, LOG_DEBUG,
-		    "%s: IP address %s/%d already exists",
-		    ifp->name, inet_ntoa(lease->addr),
-		    inet_ntocidr(lease->net));
+		    "%s: IP address %s already exists",
+		    ifp->name, ia->saddr);
 	else {
 #if __linux__
 		/* Linux does not change netmask/broadcast address
 		 * for re-added addresses, so we need to delete the old one
 		 * first. */
-		if (ap != NULL)
-			ipv4_deladdr(ifp, &ap->addr, &ap->net, 0);
+		if (ia != NULL)
+			ipv4_deladdr(ia, 0);
 #endif
 		r = ipv4_daddaddr(ifp, lease);
 		if (r == -1 && errno != EEXIST)
 			return;
 	}
 
-#ifdef IN_IFF_NOTUSEABLE
-	ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
-	if (ap == NULL) {
+	ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+	if (ia == NULL) {
 		logger(ifp->ctx, LOG_ERR, "%s: added address vanished",
 		    ifp->name);
 		return;
-	} else if (ap->addr_flags & IN_IFF_NOTUSEABLE)
+	}
+#ifdef IN_IFF_NOTUSEABLE
+	if (ia->addr_flags & IN_IFF_NOTUSEABLE)
 		return;
 #endif
 
 	/* Delete the old address if different */
-	if (state->addr.s_addr != lease->addr.s_addr &&
-	    state->addr.s_addr != 0 &&
+	if (state->addr &&
+	    state->addr->addr.s_addr != lease->addr.s_addr &&
 	    ipv4_iffindaddr(ifp, &lease->addr, NULL))
 		delete_address(ifp);
 
+	state->addr = ia;
 	state->added = STATE_ADDED;
-	state->addr.s_addr = lease->addr.s_addr;
-	state->net.s_addr = lease->net.s_addr;
 
 	/* 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);
+	if_initrt(ifp->ctx);
 	ipv4_buildroutes(ifp->ctx);
 	/* Announce the address */
 	if (ifo->options & DHCPCD_ARP) {
 		struct arp_state *astate;
 
-		if ((astate = arp_new(ifp, &state->addr)) != NULL)
+		if ((astate = arp_new(ifp, &state->addr->addr)) != NULL)
 			arp_announce(astate);
 	}
 	if (state->state == DHS_BOUND) {
@@ -1226,12 +1210,12 @@ ipv4_applyaddr(void *arg)
 void
 ipv4_handleifa(struct dhcpcd_ctx *ctx,
     int cmd, struct if_head *ifs, const char *ifname,
-    const struct in_addr *addr, const struct in_addr *net,
+    const struct in_addr *addr, const struct in_addr *mask,
     const struct in_addr *brd, int flags)
 {
 	struct interface *ifp;
 	struct ipv4_state *state;
-	struct ipv4_addr *ap;
+	struct ipv4_addr *ia;
 
 	if (ifs == NULL)
 		ifs = ctx->ifaces;
@@ -1239,10 +1223,6 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
 		errno = ESRCH;
 		return;
 	}
-	if (addr->s_addr == INADDR_ANY) {
-		errno = EINVAL;
-		return;
-	}
 	if ((ifp = if_find(ifs, ifname)) == NULL)
 		return;
 	if ((state = ipv4_getstate(ifp)) == NULL) {
@@ -1250,43 +1230,58 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
 		return;
 	}
 
-	ap = ipv4_iffindaddr(ifp, addr, NULL);
-	if (cmd == RTM_NEWADDR) {
-		if (ap == NULL) {
-			if ((ap = malloc(sizeof(*ap))) == NULL) {
+	ia = ipv4_iffindaddr(ifp, addr, NULL);
+	switch (cmd) {
+	case RTM_NEWADDR:
+		if (ia == NULL) {
+			if ((ia = malloc(sizeof(*ia))) == NULL) {
 				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
 				return;
 			}
-			ap->iface = ifp;
-			ap->addr = *addr;
-			TAILQ_INSERT_TAIL(&state->addrs, ap, next);
-		}
-		ap->net = *net;
-		ap->brd = *brd;
-		ap->addr_flags = flags;
-	} else if (cmd == RTM_DELADDR) {
-		if (ap) {
-			TAILQ_REMOVE(&state->addrs, ap, next);
-			free(ap);
-		}
+			ia->iface = ifp;
+			ia->addr = *addr;
+			TAILQ_INSERT_TAIL(&state->addrs, ia, next);
+		}
+		/* Mask could have changed */
+		ia->mask = *mask;
+		snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
+		    inet_ntoa(*addr), inet_ntocidr(*mask));
+		if (brd != NULL)
+			ia->brd = *brd;
+		else
+			ia->brd.s_addr = INADDR_ANY;
+		ia->addr_flags = flags;
+		break;
+	case RTM_DELADDR:
+		if (ia == NULL)
+			return;
+		TAILQ_REMOVE(&state->addrs, ia, next);
+		break;
+	default:
+		return;
 	}
 
-	arp_handleifa(cmd, ifp, addr, flags);
-	dhcp_handleifa(cmd, ifp, addr, net, brd, flags);
+	if (addr->s_addr != INADDR_ANY && addr->s_addr != INADDR_BROADCAST) {
+		arp_handleifa(cmd, ia);
+		dhcp_handleifa(cmd, ia);
+	}
+
+	if (cmd == RTM_DELADDR)
+		free(ia);
 }
 
 void
 ipv4_free(struct interface *ifp)
 {
 	struct ipv4_state *state;
-	struct ipv4_addr *addr;
+	struct ipv4_addr *ia;
 
 	if (ifp) {
 		state = IPV4_STATE(ifp);
 		if (state) {
-		        while ((addr = TAILQ_FIRST(&state->addrs))) {
-				TAILQ_REMOVE(&state->addrs, addr, next);
-				free(addr);
+		        while ((ia = TAILQ_FIRST(&state->addrs))) {
+				TAILQ_REMOVE(&state->addrs, ia, next);
+				free(ia);
 			}
 			ipv4_freerts(&state->routes);
 #ifdef BSD

Index: src/external/bsd/dhcpcd/dist/ipv4ll.h
diff -u src/external/bsd/dhcpcd/dist/ipv4ll.h:1.11 src/external/bsd/dhcpcd/dist/ipv4ll.h:1.12
--- src/external/bsd/dhcpcd/dist/ipv4ll.h:1.11	Sun Apr 10 21:00:53 2016
+++ src/external/bsd/dhcpcd/dist/ipv4ll.h	Fri Jun 17 19:42:32 2016
@@ -1,8 +1,8 @@
-/* $NetBSD: ipv4ll.h,v 1.11 2016/04/10 21:00:53 roy Exp $ */
+/* $NetBSD: ipv4ll.h,v 1.12 2016/06/17 19:42:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <r...@marples.name>
+ * Copyright (c) 2006-2016 Roy Marples <r...@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -33,19 +33,16 @@
 #ifdef INET
 #include "arp.h"
 
-extern const struct in_addr inaddr_llmask;
-extern const struct in_addr inaddr_llbcast;
-
 #define LINKLOCAL_ADDR	0xa9fe0000
 #define LINKLOCAL_MASK	IN_CLASSB_NET
-#define LINKLOCAL_BRDC	(LINKLOCAL_ADDR | ~LINKLOCAL_MASK)
+#define LINKLOCAL_BCAST	(LINKLOCAL_ADDR | ~LINKLOCAL_MASK)
 
 #ifndef IN_LINKLOCAL
 # define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == LINKLOCAL_ADDR)
 #endif
 
 struct ipv4ll_state {
-	struct in_addr addr;
+	struct ipv4_addr *addr;
 	struct arp_state *arp;
 	unsigned int conflicts;
 	struct timespec defend;
@@ -58,8 +55,8 @@ struct ipv4ll_state {
 #define IPV4LL_CSTATE(ifp)						       \
 	((const struct ipv4ll_state *)(ifp)->if_data[IF_DATA_IPV4LL])
 #define IPV4LL_STATE_RUNNING(ifp)					       \
-	(IPV4LL_CSTATE((ifp)) && !IPV4LL_CSTATE((ifp))->down &&	       \
-	IN_LINKLOCAL(ntohl(IPV4LL_CSTATE((ifp))->addr.s_addr)))
+	(IPV4LL_CSTATE((ifp)) && !IPV4LL_CSTATE((ifp))->down &&		       \
+	(IPV4LL_CSTATE((ifp))->addr != NULL))
 
 struct rt* ipv4ll_subnet_route(const struct interface *);
 struct rt* ipv4ll_default_route(const struct interface *);

Index: src/external/bsd/dhcpcd/dist/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.18 src/external/bsd/dhcpcd/dist/ipv6.c:1.19
--- src/external/bsd/dhcpcd/dist/ipv6.c:1.18	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/ipv6.c	Fri Jun 17 19:42:32 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6.c,v 1.18 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: ipv6.c,v 1.19 2016/06/17 19:42:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -592,9 +592,9 @@ ipv6_deleteaddr(struct ipv6_addr *ia)
 
 	logger(ia->iface->ctx, LOG_INFO, "%s: deleting address %s",
 	    ia->iface->name, ia->saddr);
-	if (if_deladdress6(ia) == -1 &&
+	if (if_address6(RTM_DELADDR, ia) == -1 &&
 	    errno != EADDRNOTAVAIL && errno != ENXIO && errno != ENODEV)
-		logger(ia->iface->ctx, LOG_ERR, "if_deladdress6: :%m");
+		logger(ia->iface->ctx, LOG_ERR, "if_address6: :%m");
 
 	/* NOREJECT is set if we delegated exactly the prefix to another
 	 * address.
@@ -704,7 +704,7 @@ ipv6_addaddr(struct ipv6_addr *ap, const
 #endif
 	}
 
-	if (if_addaddress6(ap) == -1) {
+	if (if_address6(RTM_NEWADDR, ap) == -1) {
 		logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
 		/* Restore real pltime and vltime */
 		ap->prefix_pltime = pltime;
@@ -827,10 +827,10 @@ ipv6_addaddrs(struct ipv6_addrhead *addr
 				    apf->iface->name,
 				    ap->saddr,
 				    ap->iface->name);
-				if (if_deladdress6(apf) == -1 &&
+				if (if_address6(RTM_DELADDR, apf) == -1 &&
 				    errno != EADDRNOTAVAIL && errno != ENXIO)
 					logger(apf->iface->ctx, LOG_ERR,
-					    "if_deladdress6: %m");
+					    "if_address6: %m");
 				apf->flags &=
 				    ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
 			} else if (apf)
@@ -1453,7 +1453,7 @@ ipv6_startstatic(struct interface *ifp)
 	ia->prefix_pltime = ND6_INFINITE_LIFETIME;
 	ia->dadcallback = ipv6_staticdadcallback;
 	ipv6_addaddr(ia, NULL);
-	if_initrt6(ifp);
+	if_initrt6(ifp->ctx);
 	ipv6_buildroutes(ifp->ctx);
 	if (run_script)
 		script_runreason(ifp, "STATIC6");
@@ -1476,7 +1476,7 @@ ipv6_start(struct interface *ifp)
 	}
 
 	/* Load existing routes */
-	if_initrt6(ifp);
+	if_initrt6(ifp->ctx);
 	if (!IN6_IS_ADDR_UNSPECIFIED(&ifp->options->req_addr6))
 		ipv6_buildroutes(ifp->ctx);
 	return 0;
@@ -1497,7 +1497,7 @@ ipv6_freedrop(struct interface *ifp, int
 	ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, NULL);
 	if (drop) {
 		if (ifp->ctx->ipv6 != NULL) {
-			if_initrt6(ifp);
+			if_initrt6(ifp->ctx);
 			ipv6_buildroutes(ifp->ctx);
 		}
 	} else {
@@ -1955,7 +1955,7 @@ find_route6(struct rt6_head *rts, const 
 		    (r->iface == NULL || rt->iface == NULL ||
 		    rt->iface->metric == r->iface->metric) &&
 #endif
-		    IN6_ARE_ADDR_EQUAL(&rt->net, &r->net))
+		    IN6_ARE_ADDR_EQUAL(&rt->mask, &r->mask))
 			return rt;
 	}
 	return NULL;
@@ -1975,16 +1975,16 @@ desc_route(const char *cmd, const struct
 	gate = inet_ntop(AF_INET6, &rt->gate, gatebuf, INET6_ADDRSTRLEN);
 	if (IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_any))
 		logger(ctx, LOG_INFO, "%s: %s route to %s/%d",
-		    ifname, cmd, dest, ipv6_prefixlen(&rt->net));
+		    ifname, cmd, dest, ipv6_prefixlen(&rt->mask));
 	else if (IN6_ARE_ADDR_EQUAL(&rt->dest, &in6addr_any) &&
-	    IN6_ARE_ADDR_EQUAL(&rt->net, &in6addr_any))
+	    IN6_ARE_ADDR_EQUAL(&rt->mask, &in6addr_any))
 		logger(ctx, LOG_INFO, "%s: %s default route via %s",
 		    ifname, cmd, gate);
 	else
 		logger(ctx, LOG_INFO, "%s: %s%s route to %s/%d via %s",
 		    ifname, cmd,
 		    rt->flags & RTF_REJECT ? " reject" : "",
-		    dest, ipv6_prefixlen(&rt->net), gate);
+		    dest, ipv6_prefixlen(&rt->mask), gate);
 }
 
 static struct rt6*
@@ -2002,7 +2002,7 @@ ipv6_findrt(struct dhcpcd_ctx *ctx, cons
 		    (!flags || rt->iface == r->iface ||
 		    (rt->flags & RTF_REJECT && r->flags & RTF_REJECT)) &&
 #endif
-		    IN6_ARE_ADDR_EQUAL(&rt->net, &r->net))
+		    IN6_ARE_ADDR_EQUAL(&rt->mask, &r->mask))
 			return r;
 	}
 	return NULL;
@@ -2064,7 +2064,7 @@ nc_route(struct rt6 *ort, struct rt6 *nr
 
 	/* Don't set default routes if not asked to */
 	if (IN6_IS_ADDR_UNSPECIFIED(&nrt->dest) &&
-	    IN6_IS_ADDR_UNSPECIFIED(&nrt->net) &&
+	    IN6_IS_ADDR_UNSPECIFIED(&nrt->mask) &&
 	    !(nrt->iface->options->options & DHCPCD_GATEWAY))
 		return -1;
 
@@ -2208,7 +2208,7 @@ make_prefix(const struct interface *ifp,
 	if (r == NULL)
 		return NULL;
 	r->dest = addr->prefix;
-	ipv6_mask(&r->net, addr->prefix_len);
+	ipv6_mask(&r->mask, addr->prefix_len);
 	if (addr->flags & IPV6_AF_DELEGATEDPFX) {
 		r->flags |= RTF_REJECT;
 		r->gate = in6addr_loopback;
@@ -2226,14 +2226,14 @@ make_router(const struct ra *rap)
 	if (r == NULL)
 		return NULL;
 	r->dest = in6addr_any;
-	r->net = in6addr_any;
+	r->mask = in6addr_any;
 	r->gate = rap->from;
 	return r;
 }
 
 #define RT_IS_DEFAULT(rtp) \
 	(IN6_ARE_ADDR_EQUAL(&((rtp)->dest), &in6addr_any) &&		      \
-	    IN6_ARE_ADDR_EQUAL(&((rtp)->net), &in6addr_any))
+	    IN6_ARE_ADDR_EQUAL(&((rtp)->mask), &in6addr_any))
 
 static void
 ipv6_build_static_routes(struct dhcpcd_ctx *ctx, struct rt6_head *dnr)
Index: src/external/bsd/dhcpcd/dist/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.18 src/external/bsd/dhcpcd/dist/ipv6.h:1.19
--- src/external/bsd/dhcpcd/dist/ipv6.h:1.18	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/ipv6.h	Fri Jun 17 19:42:32 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6.h,v 1.18 2016/05/09 10:15:59 roy Exp $ */
+/* $NetBSD: ipv6.h,v 1.19 2016/06/17 19:42:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -183,14 +183,15 @@ struct ipv6_addr {
 #define	IPV6_AF_NOREJECT	0x0200
 #define	IPV6_AF_REQUEST		0x0400
 #define	IPV6_AF_STATIC		0x0800
+#define IPV6_AF_DELEGATEDLOG	0x1000
 #ifdef IPV6_MANAGETEMPADDR
-#define	IPV6_AF_TEMPORARY	0X1000
+#define	IPV6_AF_TEMPORARY	0X2000
 #endif
 
 struct rt6 {
 	TAILQ_ENTRY(rt6) next;
 	struct in6_addr dest;
-	struct in6_addr net;
+	struct in6_addr mask;
 	struct in6_addr gate;
 	const struct interface *iface;
 	unsigned int flags;

Index: src/external/bsd/dhcpcd/dist/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.29 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.30
--- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.29	Wed Apr 20 08:53:01 2016
+++ src/external/bsd/dhcpcd/dist/ipv6nd.c	Fri Jun 17 19:42:32 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6nd.c,v 1.29 2016/04/20 08:53:01 roy Exp $");
+ __RCSID("$NetBSD: ipv6nd.c,v 1.30 2016/06/17 19:42:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -258,15 +258,6 @@ ipv6nd_makersprobe(struct interface *ifp
 	return 0;
 }
 
-static void ipv6nd_dropdhcp6(struct interface *ifp)
-{
-	const struct dhcp6_state *d6;
-
-	/* Don't drop DHCP6 if the interface is delegated to. */
-	if ((d6 = D6_CSTATE(ifp)) != NULL && d6->state != DH6S_DELEGATED)
-		dhcp6_drop(ifp, "EXPIRE6");
-}
-
 static void
 ipv6nd_sendrsprobe(void *arg)
 {
@@ -330,7 +321,7 @@ ipv6nd_sendrsprobe(void *arg)
 		logger(ifp->ctx, LOG_WARNING,
 		    "%s: no IPv6 Routers available", ifp->name);
 		ipv6nd_drop(ifp);
-		ipv6nd_dropdhcp6(ifp);
+		dhcp6_dropnondelegates(ifp);
 	}
 }
 
@@ -660,9 +651,9 @@ ipv6nd_dadcallback(void *arg)
 			}
 			logger(ifp->ctx, LOG_INFO, "%s: deleting address %s",
 				ifp->name, ap->saddr);
-			if (if_deladdress6(ap) == -1 &&
+			if (if_address6(RTM_DELADDR, ap) == -1 &&
 			    errno != EADDRNOTAVAIL && errno != ENXIO)
-				logger(ifp->ctx, LOG_ERR, "if_deladdress6: %m");
+				logger(ifp->ctx, LOG_ERR, "if_address6: %m");
 			dadcounter = ap->dadcounter;
 			if (ipv6_makestableprivate(&ap->addr,
 			    &ap->prefix, ap->prefix_len,
@@ -1102,7 +1093,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 	/* 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_initrt6(ifp);
+	if_initrt6(ifp->ctx);
 
 	ipv6_buildroutes(ifp->ctx);
 	if (ipv6nd_scriptrun(rap))
@@ -1395,7 +1386,7 @@ ipv6nd_expirera(void *arg)
 
 	/* No valid routers? Kill any DHCPv6. */
 	if (!validone)
-		ipv6nd_dropdhcp6(ifp);
+		dhcp6_dropnondelegates(ifp);
 }
 
 void

Index: src/external/bsd/dhcpcd/dist/script.c
diff -u src/external/bsd/dhcpcd/dist/script.c:1.26 src/external/bsd/dhcpcd/dist/script.c:1.27
--- src/external/bsd/dhcpcd/dist/script.c:1.26	Mon May  9 10:15:59 2016
+++ src/external/bsd/dhcpcd/dist/script.c	Fri Jun 17 19:42:32 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: script.c,v 1.26 2016/05/09 10:15:59 roy Exp $");
+ __RCSID("$NetBSD: script.c,v 1.27 2016/06/17 19:42:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -264,7 +264,7 @@ make_env(const struct interface *ifp, co
 			ra = 1;
 #endif
 #ifdef INET
-		else if (istate && istate->addr.s_addr != INADDR_ANY)
+		else if (istate && istate->addr != NULL)
 			ipv4ll = 1;
 		else
 			dhcp = 1;

Index: src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.8 src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.9
--- src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.8	Fri Aug 21 10:39:00 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf	Fri Jun 17 19:42:32 2016
@@ -1,4 +1,4 @@
-# $NetBSD: 20-resolv.conf,v 1.8 2015/08/21 10:39:00 roy Exp $
+# $NetBSD: 20-resolv.conf,v 1.9 2016/06/17 19:42:32 roy Exp $
 
 # Generate /etc/resolv.conf
 # Support resolvconf(8) if available
@@ -94,8 +94,8 @@ eval_nd_dns()
 
 	[ -z "$rdnss" -a -z "$dnssl" ] && return 1
 
-	new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
-	new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
+	[ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
+	[ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
 	j=$(($j + 1))
 	return 0
 }
@@ -116,8 +116,10 @@ add_resolv_conf()
 		j=1
 		eval_nd_dns || break
 	done
-	new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
-	new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
+	[ -n "$new_rdnss" ] && \
+	    new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
+	[ -n "$new_dnssl" ] && \
+	    new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
 
 	# Derive a new domain from our various hostname options
 	if [ -z "$new_domain_name" ]; then

Index: src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname:1.7 src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname:1.8
--- src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname:1.7	Fri Aug 21 10:39:00 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-hooks/30-hostname	Fri Jun 17 19:42:32 2016
@@ -1,4 +1,4 @@
-# $NetBSD: 30-hostname,v 1.7 2015/08/21 10:39:00 roy Exp $
+# $NetBSD: 30-hostname,v 1.8 2016/06/17 19:42:32 roy Exp $
 
 # Set the hostname from DHCP data if required
 
@@ -68,7 +68,7 @@ need_hostname()
 	
 	case "$hostname_fqdn" in
 	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)	hfqdn=true;;
-	[Ss][Ee][Rr][Vv][Ee][Rr])		;;
+	""|[Ss][Ee][Rr][Vv][Ee][Rr])		;;
 	*)					hshort=true;;
 	esac
 
@@ -117,7 +117,7 @@ set_hostname()
 
 	case "$hostname_fqdn" in
 	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)	hfqdn=true;;
-	"")					;;
+	""|[Ss][Ee][Rr][Vv][Ee][Rr])		;;
 	*)					hshort=true;;
 	esac
 

Reply via email to