Module Name:    src
Committed By:   roy
Date:           Sun Apr 10 21:00:53 UTC 2016

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

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/external/bsd/dhcpcd/dist/arp.c \
    src/external/bsd/dhcpcd/dist/ipv6.c src/external/bsd/dhcpcd/dist/ipv6.h
cvs rdiff -u -r1.18 -r1.19 src/external/bsd/dhcpcd/dist/common.c \
    src/external/bsd/dhcpcd/dist/dhcp6.c src/external/bsd/dhcpcd/dist/if.c
cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/common.h \
    src/external/bsd/dhcpcd/dist/dhcp-common.c \
    src/external/bsd/dhcpcd/dist/dhcp6.h
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/config.h \
    src/external/bsd/dhcpcd/dist/eloop.h
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/control.c \
    src/external/bsd/dhcpcd/dist/ipv4ll.h
cvs rdiff -u -r1.24 -r1.25 src/external/bsd/dhcpcd/dist/defs.h \
    src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \
    src/external/bsd/dhcpcd/dist/script.c
cvs rdiff -u -r1.37 -r1.38 src/external/bsd/dhcpcd/dist/dhcp.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcp.h \
    src/external/bsd/dhcpcd/dist/if.h src/external/bsd/dhcpcd/dist/ipv4ll.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.h
cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in \
    src/external/bsd/dhcpcd/dist/eloop.c
cvs rdiff -u -r1.31 -r1.32 src/external/bsd/dhcpcd/dist/dhcpcd.c
cvs rdiff -u -r1.15 -r1.16 src/external/bsd/dhcpcd/dist/dhcpcd.h \
    src/external/bsd/dhcpcd/dist/ipv4.h
cvs rdiff -u -r1.27 -r1.28 src/external/bsd/dhcpcd/dist/if-bsd.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.c
cvs rdiff -u -r1.30 -r1.31 src/external/bsd/dhcpcd/dist/if-options.c
cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/if-options.h
cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/ipv4.c

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

Modified files:

Index: src/external/bsd/dhcpcd/dist/arp.c
diff -u src/external/bsd/dhcpcd/dist/arp.c:1.16 src/external/bsd/dhcpcd/dist/arp.c:1.17
--- src/external/bsd/dhcpcd/dist/arp.c:1.16	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/arp.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: arp.c,v 1.16 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: arp.c,v 1.17 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -204,8 +204,7 @@ arp_open(struct interface *ifp)
 			    __func__, ifp->name);
 			return;
 		}
-		eloop_event_add(ifp->ctx->eloop, state->fd,
-		    arp_packet, ifp, NULL, NULL);
+		eloop_event_add(ifp->ctx->eloop, state->fd, arp_packet, ifp);
 	}
 }
 
Index: src/external/bsd/dhcpcd/dist/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.16 src/external/bsd/dhcpcd/dist/ipv6.c:1.17
--- src/external/bsd/dhcpcd/dist/ipv6.c:1.16	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/ipv6.c	Sun Apr 10 21:00:53 2016
@@ -1,9 +1,9 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6.c,v 1.16 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: ipv6.c,v 1.17 2016/04/10 21:00:53 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
@@ -40,6 +40,12 @@
 
 #include "config.h"
 
+#ifdef HAVE_SYS_BITOPS_H
+#include <sys/bitops.h>
+#else
+#include "compat/bitops.h"
+#endif
+
 #ifdef BSD
 /* Purely for the ND6_IFF_AUTO_LINKLOCAL #define which is solely used
  * to generate our CAN_ADD_LLADDR #define. */
@@ -62,6 +68,7 @@
 #include "eloop.h"
 #include "ipv6.h"
 #include "ipv6nd.h"
+#include "script.h"
 
 #ifdef HAVE_MD5_H
 #  ifndef DEPGEN
@@ -86,25 +93,6 @@
 #  warning polling tentative address flags periodically
 #endif
 
-#ifdef __linux__
-   /* Match Linux defines to BSD */
-#  define IN6_IFF_TEMPORARY IFA_F_TEMPORARY
-#  ifdef IFA_F_OPTIMISTIC
-#    define IN6_IFF_TENTATIVE	(IFA_F_TENTATIVE | IFA_F_OPTIMISTIC)
-#  else
-#    define IN6_IFF_TENTATIVE   (IFA_F_TENTATIVE | 0x04)
-#  endif
-#  ifdef IF_F_DADFAILED
-#    define IN6_IFF_DUPLICATED	IFA_F_DADFAILED
-#  else
-#    define IN6_IFF_DUPLICATED	0x08
-#  endif
-#  define IN6_IFF_DETACHED	0
-#endif
-
-#define IN6_IFF_NOTUSEABLE \
-	(IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED)
-
 /* Hackery at it's finest. */
 #ifndef s6_addr32
 #  ifdef __sun
@@ -184,38 +172,6 @@ ipv6_init(struct dhcpcd_ctx *dhcpcd_ctx)
 	return ctx;
 }
 
-ssize_t
-ipv6_printaddr(char *s, size_t sl, const uint8_t *d, const char *ifname)
-{
-	char buf[INET6_ADDRSTRLEN];
-	const char *p;
-	size_t l;
-
-	p = inet_ntop(AF_INET6, d, buf, sizeof(buf));
-	if (p == NULL)
-		return -1;
-
-	l = strlen(p);
-	if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80)
-		l += 1 + strlen(ifname);
-
-	if (s == NULL)
-		return (ssize_t)l;
-
-	if (sl < l) {
-		errno = ENOMEM;
-		return -1;
-	}
-
-	s += strlcpy(s, p, sl);
-	if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80) {
-		*s++ = '%';
-		s += strlcpy(s, ifname, sl);
-	}
-	*s = '\0';
-	return (ssize_t)l;
-}
-
 static ssize_t
 ipv6_readsecret(struct dhcpcd_ctx *ctx)
 {
@@ -275,11 +231,14 @@ ipv6_readsecret(struct dhcpcd_ctx *ctx)
 	    hwaddr_ntoa(ctx->secret, ctx->secret_len, line, sizeof(line)));
 	if (fclose(fp) == EOF)
 		x = -1;
+	fp = NULL;
 	if (x > 0)
 		return (ssize_t)ctx->secret_len;
 
 eexit:
 	logger(ctx, LOG_ERR, "error writing secret: %s: %m", SECRET);
+	if (fp != NULL)
+		fclose(fp);
 	unlink(SECRET);
 	ctx->secret_len = 0;
 	return -1;
@@ -409,7 +368,7 @@ ipv6_makestableprivate(struct in6_addr *
 }
 
 int
-ipv6_makeaddr(struct in6_addr *addr, const struct interface *ifp,
+ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp,
     const struct in6_addr *prefix, int prefix_len)
 {
 	const struct ipv6_addr *ap;
@@ -553,28 +512,40 @@ ipv6_userprefix(
 {
 	uint64_t vh, vl, user_low, user_high;
 
-	if (prefix_len < 0 || prefix_len > 120 ||
-	    result_len < 0 || result_len > 120)
+	if (prefix_len < 1 || prefix_len > 128 ||
+	    result_len < 1 || result_len > 128 ||
+	    user_number == 0)
 	{
 		errno = EINVAL;
 		return -1;
 	}
 
 	/* Check that the user_number fits inside result_len less prefix_len */
-	if (result_len < prefix_len || user_number > INT_MAX ||
-	    ffs((int)user_number) > result_len - prefix_len)
+	if (result_len < prefix_len ||
+	    fls64(user_number) > result_len - prefix_len)
 	{
 	       errno = ERANGE;
 	       return -1;
 	}
 
-	/* virtually shift user number by dest_len, then split at 64 */
-	if (result_len >= 64) {
-		user_high = user_number << (result_len - 64);
+	/* Shift user_number so it fit's just inside result_len.
+	 * Shifting by 0 or sizeof(user_number) is undefined,
+	 * so we cater for that. */
+	if (result_len == 128) {
+		user_high = 0;
+		user_low = user_number;
+	} else if (result_len > 64) {
+		if (prefix_len >= 64)
+			user_high = 0;
+		else
+			user_high = user_number >> (result_len - prefix_len);
+		user_low = user_number << (128 - result_len);
+	} else if (result_len == 64) {
+		user_high = user_number;
 		user_low = 0;
 	} else {
-		user_high = user_number >> (64 - result_len);
-		user_low = user_number << result_len;
+		user_high = user_number << (64 - result_len);
+		user_low = 0;
 	}
 
 	/* convert to two 64bit host order values */
@@ -662,7 +633,7 @@ ipv6_addaddr(struct ipv6_addr *ap, const
 	}
 
 	if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
-	    ipv6_iffindaddr(ap->iface, &ap->addr))
+	    ipv6_iffindaddr(ap->iface, &ap->addr, IN6_IFF_NOTUSEABLE))
 		ap->flags |= IPV6_AF_DADCOMPLETED;
 
 	logger(ap->iface->ctx, ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
@@ -773,13 +744,6 @@ ipv6_addaddr(struct ipv6_addr *ap, const
 	return 0;
 }
 
-int
-ipv6_publicaddr(const struct ipv6_addr *ia)
-{
-	return (ia->prefix_pltime &&
-	    (ia->addr.s6_addr[0] & 0xfe) != 0xfc &&
-	    !(ia->addr_flags & IN6_IFF_NOTUSEABLE));
-}
 
 int
 ipv6_findaddrmatch(const struct ipv6_addr *addr, const struct in6_addr *match,
@@ -1054,7 +1018,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 		if (ap->addr_flags & IN6_IFF_TEMPORARY)
 			ap->flags |= IPV6_AF_TEMPORARY;
 #endif
-		if (IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
+		if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) || ap->dadcallback) {
 #ifdef IPV6_POLLADDRFLAG
 			if (ap->addr_flags & IN6_IFF_TENTATIVE) {
 				struct timespec tv;
@@ -1067,7 +1031,12 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 			}
 #endif
 
-			if (!(ap->addr_flags & IN6_IFF_NOTUSEABLE)) {
+			if (ap->dadcallback)
+				ap->dadcallback(ap);
+
+			if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
+			    !(ap->addr_flags & IN6_IFF_NOTUSEABLE))
+			{
 				/* Now run any callbacks.
 				 * Typically IPv6RS or DHCPv6 */
 				while ((cb =
@@ -1096,22 +1065,23 @@ ipv6_hasaddr(const struct interface *ifp
 	return 0;
 }
 
-const struct ipv6_addr *
-ipv6_iffindaddr(const struct interface *ifp, const struct in6_addr *addr)
+struct ipv6_addr *
+ipv6_iffindaddr(struct interface *ifp, const struct in6_addr *addr,
+    int revflags)
 {
-	const struct ipv6_state *state;
-	const struct ipv6_addr *ap;
+	struct ipv6_state *state;
+	struct ipv6_addr *ap;
 
-	state = IPV6_CSTATE(ifp);
+	state = IPV6_STATE(ifp);
 	if (state) {
 		TAILQ_FOREACH(ap, &state->addrs, next) {
 			if (addr == NULL) {
 				if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
-				    !(ap->addr_flags & IN6_IFF_NOTUSEABLE))
+				    (!revflags || !(ap->addr_flags & revflags)))
 					return ap;
 			} else {
 				if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr) &&
-				    !(ap->addr_flags & IN6_IFF_TENTATIVE))
+				    (!revflags || !(ap->addr_flags & revflags)))
 					return ap;
 			}
 		}
@@ -1119,6 +1089,39 @@ ipv6_iffindaddr(const struct interface *
 	return NULL;
 }
 
+static struct ipv6_addr *
+ipv6_iffindmaskaddr(const struct interface *ifp, const struct in6_addr *addr)
+{
+	struct ipv6_state *state;
+	struct ipv6_addr *ap;
+	struct in6_addr mask;
+
+	state = IPV6_STATE(ifp);
+	if (state) {
+		TAILQ_FOREACH(ap, &state->addrs, next) {
+			if (ipv6_mask(&mask, ap->prefix_len) == -1)
+				continue;
+			if (IN6_ARE_MASKED_ADDR_EQUAL(&ap->addr, addr, &mask))
+				return ap;
+		}
+	}
+	return NULL;
+}
+
+struct ipv6_addr *
+ipv6_findmaskaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr)
+{
+	struct interface *ifp;
+	struct ipv6_addr *ap;
+
+	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+		ap = ipv6_iffindmaskaddr(ifp, addr);
+		if (ap != NULL)
+			return ap;
+	}
+	return NULL;
+}
+
 int
 ipv6_addlinklocalcallback(struct interface *ifp,
     void (*callback)(void *), void *arg)
@@ -1277,39 +1280,184 @@ nextslaacprivate:
 	return 1;
 }
 
-/* Ensure the interface has a link-local address */
-int
-ipv6_start(struct interface *ifp)
+static int
+ipv6_tryaddlinklocal(struct interface *ifp)
 {
-	const struct ipv6_state *state;
-	const struct ipv6_addr *ap;
 
 	/* We can't assign a link-locak address to this,
 	 * the ppp process has to. */
 	if (ifp->flags & IFF_POINTOPOINT)
 		return 0;
 
-	state = IPV6_CSTATE(ifp);
-	if (state) {
-		TAILQ_FOREACH(ap, &state->addrs, next) {
-			if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
-			    !(ap->addr_flags & IN6_IFF_DUPLICATED))
+	if (ipv6_iffindaddr(ifp, NULL, IN6_IFF_DUPLICATED) != NULL ||
+	    !CAN_ADD_LLADDR(ifp))
+		return 0;
+
+	return ipv6_addlinklocal(ifp);
+}
+
+static struct ipv6_addr *
+ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len)
+{
+	struct ipv6_addr *ia;
+	char buf[INET6_ADDRSTRLEN];
+	const char *cbp;
+
+	if ((ia = calloc(1, sizeof(*ia))) == NULL)
+		return NULL;
+	ia->iface = ifp;
+	ia->flags = IPV6_AF_NEW;
+	ia->addr_flags = IN6_IFF_TENTATIVE;
+	ia->addr = *addr;
+	ia->prefix_len = prefix_len;
+	if (ipv6_makeprefix(&ia->prefix, &ia->addr, ia->prefix_len) == -1) {
+		free(ia);
+		return NULL;
+	}
+	cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
+	if (cbp)
+		snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
+		    cbp, ia->prefix_len);
+	else
+		ia->saddr[0] = '\0';
+	return ia;
+}
+
+static void
+ipv6_staticdadcallback(void *arg)
+{
+	struct ipv6_addr *ia = arg;
+	int wascompleted;
+
+	wascompleted = (ia->flags & IPV6_AF_DADCOMPLETED);
+	ia->flags |= IPV6_AF_DADCOMPLETED;
+	if (ia->flags & IPV6_AF_DUPLICATED)
+		logger(ia->iface->ctx, LOG_WARNING, "%s: DAD detected %s",
+		    ia->iface->name, ia->saddr);
+	else if (!wascompleted) {
+		logger(ia->iface->ctx, LOG_DEBUG, "%s: IPv6 static DAD completed",
+		    ia->iface->name);
+	}
+
+#define FINISHED (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)
+	if (!wascompleted) {
+		struct interface *ifp;
+		struct ipv6_state *state;
+
+		ifp = ia->iface;
+		state = IPV6_STATE(ifp);
+		TAILQ_FOREACH(ia, &state->addrs, next) {
+			if (ia->flags & IPV6_AF_STATIC &&
+			    (ia->flags & FINISHED) != FINISHED)
+			{
+				wascompleted = 1;
 				break;
+			}
 		}
+		if (!wascompleted)
+			script_runreason(ifp, "STATIC6");
+	}
+#undef FINISHED
+}
+
+ssize_t
+ipv6_env(char **env, const char *prefix, const struct interface *ifp)
+{
+	char **ep;
+	ssize_t n;
+	struct ipv6_addr *ia;
+
+	ep = env;
+	n = 0;
+	ia = ipv6_iffindaddr(UNCONST(ifp), &ifp->options->req_addr6, IN6_IFF_NOTUSEABLE);
+	if (ia) {
+		if (env)
+			addvar(ifp->ctx, &ep, prefix, "ip6_address", ia->saddr);
+		n++;
+	}
+
+	return n;
+}
+
+int
+ipv6_staticdadcompleted(const struct interface *ifp)
+{
+	const struct ipv6_state *state;
+	const struct ipv6_addr *ia;
+	int n;
+
+	if ((state = IPV6_CSTATE(ifp)) == NULL)
+		return 0;
+	n = 0;
+#define COMPLETED (IPV6_AF_STATIC | IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)
+	TAILQ_FOREACH(ia, &state->addrs, next) {
+		if ((ia->flags & COMPLETED) == COMPLETED &&
+		    !(ia->addr_flags & IN6_IFF_NOTUSEABLE))
+			n++;
+	}
+	return n;
+}
+
+int
+ipv6_startstatic(struct interface *ifp)
+{
+	struct ipv6_addr *ia;
+	int run_script;
+
+	if (IN6_IS_ADDR_UNSPECIFIED(&ifp->options->req_addr6))
+		return 0;
+
+	ia = ipv6_iffindaddr(ifp, &ifp->options->req_addr6, 0);
+	if (ia != NULL &&
+	    (ia->prefix_len != ifp->options->req_prefix_len ||
+	    ia->addr_flags & IN6_IFF_NOTUSEABLE))
+	{
+		ipv6_deleteaddr(ia);
+		ia = NULL;
+	}
+	if (ia == NULL) {
+		struct ipv6_state *state;
+
+		ia = ipv6_newaddr(ifp, &ifp->options->req_addr6,
+		    ifp->options->req_prefix_len);
+		if (ia == NULL)
+	    		return -1;
+		state = IPV6_STATE(ifp);
+		TAILQ_INSERT_TAIL(&state->addrs, ia, next);
+		run_script = 0;
+	} else
+		run_script = 1;
+	ia->flags |= IPV6_AF_STATIC | IPV6_AF_ONLINK;
+	ia->prefix_vltime = ND6_INFINITE_LIFETIME;
+	ia->prefix_pltime = ND6_INFINITE_LIFETIME;
+	ia->dadcallback = ipv6_staticdadcallback;
+	ipv6_addaddr(ia, NULL);
+	if_initrt6(ifp);
+	ipv6_buildroutes(ifp->ctx);
+	if (run_script)
+		script_runreason(ifp, "STATIC6");
+	return 1;
+}
+
+/* Ensure the interface has a link-local address */
+int
+ipv6_start(struct interface *ifp)
+{
+
+	if (ipv6_tryaddlinklocal(ifp) == -1)
+		return -1;
+
+	if (IPV6_CSTATE(ifp)) {
 		/* Regenerate new ids */
 		if (ifp->options->options & DHCPCD_IPV6RA_OWN &&
 		    ip6_use_tempaddr(ifp->name))
 			ipv6_regentempifid(ifp);
-	} else
-		ap = NULL;
-
-	if (ap == NULL &&
-	    CAN_ADD_LLADDR(ifp) &&
-	    ipv6_addlinklocal(ifp) == -1)
-		return -1;
+	}
 
 	/* Load existing routes */
 	if_initrt6(ifp);
+	if (!IN6_IS_ADDR_UNSPECIFIED(&ifp->options->req_addr6))
+		ipv6_buildroutes(ifp->ctx);
 	return 0;
 }
 
@@ -1326,10 +1474,14 @@ ipv6_freedrop(struct interface *ifp, int
 		return;
 
 	ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, NULL);
-
-	/* Because we need to cache the addresses we don't control,
-	 * we only free the state on when NOT dropping addresses. */
-	if (drop == 0) {
+	if (drop) {
+		if (ifp->ctx->ipv6 != NULL) {
+			if_initrt6(ifp);
+			ipv6_buildroutes(ifp->ctx);
+		}
+	} else {
+		/* Because we need to cache the addresses we don't control,
+		 * we only free the state on when NOT dropping addresses. */
 		while ((cb = TAILQ_FIRST(&state->ll_callbacks))) {
 			TAILQ_REMOVE(&state->ll_callbacks, cb, next);
 			free(cb);
@@ -1848,7 +2000,7 @@ ipv6_freerts(struct rt6_head *routes)
 /* If something other than dhcpcd removes a route,
  * we need to remove it from our internal table. */
 int
-ipv6_handlert(struct dhcpcd_ctx *ctx, int cmd, struct rt6 *rt)
+ipv6_handlert(struct dhcpcd_ctx *ctx, int cmd, const struct rt6 *rt)
 {
 	struct rt6 *f;
 
@@ -2046,6 +2198,29 @@ make_router(const struct ra *rap)
 	    IN6_ARE_ADDR_EQUAL(&((rtp)->net), &in6addr_any))
 
 static void
+ipv6_build_static_routes(struct dhcpcd_ctx *ctx, struct rt6_head *dnr)
+{
+	const struct interface *ifp;
+	const struct ipv6_state *state;
+	const struct ipv6_addr *ia;
+	struct rt6 *rt;
+
+	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+		if ((state = IPV6_CSTATE(ifp)) == NULL)
+			continue;
+		TAILQ_FOREACH(ia, &state->addrs, next) {
+			if ((ia->flags & (IPV6_AF_ADDED | IPV6_AF_STATIC)) ==
+			    (IPV6_AF_ADDED | IPV6_AF_STATIC))
+			{
+				rt = make_prefix(ifp, NULL, ia);
+				if (rt)
+					TAILQ_INSERT_TAIL(dnr, rt, next);
+			}
+		}
+	}
+}
+
+static void
 ipv6_build_ra_routes(struct ipv6_ctx *ctx, struct rt6_head *dnr, int expired)
 {
 	struct rt6 *rt;
@@ -2063,8 +2238,7 @@ ipv6_build_ra_routes(struct ipv6_ctx *ct
 			}
 		}
 		if (rap->lifetime && rap->iface->options->options &
-		    (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT) &&
-		    !rap->no_public_warned)
+		    (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT))
 		{
 			rt = make_router(rap);
 			if (rt)
@@ -2108,6 +2282,9 @@ ipv6_buildroutes(struct dhcpcd_ctx *ctx)
 
 	TAILQ_INIT(&dnr);
 
+	/* Should static take priority? */
+	ipv6_build_static_routes(ctx, &dnr);
+
 	/* First add reachable routers and their prefixes */
 	ipv6_build_ra_routes(ctx->ipv6, &dnr, 0);
 #ifdef HAVE_ROUTE_METRIC
Index: src/external/bsd/dhcpcd/dist/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.16 src/external/bsd/dhcpcd/dist/ipv6.h:1.17
--- src/external/bsd/dhcpcd/dist/ipv6.h:1.16	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/ipv6.h	Sun Apr 10 21:00:53 2016
@@ -1,8 +1,8 @@
-/* $NetBSD: ipv6.h,v 1.16 2016/01/07 20:09:43 roy Exp $ */
+/* $NetBSD: ipv6.h,v 1.17 2016/04/10 21:00:53 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
@@ -47,9 +47,6 @@
 
 #define ALLROUTERS "ff02::2"
 
-#define ROUNDUP8(a)  (1 + (((a) - 1) |  7))
-#define ROUNDUP16(a) (1 + (((a) - 1) | 16))
-
 #define EUI64_GBIT		0x01
 #define EUI64_UBIT		0x02
 #define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
@@ -72,6 +69,14 @@
 #define IDGEN_RETRIES	3
 #define IDGEN_DELAY	1 /* second */
 
+#ifndef IN6_ARE_MASKED_ADDR_EQUAL
+#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)	(	\
+	(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
+	(((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
+	(((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
+	(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
+#endif
+
 /*
  * BSD kernels don't inform userland of DAD results.
  * See the discussion here:
@@ -116,6 +121,25 @@
 #define IPV6_MANAGETEMPADDR
 #endif
 
+#ifdef __linux__
+   /* Match Linux defines to BSD */
+#  define IN6_IFF_TEMPORARY IFA_F_TEMPORARY
+#  ifdef IFA_F_OPTIMISTIC
+#    define IN6_IFF_TENTATIVE	(IFA_F_TENTATIVE | IFA_F_OPTIMISTIC)
+#  else
+#    define IN6_IFF_TENTATIVE   (IFA_F_TENTATIVE | 0x04)
+#  endif
+#  ifdef IF_F_DADFAILED
+#    define IN6_IFF_DUPLICATED	IFA_F_DADFAILED
+#  else
+#    define IN6_IFF_DUPLICATED	0x08
+#  endif
+#  define IN6_IFF_DETACHED	0
+#endif
+
+#define IN6_IFF_NOTUSEABLE \
+	(IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED)
+
 struct ipv6_addr {
 	TAILQ_ENTRY(ipv6_addr) next;
 	struct interface *iface;
@@ -154,8 +178,9 @@ TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
 #define IPV6_AF_DELEGATEDPFX	0x0100
 #define IPV6_AF_DELEGATEDZERO	0x0200
 #define IPV6_AF_REQUEST		0x0400
+#define IPV6_AF_STATIC		0x0800
 #ifdef IPV6_MANAGETEMPADDR
-#define IPV6_AF_TEMPORARY	0X0800
+#define IPV6_AF_TEMPORARY	0X1000
 #endif
 
 struct rt6 {
@@ -195,9 +220,11 @@ struct ipv6_state {
 	((struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])
 #define IPV6_CSTATE(ifp)						       \
 	((const struct ipv6_state *)(ifp)->if_data[IF_DATA_IPV6])
+#define IPV6_STATE_RUNNING(ifp) ipv6_staticdadcompleted((ifp))
 
 /* dhcpcd requires CMSG_SPACE to evaluate to a compile time constant. */
-#ifdef __QNX__
+#if defined(__QNX) || \
+	(defined(__NetBSD_Version__) && __NetBSD_Version__ < 600000000)
 #undef CMSG_SPACE
 #endif
 
@@ -238,11 +265,10 @@ struct ipv6_ctx {
 };
 
 struct ipv6_ctx *ipv6_init(struct dhcpcd_ctx *);
-ssize_t ipv6_printaddr(char *, size_t, const uint8_t *, const char *);
 int ipv6_makestableprivate(struct in6_addr *addr,
     const struct in6_addr *prefix, int prefix_len,
     const struct interface *ifp, int *dad_counter);
-int ipv6_makeaddr(struct in6_addr *, const struct interface *,
+int ipv6_makeaddr(struct in6_addr *, struct interface *,
     const struct in6_addr *, int);
 int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int);
 int ipv6_mask(struct in6_addr *, int);
@@ -258,15 +284,16 @@ void ipv6_handleifa(struct dhcpcd_ctx *c
     const char *, const struct in6_addr *, uint8_t, int);
 int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
     const struct in6_addr *, int);
-int ipv6_publicaddr(const struct ipv6_addr *);
-const struct ipv6_addr *ipv6_iffindaddr(const struct interface *,
-    const struct in6_addr *);
+struct ipv6_addr *ipv6_iffindaddr(struct interface *,
+    const struct in6_addr *, int);
 int ipv6_hasaddr(const struct interface *);
 int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *,
     short);
 struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,
     const struct in6_addr *, short);
-#define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL)
+struct ipv6_addr *ipv6_findmaskaddr(struct dhcpcd_ctx *,
+    const struct in6_addr *);
+#define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL, IN6_IFF_NOTUSEABLE)
 int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
 void ipv6_freeaddr(struct ipv6_addr *);
 void ipv6_freedrop(struct interface *, int);
@@ -286,14 +313,19 @@ void ipv6_addtempaddrs(struct interface 
 #endif
 
 int ipv6_start(struct interface *);
+int ipv6_staticdadcompleted(const struct interface *);
+int ipv6_startstatic(struct interface *);
+ssize_t ipv6_env(char **, const char *, const struct interface *);
 void ipv6_ctxfree(struct dhcpcd_ctx *);
-int ipv6_handlert(struct dhcpcd_ctx *, int cmd, struct rt6 *);
+int ipv6_handlert(struct dhcpcd_ctx *, int cmd, const struct rt6 *);
 void ipv6_freerts(struct rt6_head *);
 void ipv6_buildroutes(struct dhcpcd_ctx *);
 
 #else
 #define ipv6_init(a) (NULL)
 #define ipv6_start(a) (-1)
+#define ipv6_startstatic(a)
+#define ipv6_staticdadcompleted(a) (0)
 #define ipv6_hasaddr(a) (0)
 #define ipv6_free_ll_callbacks(a) {}
 #define ipv6_free(a) {}

Index: src/external/bsd/dhcpcd/dist/common.c
diff -u src/external/bsd/dhcpcd/dist/common.c:1.18 src/external/bsd/dhcpcd/dist/common.c:1.19
--- src/external/bsd/dhcpcd/dist/common.c:1.18	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/common.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: common.c,v 1.18 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: common.c,v 1.19 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -72,7 +72,7 @@ logger_open(struct dhcpcd_ctx *ctx)
 			warn("open: %s", ctx->logfile);
 #ifndef O_CLOEXEC
 		else {
-			if (fcntl(ctx->log_fd, F_GETFD, &f) == -1 ||
+			if ((f = fcntl(ctx->log_fd, F_GETFD)) == -1 ||
 			    fcntl(ctx->log_fd, F_SETFD, f | FD_CLOEXEC) == -1)
 				warn("fcntl: %s", ctx->logfile);
 		}
Index: src/external/bsd/dhcpcd/dist/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.18 src/external/bsd/dhcpcd/dist/dhcp6.c:1.19
--- src/external/bsd/dhcpcd/dist/dhcp6.c:1.18	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/dhcp6.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp6.c,v 1.18 2016/01/20 19:42:33 roy Exp $");
+ __RCSID("$NetBSD: dhcp6.c,v 1.19 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -57,6 +57,12 @@
 #include "ipv6nd.h"
 #include "script.h"
 
+#ifdef HAVE_SYS_BITOPS_H
+#include <sys/bitops.h>
+#else
+#include "compat/bitops.h"
+#endif
+
 #ifndef __UNCONST
 #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
 #endif
@@ -87,7 +93,7 @@ static const struct dhcp6_op dhcp6_ops[]
 	{ DHCP6_CONFIRM, "CONFIRM6" },
 	{ DHCP6_INFORMATION_REQ, "INFORM6" },
 	{ DHCP6_RELEASE, "RELEASE6" },
-	{ DHCP6_RECONFIGURE, "RECONFIURE6" },
+	{ DHCP6_RECONFIGURE, "RECONFIGURE6" },
 	{ 0, NULL }
 };
 
@@ -377,40 +383,6 @@ dhcp6_findselfsla(struct interface *ifp,
 	return NULL;
 }
 
-
-#ifndef ffs32
-static int
-ffs32(uint32_t n)
-{
-	int v;
-
-	if (!n)
-		return 0;
-
-	v = 1;
-	if ((n & 0x0000FFFFU) == 0) {
-		n >>= 16;
-		v += 16;
-	}
-	if ((n & 0x000000FFU) == 0) {
-		n >>= 8;
-		v += 8;
-	}
-	if ((n & 0x0000000FU) == 0) {
-		n >>= 4;
-		v += 4;
-	}
-	if ((n & 0x00000003U) == 0) {
-		n >>= 2;
-		v += 2;
-	}
-	if ((n & 0x00000001U) == 0)
-		v += 1;
-
-	return v;
-}
-#endif
-
 static int
 dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
     const struct ipv6_addr *prefix, const struct if_sla *sla, struct if_ia *ia)
@@ -455,13 +427,13 @@ dhcp6_delegateaddr(struct in6_addr *addr
 
 			sla_max = 0;
 			TAILQ_FOREACH(ifi, ifp->ctx->ifaces, next) {
-				if (ifi != ifp && ifi->index > sla_max)
+				if (ifi->index > sla_max)
 					sla_max = ifi->index;
 			}
 		} else
 			sla_max = ia->sla_max;
 
-		bits = ffs32(sla_max);
+		bits = fls32(sla_max);
 
 		if (prefix->prefix_len + bits > UINT8_MAX)
 			asla.prefix_len = UINT8_MAX;
@@ -469,15 +441,16 @@ dhcp6_delegateaddr(struct in6_addr *addr
 			asla.prefix_len = (uint8_t)(prefix->prefix_len + bits);
 
 			/* Make a 64 prefix by default, as this maks SLAAC
-			 * possible. Otherwise round up to the nearest octet. */
+			 * possible.
+			 * Otherwise round up to the nearest 4 bits. */
 			if (asla.prefix_len <= 64)
 				asla.prefix_len = 64;
 			else
-				asla.prefix_len = (uint8_t)ROUNDUP8(asla.prefix_len);
-
+				asla.prefix_len =
+				    (uint8_t)ROUNDUP4(asla.prefix_len);
 		}
 
-#define BIT(n) (1l << (n))
+#define BIT(n) (1UL << (n))
 #define BIT_MASK(len) (BIT(len) - 1)
 		if (ia->sla_max == 0)
 			/* Work out the real sla_max from our bits used */
@@ -511,21 +484,6 @@ dhcp6_delegateaddr(struct in6_addr *addr
 	return sla->prefix_len;
 }
 
-int
-dhcp6_has_public_addr(const struct interface *ifp)
-{
-	const struct dhcp6_state *state = D6_CSTATE(ifp);
-	const struct ipv6_addr *ia;
-
-	if (state == NULL)
-		return 0;
-	TAILQ_FOREACH(ia, &state->addrs, next) {
-		if (ipv6_publicaddr(ia))
-			return 1;
-	}
-	return 0;
-}
-
 static int
 dhcp6_makemessage(struct interface *ifp)
 {
@@ -1773,7 +1731,7 @@ dhcp6_findna(struct interface *ifp, uint
 	char iabuf[INET6_ADDRSTRLEN];
 	const char *ia;
 	int i;
-	uint32_t u32;
+	uint32_t u32, pltime, vltime;
 	size_t off;
 	const struct dhcp6_ia_addr *iap;
 
@@ -1793,6 +1751,16 @@ dhcp6_findna(struct interface *ifp, uint
 			continue;
 		}
 		iap = (const struct dhcp6_ia_addr *)D6_COPTION_DATA(o);
+		pltime = ntohl(iap->pltime);
+		vltime = ntohl(iap->vltime);
+		/* RFC 3315 22.6 */
+		if (pltime > vltime) {
+			errno = EINVAL;
+			logger(ifp->ctx, LOG_ERR,
+			    "%s: IA Address pltime %"PRIu32" > vltime %"PRIu32,
+			    ifp->name, pltime, vltime);
+			continue;
+		}
 		TAILQ_FOREACH(a, &state->addrs, next) {
 			if (ipv6_findaddrmatch(a, &iap->addr, 0))
 				break;
@@ -1832,11 +1800,10 @@ dhcp6_findna(struct interface *ifp, uint
 			a->flags &= ~IPV6_AF_STALE;
 		}
 		a->acquired = *acquired;
-		a->prefix_pltime = ntohl(iap->pltime);
-		u32 = ntohl(iap->vltime);
-		if (a->prefix_vltime != u32) {
+		a->prefix_pltime = pltime;
+		if (a->prefix_vltime != vltime) {
 			a->flags |= IPV6_AF_NEW;
-			a->prefix_vltime = u32;
+			a->prefix_vltime = vltime;
 		}
 		if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
 		    state->lowpl = a->prefix_pltime;
@@ -1862,6 +1829,7 @@ dhcp6_findpd(struct interface *ifp, cons
 	size_t off;
 	uint16_t ol;
 	const struct dhcp6_pd_addr *pdp;
+	uint32_t pltime, vltime;
 
 	i = 0;
 	state = D6_STATE(ifp);
@@ -1880,10 +1848,23 @@ dhcp6_findpd(struct interface *ifp, cons
 		}
 
 		pdp = (const struct dhcp6_pd_addr *)D6_COPTION_DATA(o);
+
+		pltime = ntohl(pdp->pltime);
+		vltime = ntohl(pdp->vltime);
+		/* RFC 3315 22.6 */
+		if (pltime > vltime) {
+			errno = EINVAL;
+			logger(ifp->ctx, LOG_ERR,
+			    "%s: IA Prefix pltime %"PRIu32" > vltime %"PRIu32,
+			    ifp->name, pltime, vltime);
+			continue;
+		}
+
 		TAILQ_FOREACH(a, &state->addrs, next) {
 			if (IN6_ARE_ADDR_EQUAL(&a->prefix, &pdp->prefix))
 				break;
 		}
+
 		if (a == NULL) {
 			a = calloc(1, sizeof(*a));
 			if (a == NULL) {
@@ -1912,8 +1893,8 @@ dhcp6_findpd(struct interface *ifp, cons
 		}
 
 		a->acquired = *acquired;
-		a->prefix_pltime = ntohl(pdp->pltime);
-		a->prefix_vltime = ntohl(pdp->vltime);
+		a->prefix_pltime = pltime;
+		a->prefix_vltime = vltime;
 
 		if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
 			state->lowpl = a->prefix_pltime;
@@ -2067,6 +2048,16 @@ dhcp6_findia(struct interface *ifp, cons
 			rebind = ntohl(u32);
 			p += sizeof(u32);
 			ol = (uint16_t)(ol - sizeof(u32));
+
+			/* RFC 3315 22.4 */
+			if (rebind > 0 && renew > rebind) {
+				logger(ifp->ctx, LOG_WARNING,
+				    "%s: IAID %s T1 (%d) > T2 (%d) from %s",
+				    ifp->name,
+				    hwaddr_ntoa(iaid, sizeof(iaid), buf, sizeof(buf)),
+				    renew, rebind, sfrom);
+				continue;
+			}
 		} else
 			renew = rebind = 0; /* appease gcc */
 		if (dhcp6_checkstatusok(ifp, NULL, p, ol) == -1) {
@@ -2090,14 +2081,6 @@ dhcp6_findia(struct interface *ifp, cons
 			}
 		}
 		if (code != D6_OPTION_IA_TA) {
-			if (renew > rebind && rebind > 0) {
-				if (sfrom)
-				    logger(ifp->ctx, LOG_WARNING,
-					"%s: T1 (%d) > T2 (%d) from %s",
-					ifp->name, renew, rebind, sfrom);
-				renew = 0;
-				rebind = 0;
-			}
 			if (renew != 0 &&
 			    (renew < state->renew || state->renew == 0))
 				state->renew = renew;
@@ -2367,6 +2350,7 @@ dhcp6_ifdelegateaddr(struct interface *i
 	char sabuf[INET6_ADDRSTRLEN];
 	const char *sa;
 	int pfxlen;
+	uint64_t vl;
 
 	/* RFC6603 Section 4.2 */
 	if (strcmp(ifp->name, ifs->name) == 0) {
@@ -2385,6 +2369,12 @@ dhcp6_ifdelegateaddr(struct interface *i
 	    sla, ia)) == -1)
 		return NULL;
 
+	if (fls64(sla->suffix) > 128 - pfxlen) {
+		logger(ifp->ctx, LOG_ERR,
+		    "%s: suffix %" PRIu64 " + prefix_len %d > 128",
+		    ifp->name, sla->suffix, pfxlen);
+		return NULL;
+	}
 
 	a = calloc(1, sizeof(*a));
 	if (a == NULL) {
@@ -2402,11 +2392,23 @@ dhcp6_ifdelegateaddr(struct interface *i
 	a->prefix = addr;
 	a->prefix_len = (uint8_t)pfxlen;
 
-	/* Wang a 1 at the end as the prefix could be >64
-	 * making SLAAC impossible. */
-	a->addr = a->prefix;
-	a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] =
-	    (uint8_t)(a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] + 1);
+	/* Add our suffix */
+	if (sla->suffix) {
+		a->addr = addr;
+		vl = be64dec(addr.s6_addr + 8);
+		vl |= sla->suffix;
+		be64enc(a->addr.s6_addr + 8, vl);
+	} else {
+		a->dadcounter = ipv6_makeaddr(&a->addr, ifp,
+		    &a->prefix, a->prefix_len);
+		if (a->dadcounter == -1) {
+			logger(ifp->ctx, LOG_ERR,
+			    "%s: error adding slaac to prefix_len %d",
+			    ifp->name, a->prefix_len);
+			free(a);
+			return NULL;
+		}
+	}
 
 	state = D6_STATE(ifp);
 	/* Remove any exiting address */
@@ -2442,7 +2444,7 @@ dhcp6_script_try_run(struct interface *i
 			continue;
 		if (ap->flags & IPV6_AF_ONLINK) {
 			if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
-			    ipv6_iffindaddr(ap->iface, &ap->addr))
+			    ipv6_iffindaddr(ap->iface, &ap->addr, IN6_IFF_TENTATIVE))
 				ap->flags |= IPV6_AF_DADCOMPLETED;
 			if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0 &&
 			    ((delegated && ap->delegating_iface) ||
@@ -2477,31 +2479,6 @@ dhcp6_delegate_prefix(struct interface *
 	ifo = ifp->options;
 	state = D6_STATE(ifp);
 
-	/* Ensure we have all interfaces */
-	for (i = 0; i < ifo->ia_len; i++) {
-		ia = &ifo->ia[i];
-		for (j = 0; j < ia->sla_len; j++) {
-			sla = &ia->sla[j];
-			for (k = 0; k < i; j++)
-				if (strcmp(sla->ifname, ia->sla[j].ifname) == 0)
-					break;
-			if (j >= i) {
-				ifd = if_find(ifp->ctx->ifaces, sla->ifname);
-				if (ifd == NULL)
-					logger(ifp->ctx, LOG_ERR,
-					    "%s: interface does not exist"
-					    " for delegation",
-					    sla->ifname);
-				else if (!ifd->active) {
-					logger(ifp->ctx, LOG_INFO,
-					    "%s: activating for delegation",
-					    sla->ifname);
-					dhcpcd_activateinterface(ifd);
-				}
-			}
-		}
-	}
-
 	TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
 		if (!ifd->active)
 			continue;
@@ -2856,6 +2833,7 @@ dhcp6_handledata(void *arg)
 				state->state = DH6S_REQUEST;
 			else
 				op = NULL;
+			/* FALLTHROUGH */
 		case DH6S_REQUEST: /* FALLTHROUGH */
 		case DH6S_RENEW: /* FALLTHROUGH */
 		case DH6S_REBIND:
@@ -3034,6 +3012,39 @@ recv:
 	case DH6S_CONFIRM:
 		if (state->reason == NULL)
 			state->reason = "REBOOT6";
+		if (state->renew != 0) {
+			int all_expired = 1;
+
+			TAILQ_FOREACH(ap, &state->addrs, next) { 
+				if (ap->flags & IPV6_AF_STALE)
+					continue;
+				if (ap->prefix_vltime <= state->renew)
+					logger(ifp->ctx, LOG_WARNING,
+					    "%s: %s will expire before renewal",
+					    ifp->name, ap->saddr);
+				else
+					all_expired = 0;
+			}
+			if (all_expired) {
+				/* All address's vltime happens at or before
+				 * the configured T1 in the IA.
+				 * This is a badly configured server and we
+				 * have to use our own notion of what
+				 * T1 and T2 should be as a result.
+				 *
+				 * Doing this violates RFC 3315 22.4:
+				 * In a message sent by a server to a client,
+				 * the client MUST use the values in the T1
+				 * and T2 fields for the T1 and T2 parameters,
+				 * unless those values in those fields are 0.
+				 */
+				logger(ifp->ctx, LOG_WARNING,
+				    "%s: ignoring T1 %"PRIu32
+				    " to due address expiry",
+				    ifp->name, state->renew);
+				state->renew = state->rebind = 0;
+			}
+		}
 		if (state->renew == 0) {
 			if (state->expire == ND6_INFINITE_LIFETIME)
 				state->renew = ND6_INFINITE_LIFETIME;
@@ -3081,9 +3092,7 @@ recv:
 			eloop_timeout_add_sec(ifp->ctx->eloop,
 			    (time_t)state->expire, dhcp6_startexpire, ifp);
 
-		ipv6nd_runignoredra(ifp);
 		ipv6_addaddrs(&state->addrs);
-		dhcp6_delegate_prefix(ifp);
 
 		if (state->state == DH6S_INFORMED)
 			logger(ifp->ctx, has_new ? LOG_INFO : LOG_DEBUG,
@@ -3091,15 +3100,18 @@ recv:
 			    ifp->name, state->renew);
 		else if (state->renew || state->rebind)
 			logger(ifp->ctx, has_new ? LOG_INFO : LOG_DEBUG,
-			    "%s: renew in %"PRIu32" seconds,"
-			    " rebind in %"PRIu32" seconds",
-			    ifp->name, state->renew, state->rebind);
+			    "%s: renew in %"PRIu32", "
+			    "rebind in %"PRIu32", "
+			    "expire in %"PRIu32" seconds",
+			    ifp->name,
+			    state->renew, state->rebind, state->expire);
 		else if (state->expire == 0)
 			logger(ifp->ctx, has_new ? LOG_INFO : LOG_DEBUG,
 			    "%s: will expire", ifp->name);
 		if_initrt6(ifp);
 		ipv6_buildroutes(ifp->ctx);
 		dhcp6_writelease(ifp);
+		dhcp6_delegate_prefix(ifp);
 		dhcp6_script_try_run(ifp, 0);
 	}
 
@@ -3126,8 +3138,9 @@ dhcp6_open(struct dhcpcd_ctx *dctx)
 #endif
 
 	ctx = dctx->ipv6;
-	ctx->dhcp_fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP,
-	    O_NONBLOCK|O_CLOEXEC);
+#define SOCK_FLAGS	SOCK_CLOEXEC | SOCK_NONBLOCK
+	ctx->dhcp_fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, SOCK_FLAGS);
+#undef SOCK_FLAGS
 	if (ctx->dhcp_fd == -1)
 		return -1;
 
@@ -3156,8 +3169,7 @@ dhcp6_open(struct dhcpcd_ctx *dctx)
 	    &n, sizeof(n)) == -1)
 		goto errexit;
 
-	eloop_event_add(dctx->eloop, ctx->dhcp_fd,
-	    dhcp6_handledata, dctx, NULL, NULL);
+	eloop_event_add(dctx->eloop, ctx->dhcp_fd, dhcp6_handledata, dctx);
 	return 0;
 
 errexit:
@@ -3167,6 +3179,36 @@ errexit:
 }
 
 static void
+dhcp6_activateinterfaces(struct interface *ifp)
+{
+	struct interface *ifd;
+	size_t i, j;
+	struct if_ia *ia;
+	struct if_sla *sla;
+
+	for (i = 0; i < ifp->options->ia_len; i++) {
+		ia = &ifp->options->ia[i];
+		for (j = 0; j < ia->sla_len; j++) {
+			sla = &ia->sla[j];
+			ifd = if_find(ifp->ctx->ifaces, sla->ifname);
+			if (ifd == NULL) {
+				logger(ifp->ctx, LOG_WARNING,
+				    "%s: cannot delegate to %s: %m",
+				    ifp->name, sla->ifname);
+				continue;
+			}
+			if (!ifd->active) {
+				logger(ifp->ctx, LOG_INFO,
+				    "%s: activating for delegation",
+				    sla->ifname);
+				dhcpcd_activateinterface(ifd,
+				    DHCPCD_IPV6 | DHCPCD_DHCP6);
+			}
+		}
+	}
+}
+
+static void
 dhcp6_start1(void *arg)
 {
 	struct interface *ifp = arg;
@@ -3204,6 +3246,8 @@ dhcp6_start1(void *arg)
 		del_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
 		dhcp6_startinit(ifp);
 	}
+
+	dhcp6_activateinterfaces(ifp);
 }
 
 int
@@ -3230,6 +3274,7 @@ dhcp6_start(struct interface *ifp, enum 
 		}
 		/* We're already running DHCP6 */
 		/* XXX: What if the managed flag vanishes from all RA? */
+		dhcp6_activateinterfaces(ifp);
 		return 0;
 	}
 
Index: src/external/bsd/dhcpcd/dist/if.c
diff -u src/external/bsd/dhcpcd/dist/if.c:1.18 src/external/bsd/dhcpcd/dist/if.c:1.19
--- src/external/bsd/dhcpcd/dist/if.c:1.18	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/if.c	Sun Apr 10 21:00:53 2016
@@ -1,9 +1,9 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if.c,v 1.18 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: if.c,v 1.19 2016/04/10 21:00:53 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
@@ -92,23 +92,16 @@ int
 if_opensockets(struct dhcpcd_ctx *ctx)
 {
 
-	if ((ctx->link_fd = if_openlinksocket()) == -1)
+	if (if_opensockets_os(ctx) == -1)
 		return -1;
 
 	/* We use this socket for some operations without INET. */
-	ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC);
+	ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM, 0, SOCK_CLOEXEC);
 	if (ctx->pf_inet_fd == -1)
 		return -1;
 
-#if defined(INET6) && defined(BSD)
-	ctx->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
-	/* Don't return an error so we at least work on kernels witout INET6
-	 * even though we expect INET6 support.
-	 * We will fail noisily elsewhere anyway. */
-#endif
-
 #ifdef IFLR_ACTIVE
-	ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0, O_CLOEXEC);
+	ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0, SOCK_CLOEXEC);
 	if (ctx->pf_link_fd == -1)
 		return -1;
 #endif
@@ -116,6 +109,23 @@ if_opensockets(struct dhcpcd_ctx *ctx)
 	return 0;
 }
 
+void
+if_closesockets(struct dhcpcd_ctx *ctx)
+{
+
+	if (ctx->pf_inet_fd != -1)
+		close(ctx->pf_inet_fd);
+#ifdef IFLR_ACTIVE
+	if (ctx->pf_link_fd != -1)
+		close(ctx->pf_link_fd);
+#endif
+
+	if (ctx->priv) {
+		if_closesockets_os(ctx);
+		free(ctx->priv);
+	}
+}
+
 int
 if_carrier(struct interface *ifp)
 {
@@ -179,7 +189,7 @@ if_hasconf(struct dhcpcd_ctx *ctx, const
 	return 0;
 }
 
-static void if_learnaddrs1(struct dhcpcd_ctx *ctx, struct if_head *ifs,
+static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs,
     struct ifaddrs *ifaddrs)
 {
 	struct ifaddrs *ifa;
@@ -201,10 +211,8 @@ static void if_learnaddrs1(struct dhcpcd
 		switch(ifa->ifa_addr->sa_family) {
 #ifdef INET
 		case AF_INET:
-			addr = (const struct sockaddr_in *)
-			    (void *)ifa->ifa_addr;
-			net = (const struct sockaddr_in *)
-			    (void *)ifa->ifa_netmask;
+			addr = (void *)ifa->ifa_addr;
+			net = (void *)ifa->ifa_netmask;
 			if (ifa->ifa_flags & IFF_POINTOPOINT)
 				dst = (const struct sockaddr_in *)
 				    (void *)ifa->ifa_dstaddr;
@@ -219,8 +227,8 @@ static void if_learnaddrs1(struct dhcpcd
 #endif
 #ifdef INET6
 		case AF_INET6:
-			sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
-			net6 = (struct sockaddr_in6 *)(void *)ifa->ifa_netmask;
+			sin6 = (void *)ifa->ifa_addr;
+			net6 = (void *)ifa->ifa_netmask;
 #ifdef __KAME__
 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 				/* Remove the scope from the address */
@@ -294,7 +302,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		if (ifp)
 			continue;
 
-		active = 1;
+		active = IF_ACTIVE_USER;
 		if (argc > 0) {
 			for (i = 0; i < argc; i++) {
 #ifdef __linux__
@@ -311,7 +319,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 #endif
 			}
 			if (i == argc) {
-				active = 0;
+				active = IF_INACTIVE;
 				p =  ifa->ifa_name;
 #ifdef __linux__
 				strlcpy(ifn, ifa->ifa_name, sizeof(ifn));
@@ -334,12 +342,12 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 			if (!fnmatch(ctx->ifdv[i], p, 0))
 				break;
 		if (i < ctx->ifdc)
-			active = 0;
+			active = IF_INACTIVE;
 		for (i = 0; i < ctx->ifac; i++)
 			if (!fnmatch(ctx->ifav[i], p, 0))
 				break;
 		if (ctx->ifac && i == ctx->ifac)
-			active = 0;
+			active = IF_INACTIVE;
 
 #ifdef PLUGIN_DEV
 		/* Ensure that the interface name has settled */
@@ -351,7 +359,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		if (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
 			if ((argc == 0 || argc == -1) &&
 			    ctx->ifac == 0 && !if_hasconf(ctx, p))
-				active = 0;
+				active = IF_INACTIVE;
 		}
 
 		if (if_vimaster(ctx, p) == 1) {
@@ -377,7 +385,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 
 		if (ifa->ifa_addr != NULL) {
 #ifdef AF_LINK
-			sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;
+			sdl = (const void *)ifa->ifa_addr;
 
 #ifdef IFLR_ACTIVE
 			/* We need to check for active address */
@@ -417,7 +425,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 					    " interface type and"
 					    " no config",
 					    ifp->name);
-					active = 0;
+					active = IF_INACTIVE;
 				}
 				/* FALLTHROUGH */
 #endif
@@ -445,7 +453,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 				if ((argc == 0 || argc == -1) &&
 				    ctx->ifac == 0 &&
 				    !if_hasconf(ctx, ifp->name))
-					active = 0;
+					active = IF_INACTIVE;
 				if (active)
 					logger(ifp->ctx, LOG_WARNING,
 					    "%s: unsupported"
@@ -461,7 +469,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 #endif
 			memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
 #elif AF_PACKET
-			sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr;
+			sll = (const void *)ifa->ifa_addr;
 			ifp->index = (unsigned int)sll->sll_ifindex;
 			ifp->family = sll->sll_hatype;
 			ifp->hwlen = sll->sll_halen;
@@ -479,7 +487,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		if (ifp->family != ARPHRD_ETHER) {
 			if ((argc == 0 || argc == -1) &&
 			    ctx->ifac == 0 && !if_hasconf(ctx, ifp->name))
-				active = 0;
+				active = IF_INACTIVE;
 			switch (ifp->family) {
 			case ARPHRD_IEEE1394:
 			case ARPHRD_INFINIBAND:
@@ -530,6 +538,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
 		if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0)
 			ifp->metric = (unsigned int)ifr.ifr_metric;
+		if_getssid(ifp);
 #else
 		/* We reserve the 100 range for virtual interfaces, if and when
 		 * we can work them out. */
@@ -544,7 +553,7 @@ if_discover(struct dhcpcd_ctx *ctx, int 
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
-	if_learnaddrs1(ctx, ifs, ifaddrs);
+	if_learnaddrs(ctx, ifs, ifaddrs);
 	freeifaddrs(ifaddrs);
 
 	return ifs;
@@ -567,7 +576,7 @@ if_findindexname(struct if_head *ifaces,
 		}
 	}
 
-	errno = ESRCH;
+	errno = ENXIO;
 	return NULL;
 }
 
@@ -609,9 +618,9 @@ if_cmp(const struct interface *si, const
 #endif
 
 	/* Check active first */
-	if (si->active && !ti->active)
+	if (si->active > ti->active)
 		return -1;
-	if (!si->active && ti->active)
+	if (si->active < ti->active)
 		return 1;
 
 	/* Check carrier status next */
@@ -679,25 +688,37 @@ if_sortinterfaces(struct dhcpcd_ctx *ctx
 int
 xsocket(int domain, int type, int protocol, int flags)
 {
-#ifdef SOCK_CLOEXEC
-	if (flags & O_CLOEXEC)
+	int s;
+#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
+	int xflags;
+#endif
+
+#ifdef HAVE_SOCK_CLOEXEC
+	if (flags & SOCK_CLOEXEC)
 		type |= SOCK_CLOEXEC;
-	if (flags & O_NONBLOCK)
+#endif
+#ifdef HAVE_SOCK_NONBLOCK
+	if (flags & SOCK_NONBLOCK)
 		type |= SOCK_NONBLOCK;
-
-	return socket(domain, type, protocol);
-#else
-	int s, xflags;
+#endif
 
 	if ((s = socket(domain, type, protocol)) == -1)
 		return -1;
-	if ((flags & O_CLOEXEC) && ((xflags = fcntl(s, F_GETFD, 0)) == -1 ||
+
+#ifndef HAVE_SOCK_CLOEXEC
+	if ((flags & SOCK_CLOEXEC) && ((xflags = fcntl(s, F_GETFD)) == -1 ||
 	    fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1))
 		goto out;
-	if ((flags & O_NONBLOCK) && ((xflags = fcntl(s, F_GETFL, 0)) == -1 ||
+#endif
+#ifndef HAVE_SOCK_NONBLOCK
+	if ((flags & SOCK_NONBLOCK) && ((xflags = fcntl(s, F_GETFL)) == -1 ||
 	    fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1))
 		goto out;
+#endif
+
 	return s;
+
+#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK)
 out:
 	close(s);
 	return -1;

Index: src/external/bsd/dhcpcd/dist/common.h
diff -u src/external/bsd/dhcpcd/dist/common.h:1.12 src/external/bsd/dhcpcd/dist/common.h:1.13
--- src/external/bsd/dhcpcd/dist/common.h:1.12	Mon Nov 30 16:33:00 2015
+++ src/external/bsd/dhcpcd/dist/common.h	Sun Apr 10 21:00:53 2016
@@ -1,8 +1,8 @@
-/* $NetBSD: common.h,v 1.12 2015/11/30 16:33:00 roy Exp $ */
+/* $NetBSD: common.h,v 1.13 2016/04/10 21:00:53 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
@@ -53,6 +53,9 @@
 #define TOSTRING(a)		STRINGIFY(a)
 #define UNUSED(a)		(void)(a)
 
+#define ROUNDUP4(a)		(1 + (((a) - 1) |  3))
+#define ROUNDUP8(a)		(1 + (((a) - 1) |  7))
+
 #define USEC_PER_SEC		1000000L
 #define USEC_PER_NSEC		1000L
 #define NSEC_PER_SEC		1000000000L
Index: src/external/bsd/dhcpcd/dist/dhcp-common.c
diff -u src/external/bsd/dhcpcd/dist/dhcp-common.c:1.12 src/external/bsd/dhcpcd/dist/dhcp-common.c:1.13
--- src/external/bsd/dhcpcd/dist/dhcp-common.c:1.12	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/dhcp-common.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp-common.c,v 1.12 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: dhcp-common.c,v 1.13 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -67,10 +67,10 @@ dhcp_get_hostname(char *buf, size_t buf_
 		strlcpy(buf, ifo->hostname, buf_len);
 
 	/* Deny sending of these local hostnames */
-	if (strcmp(buf, "(none)") == 0 ||
+	if (buf[0] == '\0' || buf[0] == '.' ||
+	    strcmp(buf, "(none)") == 0 ||
 	    strcmp(buf, "localhost") == 0 ||
-	    strncmp(buf, "localhost.", strlen("localhost.")) == 0 ||
-	    buf[0] == '.')
+	    strncmp(buf, "localhost.", strlen("localhost.")) == 0)
 		return NULL;
 
 	/* Shorten the hostname if required */
@@ -621,6 +621,39 @@ dhcp_optlen(const struct dhcp_opt *opt, 
 	return (ssize_t)sz;
 }
 
+/* It's possible for DHCPv4 to contain an IPv6 address */
+static ssize_t
+ipv6_printaddr(char *s, size_t sl, const uint8_t *d, const char *ifname)
+{
+	char buf[INET6_ADDRSTRLEN];
+	const char *p;
+	size_t l;
+
+	p = inet_ntop(AF_INET6, d, buf, sizeof(buf));
+	if (p == NULL)
+		return -1;
+
+	l = strlen(p);
+	if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80)
+		l += 1 + strlen(ifname);
+
+	if (s == NULL)
+		return (ssize_t)l;
+
+	if (sl < l) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	s += strlcpy(s, p, sl);
+	if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80) {
+		*s++ = '%';
+		s += strlcpy(s, ifname, sl);
+	}
+	*s = '\0';
+	return (ssize_t)l;
+}
+
 static ssize_t
 print_option(char *s, size_t len, const struct dhcp_opt *opt,
     const uint8_t *data, size_t dl, const char *ifname)
@@ -635,10 +668,6 @@ print_option(char *s, size_t len, const 
 	size_t l;
 	char *tmp;
 
-#ifndef INET6
-	UNUSED(ifname);
-#endif
-
 	if (opt->type & RFC1035) {
 		sl = decode_rfc1035(NULL, 0, data, dl);
 		if (sl == 0 || sl == -1)
@@ -719,23 +748,20 @@ print_option(char *s, size_t len, const 
 		} else if (opt->type & ADDRIPV4) {
 			l = 16;
 			dl /= 4;
-		}
-#ifdef INET6
-		else if (opt->type & ADDRIPV6) {
+		} else if (opt->type & ADDRIPV6) {
 			e = data + dl;
 			l = 0;
 			while (data < e) {
 				if (l)
 					l++; /* space */
 				sl = ipv6_printaddr(NULL, 0, data, ifname);
-				if (sl != -1)
-					l += (size_t)sl;
+				if (sl == -1)
+					return l == 0 ? -1 : (ssize_t)l;
+				l += (size_t)sl;
 				data += 16;
 			}
 			return (ssize_t)l;
-		}
-#endif
-		else {
+		} else {
 			errno = EINVAL;
 			return -1;
 		}
@@ -777,21 +803,15 @@ print_option(char *s, size_t len, const 
 			memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
 			sl = snprintf(s, len, "%s", inet_ntoa(addr));
 			data += sizeof(addr.s_addr);
-		}
-#ifdef INET6
-		else if (opt->type & ADDRIPV6) {
-			ssize_t r;
-
-			r = ipv6_printaddr(s, len, data, ifname);
-			if (r != -1)
-				sl = r;
-			else
-				sl = 0;
+		} else if (opt->type & ADDRIPV6) {
+			sl = ipv6_printaddr(s, len, data, ifname);
 			data += 16;
+		} else {
+			errno = EINVAL;
+			return -1;
 		}
-#endif
-		else
-			sl = 0;
+		if (sl == -1)
+			return bytes == 0 ? -1 : bytes;
 		len -= (size_t)sl;
 		bytes += sl;
 		s += sl;
Index: src/external/bsd/dhcpcd/dist/dhcp6.h
diff -u src/external/bsd/dhcpcd/dist/dhcp6.h:1.12 src/external/bsd/dhcpcd/dist/dhcp6.h:1.13
--- src/external/bsd/dhcpcd/dist/dhcp6.h:1.12	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/dhcp6.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp6.h,v 1.12 2016/01/07 20:09:43 roy Exp $ */
+/* $NetBSD: dhcp6.h,v 1.13 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -201,7 +201,7 @@ struct dhcp6_state {
 	struct ipv6_addrhead addrs;
 	uint32_t lowpl;
 	/* The +3 is for the possible .pd extension for prefix delegation */
-	char leasefile[sizeof(LEASEFILE6) + IF_NAMESIZE + (IF_SSIDSIZE * 4) +3];
+	char leasefile[sizeof(LEASEFILE6) + IF_NAMESIZE + (IF_SSIDLEN * 4) +3];
 	const char *reason;
 
 	struct authstate auth;
@@ -240,7 +240,6 @@ const struct ipv6_addr *dhcp6_iffindaddr
 struct ipv6_addr *dhcp6_findaddr(struct dhcpcd_ctx *, const struct in6_addr *,
     short);
 size_t dhcp6_find_delegates(struct interface *);
-int dhcp6_has_public_addr(const struct interface *);
 int dhcp6_start(struct interface *, enum DH6S);
 void dhcp6_reboot(struct interface *);
 void dhcp6_renew(struct interface *);

Index: src/external/bsd/dhcpcd/dist/config.h
diff -u src/external/bsd/dhcpcd/dist/config.h:1.9 src/external/bsd/dhcpcd/dist/config.h:1.10
--- src/external/bsd/dhcpcd/dist/config.h:1.9	Sat May 16 23:31:32 2015
+++ src/external/bsd/dhcpcd/dist/config.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: config.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
+/* $NetBSD: config.h,v 1.10 2016/04/10 21:00:53 roy Exp $ */
 
 /* netbsd */
 #define SYSCONFDIR	"/etc"
@@ -7,9 +7,11 @@
 #define LIBEXECDIR	"/libexec"
 #define DBDIR		"/var/db"
 #define RUNDIR		"/var/run"
+#define HAVE_UTIL_H
 #define HAVE_SYS_QUEUE_H
 #define HAVE_SPAWN_H
 #define HAVE_KQUEUE
 #define HAVE_KQUEUE1
+#define HAVE_SYS_BITOPS_H
 #define HAVE_MD5_H
 #define SHA2_H		<sha2.h>
Index: src/external/bsd/dhcpcd/dist/eloop.h
diff -u src/external/bsd/dhcpcd/dist/eloop.h:1.9 src/external/bsd/dhcpcd/dist/eloop.h:1.10
--- src/external/bsd/dhcpcd/dist/eloop.h:1.9	Sat May 16 23:31:32 2015
+++ src/external/bsd/dhcpcd/dist/eloop.h	Sun Apr 10 21:00:53 2016
@@ -1,8 +1,8 @@
-/* $NetBSD: eloop.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
+/* $NetBSD: eloop.h,v 1.10 2016/04/10 21:00:53 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
@@ -32,43 +32,6 @@
 
 #include <time.h>
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#else
-/* Attempt to autodetect kqueue or epoll.
- * If we can't, the system has to support pselect, which is a POSIX call. */
-#if (defined(__unix__) || defined(unix)) && !defined(USG)
-#include <sys/param.h>
-#endif
-#if defined(BSD)
-/* Assume BSD has a working sys/queue.h and kqueue(2) interface */
-#define HAVE_SYS_QUEUE_H
-#define HAVE_KQUEUE
-#elif defined(__linux__)
-/* Assume Linux has a working epoll(3) interface */
-#define HAVE_EPOLL
-#endif
-#endif
-
-/* Our structures require TAILQ macros, which really every libc should
- * ship as they are useful beyond belief.
- * Sadly some libc's don't have sys/queue.h and some that do don't have
- * the TAILQ_FOREACH macro. For those that don't, the application using
- * this implementation will need to ship a working queue.h somewhere.
- * If we don't have sys/queue.h found in config.h, then
- * allow QUEUE_H to override loading queue.h in the current directory. */
-#ifndef TAILQ_FOREACH
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h>
-#elif defined(QUEUE_H)
-#define __QUEUE_HEADER(x) #x
-#define _QUEUE_HEADER(x) __QUEUE_HEADER(x)
-#include _QUEUE_HEADER(QUEUE_H)
-#else
-#include "queue.h"
-#endif
-#endif
-
 /* Some systems don't define timespec macros */
 #ifndef timespecclear
 #define timespecclear(tsp)      (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L)
@@ -99,61 +62,22 @@
 
 /* eloop queues are really only for deleting timeouts registered
  * for a function or object.
- * The idea being that one interface as different timeouts for
+ * The idea being that one interface has different timeouts for
  * say DHCP and DHCPv6. */
 #ifndef ELOOP_QUEUE
   #define ELOOP_QUEUE 1
 #endif
 
-struct eloop_event {
-	TAILQ_ENTRY(eloop_event) next;
-	int fd;
-	void (*read_cb)(void *);
-	void *read_cb_arg;
-	void (*write_cb)(void *);
-	void *write_cb_arg;
-#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL)
-	struct pollfd *pollfd;
-#endif
-};
-
-struct eloop_timeout {
-	TAILQ_ENTRY(eloop_timeout) next;
-	struct timespec when;
-	void (*callback)(void *);
-	void *arg;
-	int queue;
-};
-
-struct eloop {
-	size_t events_len;
-	TAILQ_HEAD (event_head, eloop_event) events;
-	struct event_head free_events;
-
-	TAILQ_HEAD (timeout_head, eloop_timeout) timeouts;
-	struct timeout_head free_timeouts;
-
-	void (*timeout0)(void *);
-	void *timeout0_arg;
-	const int *signals;
-	size_t signals_len;
-	void (*signal_cb)(int, void *);
-	void *signal_cb_ctx;
-
-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
-	int poll_fd;
-#else
-	struct pollfd *fds;
-	size_t fds_len;
-#endif
-
-	int exitnow;
-	int exitcode;
-};
+/* Forward declare eloop - the content should be invisible to the outside */
+struct eloop;
 
-int eloop_event_add(struct eloop *, int,
+int eloop_event_add_rw(struct eloop *, int,
     void (*)(void *), void *,
     void (*)(void *), void *);
+int eloop_event_add(struct eloop *, int,
+    void (*)(void *), void *);
+int eloop_event_add_w(struct eloop *, int,
+    void (*)(void *), void *);
 #define eloop_event_delete(eloop, fd) \
     eloop_event_delete_write((eloop), (fd), 0)
 #define eloop_event_remove_writecb(eloop, fd) \
@@ -181,11 +105,7 @@ int eloop_signal_set_cb(struct eloop *, 
 int eloop_signal_mask(struct eloop *, sigset_t *oldset);
 
 struct eloop * eloop_new(void);
-#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
 int eloop_requeue(struct eloop *);
-#else
-#define eloop_requeue(eloop) (0)
-#endif
 void eloop_free(struct eloop *);
 void eloop_exit(struct eloop *, int);
 int eloop_start(struct eloop *, sigset_t *);

Index: src/external/bsd/dhcpcd/dist/control.c
diff -u src/external/bsd/dhcpcd/dist/control.c:1.10 src/external/bsd/dhcpcd/dist/control.c:1.11
--- src/external/bsd/dhcpcd/dist/control.c:1.10	Fri Aug 21 10:39:00 2015
+++ src/external/bsd/dhcpcd/dist/control.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: control.c,v 1.10 2015/08/21 10:39:00 roy Exp $");
+ __RCSID("$NetBSD: control.c,v 1.11 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -184,8 +184,7 @@ control_handle1(struct dhcpcd_ctx *ctx, 
 		TAILQ_INIT(&l->queue);
 		TAILQ_INIT(&l->free_queue);
 		TAILQ_INSERT_TAIL(&ctx->control_fds, l, next);
-		eloop_event_add(ctx->eloop, l->fd,
-		    control_handle_data, l, NULL, NULL);
+		eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
 	} else
 		close(fd);
 }
@@ -211,8 +210,10 @@ make_sock(struct sockaddr_un *sa, const 
 {
 	int fd;
 
-	if ((fd = xsocket(AF_UNIX, SOCK_STREAM, 0, O_NONBLOCK|O_CLOEXEC)) == -1)
+#define SOCK_FLAGS	SOCK_CLOEXEC | SOCK_NONBLOCK
+	if ((fd = xsocket(AF_UNIX, SOCK_STREAM, 0, SOCK_FLAGS)) == -1)
 		return -1;
+#undef SOCK_FLAGS
 	memset(sa, 0, sizeof(*sa));
 	sa->sun_family = AF_UNIX;
 	if (unpriv)
@@ -248,7 +249,7 @@ control_start1(struct dhcpcd_ctx *ctx, c
 		unlink(sa.sun_path);
 		return -1;
 	}
-	
+
 	if ((fmode & S_UNPRIV) != S_UNPRIV)
 		strlcpy(ctx->control_sock, sa.sun_path,
 		    sizeof(ctx->control_sock));
@@ -264,14 +265,13 @@ control_start(struct dhcpcd_ctx *ctx, co
 		return -1;
 
 	ctx->control_fd = fd;
-	eloop_event_add(ctx->eloop, fd, control_handle, ctx, NULL, NULL);
+	eloop_event_add(ctx->eloop, fd, control_handle, ctx);
 
 	if (ifname == NULL && (fd = control_start1(ctx, NULL, S_UNPRIV)) != -1){
 		/* We must be in master mode, so create an unpriviledged socket
 		 * to allow normal users to learn the status of dhcpcd. */
 		ctx->control_unpriv_fd = fd;
-		eloop_event_add(ctx->eloop, fd, control_handle_unpriv,
-		    ctx, NULL, NULL);
+		eloop_event_add(ctx->eloop, fd, control_handle_unpriv, ctx);
 	}
 	return ctx->control_fd;
 }
@@ -411,8 +411,7 @@ control_queue(struct fd_list *fd, char *
 	d->data_len = data_len;
 	d->freeit = fit;
 	TAILQ_INSERT_TAIL(&fd->queue, d, next);
-	eloop_event_add(fd->ctx->eloop, fd->fd,
-	    NULL, NULL, control_writeone, fd);
+	eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd);
 	return 0;
 }
 
Index: src/external/bsd/dhcpcd/dist/ipv4ll.h
diff -u src/external/bsd/dhcpcd/dist/ipv4ll.h:1.10 src/external/bsd/dhcpcd/dist/ipv4ll.h:1.11
--- src/external/bsd/dhcpcd/dist/ipv4ll.h:1.10	Fri Aug 21 10:39:00 2015
+++ src/external/bsd/dhcpcd/dist/ipv4ll.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv4ll.h,v 1.10 2015/08/21 10:39:00 roy Exp $ */
+/* $NetBSD: ipv4ll.h,v 1.11 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,6 +30,7 @@
 #ifndef IPV4LL_H
 #define IPV4LL_H
 
+#ifdef INET
 #include "arp.h"
 
 extern const struct in_addr inaddr_llmask;
@@ -66,9 +67,19 @@ ssize_t ipv4ll_env(char **, const char *
 void ipv4ll_start(void *);
 void ipv4ll_claimed(void *);
 void ipv4ll_handle_failure(void *);
+#ifdef HAVE_ROUTE_METRIC
+int ipv4ll_handlert(struct dhcpcd_ctx *, int, const struct rt *);
+#else
+#define ipv4ll_handlert(a, b, c) (0)
+#endif
 
 #define ipv4ll_free(ifp) ipv4ll_freedrop((ifp), 0);
 #define ipv4ll_drop(ifp) ipv4ll_freedrop((ifp), 1);
 void ipv4ll_freedrop(struct interface *, int);
+#else
+#define IPV4LL_STATE_RUNNING(ifp) (0)
+#define ipv4ll_free(a) {}
+#define ipv4ll_drop(a) {}
+#endif
 
 #endif

Index: src/external/bsd/dhcpcd/dist/defs.h
diff -u src/external/bsd/dhcpcd/dist/defs.h:1.24 src/external/bsd/dhcpcd/dist/defs.h:1.25
--- src/external/bsd/dhcpcd/dist/defs.h:1.24	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/defs.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: defs.h,v 1.24 2016/01/20 19:42:33 roy Exp $ */
+/* $NetBSD: defs.h,v 1.25 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,7 +30,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"6.10.1"
+#define VERSION			"6.10.2"
 
 #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.24 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.25
--- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.24	Mon Nov 30 16:33:00 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
-.\"     $NetBSD: dhcpcd.conf.5.in,v 1.24 2015/11/30 16:33:00 roy Exp $
-.\" Copyright (c) 2006-2015 Roy Marples
+.\"     $NetBSD: dhcpcd.conf.5.in,v 1.25 2016/04/10 21:00:53 roy Exp $
+.\" Copyright (c) 2006-2016 Roy Marples
 .\" All rights reserved
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd October 19, 2015
+.Dd March 30, 2016
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -40,8 +40,8 @@ can be used here.
 The first word on the line is the option and the rest of the line is the value.
 Leading and trailing whitespace for the option and value are trimmed.
 You can escape characters in the value using the \\ character.
-.Pp
-Blank lines and lines starting with # are ignored.
+Comments can be prefixed with the # character.
+String values should be quoted with the " character.
 .Pp
 Here's a list of available options:
 .Bl -tag -width indent
@@ -68,8 +68,13 @@ Example:
 .D1 interface bge0
 .D1 arping 192.168.0.1
 .Pp
-.D1 profile 192.168.0.1
+.D1 # My specific 192.168.0.1 network
+.D1 profile dd:ee:aa:dd:bb:ee
 .D1 static ip_address=192.168.0.10/24
+.Pp
+.D1 # A generic 192.168.0.1 network
+.D1 profile 192.168.0.1
+.D1 static ip_address=192.168.0.98/24
 .It Ic authprotocol Ar protocol Ar algorithm Ar rdm
 Authenticate DHCP messages.
 See the Supported Authentication Protocols section.
@@ -209,6 +214,43 @@ Enable DHCPv6 on the interface, on by de
 Enable IPv4 on the interface, on by default.
 .It Ic ipv6
 Enable IPv6 on the interface, on by default.
+.It Ic request Op Ar address
+Request the
+.Ar address
+in the DHCP DISCOVER message.
+There is no guarantee this is the address the DHCP server will actually give.
+If no
+.Ar address
+is given then the first address currently assigned to the
+.Ar interface
+is used.
+.It Ic inform Op Ar address Ns Op Ar /cidr
+Behaves like
+.Ic request
+as above, but sends a DHCP INFORM instead of DISCOVER/REQUEST.
+This does not get a lease as such, just notifies the DHCP server of the
+.Ar address
+in use.
+You should also include the optional
+.Ar cidr
+network number in case the address is not already configured on the interface.
+.Nm dhcpcd
+remains running and pretends it has an infinite lease.
+.Nm dhcpcd
+will not de-configure the interface when it exits.
+If
+.Nm dhcpcd
+fails to contact a DHCP server then it returns a failure instead of falling
+back on IPv4LL.
+.It Ic inform6
+Performs a DHCPv6 Information Request.
+No address is requested or specified, but all other DHCPv6 options are allowed.
+This is normally performed automatically when the IPv6 Router Advertises
+that the client should perform this operation.
+This option is only needed when
+.Nm dhcpcd
+is not processing IPv6RA messages and the need for DHCPv6 Information Request
+exists.
 .It Ic persistent
 .Nm dhcpcd
 normally de-configures the interface and configuration when it exits.
@@ -253,7 +295,7 @@ Request a DHCPv6 Temporary Address for
 You can request more than one ia_ta by specifying a unique
 .Ar iaid
 for each one.
-.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len
+.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len Op / Ar suffix
 Request a DHCPv6 Delegated Prefix for
 .Ar iaid .
 This option must be used in an
@@ -274,7 +316,12 @@ Otherwise addresses are only assigned fo
 .Ar interface
 and
 .Ar sla_id .
-Each assigned address will have a suffix of 1.
+Each assigned address will have a
+.Ar suffix ,
+defaulting to 1.
+If the
+.Ar suffix
+is 0 then a slaac address is assigned.
 You cannot assign a prefix to the requesting interface unless the
 DHCPv6 server supports
 .Li RFC6603
@@ -369,12 +416,6 @@ Each time dhcpcd receives an IPv6 Router
 the default route only.
 This allows dhcpcd to prefer an interface for outbound traffic based on metric
 and/or user selection rather than the kernel.
-.It Ic ipv6ra_accept_nopublic
-Some IPv6 routers advertise themselves as a default router without any
-public prefixes or managed addresses.
-Generally, this is incorrect behaviour and
-.Nm dhcpcd
-will ignore the advertisement unless this option is turned on.
 .It Ic ipv6rs
 Enables IPv6 Router Advertisment solicitation.
 This is on by default, but is documented here in the case where it is disabled
@@ -554,12 +595,25 @@ then
 .Nm dhcpcd
 will not attempt to obtain a lease and just use the value for the address with
 an infinite lease time.
+If you set
+.Ic ip6_address ,
+.Nm dhcpcd
+will continue auto-configuation as normal.
 .Pp
-Here is an example which configures a static address, routes and dns.
+Here is an example which configures two static addresss, an IPv4 router, DNS
+and disables IPv6 auto-configuration.
+You could also use the
+.Ic inform6
+command here if you wished to obtain more information via DHCPv6.
+For IPv4, you should use the
+.Ic inform Ar ipaddress
+option instead of setting a static address.
 .D1 interface eth0
+.D1 noipv6rs
 .D1 static ip_address=192.168.0.10/24
+.D1 static ip6_address=fd51:42f8:caae:d92e::ff/64
 .D1 static routers=192.168.0.1
-.D1 static domain_name_servers=192.168.0.1
+.D1 static domain_name_servers=192.168.0.1 fd51:42f8:caae:d92e::1
 .Pp
 Here is an example for PPP which gives the destination a default route.
 It uses the special destination keyword to insert the destination address
Index: src/external/bsd/dhcpcd/dist/script.c
diff -u src/external/bsd/dhcpcd/dist/script.c:1.24 src/external/bsd/dhcpcd/dist/script.c:1.25
--- src/external/bsd/dhcpcd/dist/script.c:1.24	Mon Nov 30 16:33:00 2015
+++ src/external/bsd/dhcpcd/dist/script.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: script.c,v 1.24 2015/11/30 16:33:00 roy Exp $");
+ __RCSID("$NetBSD: script.c,v 1.25 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -243,7 +243,7 @@ make_env(const struct interface *ifp, co
 #endif
 #ifdef INET6
 	const struct dhcp6_state *d6_state;
-	int dhcp6, ra;
+	int static6, dhcp6, ra;
 #endif
 
 #ifdef INET
@@ -252,7 +252,7 @@ make_env(const struct interface *ifp, co
 	istate = IPV4LL_CSTATE(ifp);
 #endif
 #ifdef INET6
-	dhcp6 = ra = 0;
+	static6 = dhcp6 = ra = 0;
 	d6_state = D6_CSTATE(ifp);
 #endif
 	if (strcmp(reason, "TEST") == 0) {
@@ -271,6 +271,8 @@ make_env(const struct interface *ifp, co
 #endif
 	}
 #ifdef INET6
+	else if (strcmp(reason, "STATIC6") == 0)
+		static6 = 1;
 	else if (reason[strlen(reason) - 1] == '6')
 		dhcp6 = 1;
 	else if (strcmp(reason, "ROUTERADVERT") == 0)
@@ -363,6 +365,7 @@ make_env(const struct interface *ifp, co
 	    || (ipv4ll && IPV4LL_STATE_RUNNING(ifp))
 #endif
 #ifdef INET6
+	    || (static6 && IPV6_STATE_RUNNING(ifp))
 	    || (dhcp6 && d6_state && d6_state->new)
 	    || (ra && ipv6nd_hasra(ifp))
 #endif
@@ -495,6 +498,20 @@ dumplease:
 	}
 #endif
 #ifdef INET6
+	if (static6) {
+		n = ipv6_env(NULL, NULL, ifp);
+		if (n > 0) {
+			nenv = realloc(env, sizeof(char *) *
+			    (elen + (size_t)n + 1));
+			if (nenv == NULL)
+				goto eexit;
+			env = nenv;
+			n = ipv6_env(env + elen, "new", ifp);
+			if (n == -1)
+				goto eexit;
+			elen += (size_t)n;
+		}
+	}
 	if (dhcp6 && D6_STATE_RUNNING(ifp)) {
 		n = dhcp6_env(NULL, NULL, ifp,
 		    d6_state->new, d6_state->new_len);
@@ -575,9 +592,9 @@ send_interface1(struct fd_list *fd, cons
 	elen = (size_t)arraytostr((const char *const *)env, &s);
 	if ((ssize_t)elen == -1) {
 		free(s);
-		return -1;
-	}
-	retval = control_queue(fd, s, elen, 1);
+		retval = -1;
+	} else
+		retval = control_queue(fd, s, elen, 1);
 	ep = env;
 	while (*ep)
 		free(*ep++);
@@ -623,6 +640,10 @@ send_interface(struct fd_list *fd, const
 #endif
 
 #ifdef INET6
+	if (IPV6_STATE_RUNNING(ifp)) {
+		if (send_interface1(fd, ifp, "STATIC6") == -1)
+			retval = -1;
+	}
 	if (RS_STATE_RUNNING(ifp)) {
 		if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
 			retval = -1;

Index: src/external/bsd/dhcpcd/dist/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.37 src/external/bsd/dhcpcd/dist/dhcp.c:1.38
--- src/external/bsd/dhcpcd/dist/dhcp.c:1.37	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/dhcp.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp.c,v 1.37 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: dhcp.c,v 1.38 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -99,7 +99,7 @@ static const struct dhcp_op dhcp_ops[] =
 	{ DHCP_NAK,        "NAK" },
 	{ DHCP_RELEASE,    "RELEASE" },
 	{ DHCP_INFORM,     "INFORM" },
-	{ DHCP_FORCERENEW, "DHCP_FORCERENEW"},
+	{ DHCP_FORCERENEW, "FORCERENEW"},
 	{ 0, NULL }
 };
 
@@ -1492,7 +1492,7 @@ dhcp_openudp(struct interface *ifp)
 	char *p;
 #endif
 
-	if ((s = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP, O_CLOEXEC)) == -1)
+	if ((s = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP, SOCK_CLOEXEC)) == -1)
 		return -1;
 
 	n = 1;
@@ -3092,7 +3092,7 @@ dhcp_open(struct interface *ifp)
 			return -1;
 		}
 		eloop_event_add(ifp->ctx->eloop,
-		    state->raw_fd, dhcp_handlepacket, ifp, NULL, NULL);
+		    state->raw_fd, dhcp_handlepacket, ifp);
 	}
 	return 0;
 }
@@ -3270,8 +3270,7 @@ dhcp_start1(void *arg)
 				    "%s: dhcp_openudp: %m", __func__);
 		} else
 			eloop_event_add(ifp->ctx->eloop,
-			    ifp->ctx->udp_fd, dhcp_handleudp,
-			    ifp->ctx, NULL, NULL);
+			    ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx);
 	}
 
 	if (dhcp_init(ifp) == -1) {

Index: src/external/bsd/dhcpcd/dist/dhcp.h
diff -u src/external/bsd/dhcpcd/dist/dhcp.h:1.13 src/external/bsd/dhcpcd/dist/dhcp.h:1.14
--- src/external/bsd/dhcpcd/dist/dhcp.h:1.13	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/dhcp.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp.h,v 1.13 2016/01/07 20:09:43 roy Exp $ */
+/* $NetBSD: dhcp.h,v 1.14 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -220,7 +220,7 @@ struct dhcp_state {
 	struct in_addr dst;
 	uint8_t added;
 
-	char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDSIZE * 4)];
+	char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4)];
 	struct timespec started;
 	unsigned char *clientid;
 	struct authstate auth;
Index: src/external/bsd/dhcpcd/dist/if.h
diff -u src/external/bsd/dhcpcd/dist/if.h:1.13 src/external/bsd/dhcpcd/dist/if.h:1.14
--- src/external/bsd/dhcpcd/dist/if.h:1.13	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/if.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.13 2016/01/07 20:09:43 roy Exp $ */
+/* $NetBSD: if.h,v 1.14 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -103,7 +103,9 @@ int if_init(struct interface *);
 int if_getssid(struct interface *);
 int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
 int if_opensockets(struct dhcpcd_ctx *);
-int if_openlinksocket(void);
+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 *);
 
 /* dhcpcd uses the same routing flags as BSD.
@@ -116,6 +118,19 @@ int if_managelink(struct dhcpcd_ctx *);
 #define RTM_GET		0x4	/* Report Metrics */
 #endif
 
+/* Define SOCK_CLOEXEC and SOCK_NONBLOCK for systems that lack it.
+ * xsocket() in if.c will map them to fctnl FD_CLOEXEC and O_NONBLOCK. */
+#ifdef SOCK_CLOEXEC
+# define HAVE_SOCK_CLOEXEC
+#else
+# define SOCK_CLOEXEC	0x10000000
+#endif
+#ifdef SOCK_NONBLOCK
+# define HAVE_SOCK_NONBLOCK
+#else
+# define SOCK_NONBLOCK	0x20000000
+#endif
+
 #ifdef INET
 extern const char *if_pfname;
 int if_openrawsocket(struct interface *, uint16_t);
Index: src/external/bsd/dhcpcd/dist/ipv4ll.c
diff -u src/external/bsd/dhcpcd/dist/ipv4ll.c:1.13 src/external/bsd/dhcpcd/dist/ipv4ll.c:1.14
--- src/external/bsd/dhcpcd/dist/ipv4ll.c:1.13	Mon Nov 30 16:33:00 2015
+++ src/external/bsd/dhcpcd/dist/ipv4ll.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4ll.c,v 1.13 2015/11/30 16:33:00 roy Exp $");
+ __RCSID("$NetBSD: ipv4ll.c,v 1.14 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -447,3 +447,29 @@ ipv4ll_freedrop(struct interface *ifp, i
 		}
 	}
 }
+
+/* This may cause issues in BSD systems, where running as a single dhcpcd
+ * daemon would solve this issue easily. */
+#ifdef HAVE_ROUTE_METRIC
+int
+ipv4ll_handlert(struct dhcpcd_ctx *ctx, __unused int cmd, const struct rt *rt)
+{
+	struct interface *ifp;
+
+	/* Only interested in default route changes. */
+	if (rt->dest.s_addr != INADDR_ANY)
+		return 0;
+
+	/* If any interface is running IPv4LL, rebuild our routing table. */
+	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+		if (IPV4LL_STATE_RUNNING(ifp))
+			break;
+	}
+	if (ifp != NULL) {
+		if_initrt(ifp);
+		ipv4_buildroutes(ctx);
+	}
+
+	return 0;
+}
+#endif
Index: src/external/bsd/dhcpcd/dist/ipv6nd.h
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.h:1.13 src/external/bsd/dhcpcd/dist/ipv6nd.h:1.14
--- src/external/bsd/dhcpcd/dist/ipv6nd.h:1.13	Thu Jul  9 10:15:34 2015
+++ src/external/bsd/dhcpcd/dist/ipv6nd.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6nd.h,v 1.13 2015/07/09 10:15:34 roy Exp $ */
+/* $NetBSD: ipv6nd.h,v 1.14 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -41,7 +41,7 @@ struct ra {
 	struct interface *iface;
 	struct in6_addr from;
 	char sfrom[INET6_ADDRSTRLEN];
-	unsigned char *data;
+	uint8_t *data;
 	size_t data_len;
 	struct timespec acquired;
 	unsigned char flags;
@@ -52,7 +52,6 @@ struct ra {
 	struct ipv6_addrhead addrs;
 	uint8_t hasdns;
 	uint8_t expired;
-	uint8_t no_public_warned;
 };
 
 TAILQ_HEAD(ra_head, ra);
@@ -112,7 +111,6 @@ ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
 int ipv6nd_hasra(const struct interface *);
 int ipv6nd_hasradhcp(const struct interface *);
-void ipv6nd_runignoredra(struct interface *);
 void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
     const char *, const struct in6_addr *, int);
 int ipv6nd_dadcompleted(const struct interface *);

Index: src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.11 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.12
--- src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in:1.11	Fri Aug 21 10:39:00 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $NetBSD: dhcpcd-run-hooks.in,v 1.11 2015/08/21 10:39:00 roy Exp $
+# $NetBSD: dhcpcd-run-hooks.in,v 1.12 2016/04/10 21:00:53 roy Exp $
 
 # dhcpcd client configuration script 
 
@@ -262,7 +262,8 @@ detect_init()
 	# Detect the running init system.
 	# As systemd and OpenRC can be installed on top of legacy init
 	# systems we try to detect them first.
-	_service_status=
+	local status="@STATUSARG@"
+	: ${status:=status}
 	if [ -x /bin/systemctl -a -S /run/systemd/private ]; then
 		_service_exists="/bin/systemctl --quiet is-enabled \$1.service"
 		_service_status="/bin/systemctl --quiet is-active \$1.service"
@@ -282,6 +283,9 @@ detect_init()
 	elif [ -x /sbin/service ]; then
 		_service_exists="/sbin/service \$1 >/dev/null 2>&1"
 		_service_cmd="/sbin/service \$1 \$2"
+	elif [ -x /usr/sbin/service ]; then
+		_service_exists="/usr/sbin/service \$1 $status >/dev/null 2>&1"
+		_service_cmd="/usr/sbin/service \$1 \$2"
 	elif [ -x /bin/sv ]; then
 		_service_exists="/bin/sv status \1 >/dev/null 2>&1"
 		_service_cmd="/bin/sv \$1 \$2"
@@ -291,19 +295,20 @@ detect_init()
 	elif [ -e /etc/slackware-version -a -d /etc/rc.d ]; then
 		_service_exists="[ -x /etc/rc.d/rc.\$1 ]"
 		_service_cmd="/etc/rc.d/rc.\$1 \$2"
-		_service_status="/etc/rc.d/rc.\$1 status 1>/dev/null 2>&1"
+		_service_status="/etc/rc.d/rc.\$1 status >/dev/null 2>&1"
 	else
 		for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do
 			if [ -d $x ]; then
 				_service_exists="[ -x $x/\$1 ]"
 				_service_cmd="$x/\$1 \$2"
+				_service_status="$x/\$1 $status >/dev/null 2>&1"
 				break
 			fi
 		done
 		if [ -e /etc/arch-release ]; then
 			_service_status="[ -e /var/run/daemons/\$1 ]"
 		elif [ "$x" = "/etc/rc.d" -a -e /etc/rc.d/rc.subr ]; then
-			_service_status="$x/\$1 check 1>/dev/null 2>&1"
+			_service_status="$x/\$1 check >/dev/null 2>&1"
 		fi
 	fi
 
Index: src/external/bsd/dhcpcd/dist/eloop.c
diff -u src/external/bsd/dhcpcd/dist/eloop.c:1.11 src/external/bsd/dhcpcd/dist/eloop.c:1.12
--- src/external/bsd/dhcpcd/dist/eloop.c:1.11	Sat May 16 23:31:32 2015
+++ src/external/bsd/dhcpcd/dist/eloop.c	Sun Apr 10 21:00:53 2016
@@ -1,10 +1,10 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: eloop.c,v 1.11 2015/05/16 23:31:32 roy Exp $");
+ __RCSID("$NetBSD: eloop.c,v 1.12 2016/04/10 21:00:53 roy Exp $");
 
 /*
- * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <r...@marples.name>
- * All rights reserved
+ * eloop - portable event based main loop.
+ * Copyright (c) 2006-2016 Roy Marples <r...@marples.name>
+ * All rights reserved.
 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,18 +28,59 @@
  * SUCH DAMAGE.
  */
 
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
 #include <sys/time.h>
 
 #include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <signal.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc */
+/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc. */
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
+
+/* Attempt to autodetect kqueue or epoll.
+ * Failing that, fall back to pselect. */
+#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) && !defined(HAVE_PSELECT) && \
+    !defined(HAVE_POLLTS) && !defined(HAVE_PPOLL)
+#if defined(BSD)
+/* Assume BSD has a working sys/queue.h and kqueue(2) interface. */
+#define HAVE_SYS_QUEUE_H
+#define HAVE_KQUEUE
+#elif defined(__linux__)
+/* Assume Linux has a working epoll(3) interface. */
+#define HAVE_EPOLL
+#else
+/* pselect(2) is a POSIX standard. */
+#define HAVE_PSELECT
+#endif
+#endif
+
+/* pollts and ppoll require poll.
+ * pselect is wrapped in a pollts/ppoll style interface
+ * and as such require poll as well. */
+#if defined(HAVE_PSELECT) || defined(HAVE_POLLTS) || defined(HAVE_PPOLL)
+#ifndef HAVE_POLL
+#define HAVE_POLL
+#endif
+#if defined(HAVE_POLLTS)
+#define POLLTS pollts
+#elif defined(HAVE_PPOLL)
+#define POLLTS ppoll
+#else
+#define POLLTS eloop_pollts
+#define ELOOP_NEED_POLLTS
+#endif
+#endif
+
 #include "eloop.h"
 
 #ifndef UNUSED
@@ -62,20 +103,104 @@
 #include <sys/event.h>
 #include <fcntl.h>
 #ifdef __NetBSD__
-/* udata is void * except on NetBSD
- * lengths are int except on NetBSD */
+/* udata is void * except on NetBSD.
+ * lengths are int except on NetBSD. */
 #define UPTR(x)	((intptr_t)(x))
 #define LENC(x)	(x)
 #else
 #define UPTR(x)	(x)
 #define LENC(x)	((int)(x))
 #endif
-#define eloop_event_setup_fds(eloop)
 #elif defined(HAVE_EPOLL)
 #include <sys/epoll.h>
-#define eloop_event_setup_fds(eloop)
-#else
+#elif defined(HAVE_POLL)
+#if defined(HAVE_PSELECT)
+#include <sys/select.h>
+#endif
 #include <poll.h>
+#endif
+
+/* Our structures require TAILQ macros, which really every libc should
+ * ship as they are useful beyond belief.
+ * Sadly some libc's don't have sys/queue.h and some that do don't have
+ * the TAILQ_FOREACH macro. For those that don't, the application using
+ * this implementation will need to ship a working queue.h somewhere.
+ * If we don't have sys/queue.h found in config.h, then
+ * allow QUEUE_H to override loading queue.h in the current directory. */
+#ifndef TAILQ_FOREACH
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#elif defined(QUEUE_H)
+#define __QUEUE_HEADER(x) #x
+#define _QUEUE_HEADER(x) __QUEUE_HEADER(x)
+#include _QUEUE_HEADER(QUEUE_H)
+#else
+#include "queue.h"
+#endif
+#endif
+
+struct eloop_event {
+	TAILQ_ENTRY(eloop_event) next;
+	int fd;
+	void (*read_cb)(void *);
+	void *read_cb_arg;
+	void (*write_cb)(void *);
+	void *write_cb_arg;
+};
+
+struct eloop_timeout {
+	TAILQ_ENTRY(eloop_timeout) next;
+	struct timespec when;
+	void (*callback)(void *);
+	void *arg;
+	int queue;
+};
+
+struct eloop {
+	size_t events_len;
+	TAILQ_HEAD (event_head, eloop_event) events;
+	struct event_head free_events;
+	int events_maxfd;
+	struct eloop_event **event_fds;
+
+	TAILQ_HEAD (timeout_head, eloop_timeout) timeouts;
+	struct timeout_head free_timeouts;
+
+	void (*timeout0)(void *);
+	void *timeout0_arg;
+	const int *signals;
+	size_t signals_len;
+	void (*signal_cb)(int, void *);
+	void *signal_cb_ctx;
+
+#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
+	int poll_fd;
+#elif defined(HAVE_POLL)
+	struct pollfd *fds;
+	size_t fds_len;
+#endif
+
+	int exitnow;
+	int exitcode;
+};
+
+/* Handy routing to check for potential overflow.
+ * reallocarray(3) and reallocarr(3) are not portable and this
+ * implementation is smaller than using either in libc in
+ * the final binary size. */
+#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2))
+static void *
+eloop_realloca(void *ptr, size_t n, size_t size)
+{
+
+	if ((n | size) >= SQRT_SIZE_MAX && n > SIZE_MAX / size) {
+		errno = EOVERFLOW;
+		return NULL;
+	}
+	return realloc(ptr, n * size);
+}
+
+#ifdef HAVE_POLL
 static void
 eloop_event_setup_fds(struct eloop *eloop)
 {
@@ -91,22 +216,22 @@ eloop_event_setup_fds(struct eloop *eloo
 		if (e->write_cb)
 			eloop->fds[i].events |= POLLOUT;
 		eloop->fds[i].revents = 0;
-		e->pollfd = &eloop->fds[i];
 		i++;
 	}
 }
 
-#ifndef pollts
+#ifdef ELOOP_NEED_POLLTS
 /* Wrapper around pselect, to imitate the NetBSD pollts call. */
 static int
-pollts(struct pollfd * fds, nfds_t nfds,
+eloop_pollts(struct pollfd * fds, nfds_t nfds,
     const struct timespec *ts, const sigset_t *sigmask)
 {
-	fd_set read_fds;
+	fd_set read_fds, write_fds;
 	nfds_t n;
 	int maxfd, r;
 
 	FD_ZERO(&read_fds);
+	FD_ZERO(&write_fds);
 	maxfd = 0;
 	for (n = 0; n < nfds; n++) {
 		if (fds[n].events & POLLIN) {
@@ -114,23 +239,32 @@ pollts(struct pollfd * fds, nfds_t nfds,
 			if (fds[n].fd > maxfd)
 				maxfd = fds[n].fd;
 		}
+		if (fds[n].events & POLLOUT) {
+			FD_SET(fds[n].fd, &write_fds);
+			if (fds[n].fd > maxfd)
+				maxfd = fds[n].fd;
+		}
 	}
 
-	r = pselect(maxfd + 1, &read_fds, NULL, NULL, ts, sigmask);
+	r = pselect(maxfd + 1, &read_fds, &write_fds, NULL, ts, sigmask);
 	if (r > 0) {
 		for (n = 0; n < nfds; n++) {
 			fds[n].revents =
 			    FD_ISSET(fds[n].fd, &read_fds) ? POLLIN : 0;
+			if (FD_ISSET(fds[n].fd, &write_fds))
+				fds[n].revents |= POLLOUT;
 		}
 	}
 
 	return r;
 }
-#endif
-#endif
+#endif /* pollts */
+#else /* !HAVE_POLL */
+#define eloop_event_setup_fds(a) {}
+#endif /* HAVE_POLL */
 
 int
-eloop_event_add(struct eloop *eloop, int fd,
+eloop_event_add_rw(struct eloop *eloop, int fd,
     void (*read_cb)(void *), void *read_cb_arg,
     void (*write_cb)(void *), void *write_cb_arg)
 {
@@ -139,7 +273,7 @@ eloop_event_add(struct eloop *eloop, int
 	struct kevent ke[2];
 #elif defined(HAVE_EPOLL)
 	struct epoll_event epe;
-#else
+#elif defined(HAVE_POLL)
 	struct pollfd *nfds;
 #endif
 
@@ -158,9 +292,9 @@ eloop_event_add(struct eloop *eloop, int
 		epe.events |= EPOLLOUT;
 #endif
 
-	/* We should only have one callback monitoring the fd */
-	TAILQ_FOREACH(e, &eloop->events, next) {
-		if (e->fd == fd) {
+	/* We should only have one callback monitoring the fd. */
+	if (fd <= eloop->events_maxfd) {
+		if ((e = eloop->event_fds[fd]) != NULL) {
 			int error;
 
 #if defined(HAVE_KQUEUE)
@@ -192,9 +326,26 @@ eloop_event_add(struct eloop *eloop, int
 			eloop_event_setup_fds(eloop);
 			return error;
 		}
+	} else {
+		struct eloop_event **new_fds;
+		int maxfd, i;
+
+		/* Reserve ourself and 4 more. */
+		maxfd = fd + 4;
+		new_fds = eloop_realloca(eloop->event_fds,
+		    ((size_t)maxfd + 1), sizeof(*eloop->event_fds));
+		if (new_fds == NULL)
+			return -1;
+
+		/* set new entries NULL as the fd's may not be contiguous. */
+		for (i = maxfd; i > eloop->events_maxfd; i--)
+			new_fds[i] = NULL;
+
+		eloop->event_fds = new_fds;
+		eloop->events_maxfd = maxfd;
 	}
 
-	/* Allocate a new event if no free ones already allocated */
+	/* Allocate a new event if no free ones already allocated. */
 	if ((e = TAILQ_FIRST(&eloop->free_events))) {
 		TAILQ_REMOVE(&eloop->free_events, e, next);
 	} else {
@@ -203,12 +354,12 @@ eloop_event_add(struct eloop *eloop, int
 			goto err;
 	}
 
-	/* Ensure we can actually listen to it */
+	/* Ensure we can actually listen to it. */
 	eloop->events_len++;
-#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL)
+#ifdef HAVE_POLL
 	if (eloop->events_len > eloop->fds_len) {
-		nfds = realloc(eloop->fds,
-		    sizeof(*eloop->fds) * (eloop->fds_len + 5));
+		nfds = eloop_realloca(eloop->fds,
+		    (eloop->fds_len + 5), sizeof(*eloop->fds));
 		if (nfds == NULL)
 			goto err;
 		eloop->fds_len += 5;
@@ -216,7 +367,7 @@ eloop_event_add(struct eloop *eloop, int
 	}
 #endif
 
-	/* Now populate the structure and add it to the list */
+	/* Now populate the structure and add it to the list. */
 	e->fd = fd;
 	e->read_cb = read_cb;
 	e->read_cb_arg = read_cb_arg;
@@ -238,13 +389,8 @@ eloop_event_add(struct eloop *eloop, int
 		goto err;
 #endif
 
-	/* The order of events should not matter.
-	 * However, some PPP servers love to close the link right after
-	 * sending their final message. So to ensure dhcpcd processes this
-	 * message (which is likely to be that the DHCP addresses are wrong)
-	 * we insert new events at the queue head as the link fd will be
-	 * the first event added. */
 	TAILQ_INSERT_HEAD(&eloop->events, e, next);
+	eloop->event_fds[e->fd] = e;
 	eloop_event_setup_fds(eloop);
 	return 0;
 
@@ -256,6 +402,22 @@ err:
 	return -1;
 }
 
+int
+eloop_event_add(struct eloop *eloop, int fd,
+    void (*read_cb)(void *), void *read_cb_arg)
+{
+
+	return eloop_event_add_rw(eloop, fd, read_cb, read_cb_arg, NULL, NULL);
+}
+
+int
+eloop_event_add_w(struct eloop *eloop, int fd,
+    void (*write_cb)(void *), void *write_cb_arg)
+{
+
+	return eloop_event_add_rw(eloop, fd, NULL,NULL, write_cb, write_cb_arg);
+}
+
 void
 eloop_event_delete_write(struct eloop *eloop, int fd, int write_only)
 {
@@ -268,52 +430,53 @@ eloop_event_delete_write(struct eloop *e
 
 	assert(eloop != NULL);
 
-	TAILQ_FOREACH(e, &eloop->events, next) {
-		if (e->fd == fd) {
-			if (write_only && e->read_cb != NULL) {
-				if (e->write_cb != NULL) {
-					e->write_cb = NULL;
-					e->write_cb_arg = NULL;
-#if defined(HAVE_KQUEUE)
-					EV_SET(&ke[0], (uintptr_t)fd,
-					    EVFILT_WRITE, EV_DELETE,
-					    0, 0, UPTR(NULL));
-					kevent(eloop->poll_fd, ke, 1, NULL, 0,
-					    NULL);
-#elif defined(HAVE_EPOLL)
-					memset(&epe, 0, sizeof(epe));
-					epe.data.fd = e->fd;
-					epe.data.ptr = e;
-					epe.events = EPOLLIN;
-					epoll_ctl(eloop->poll_fd,
-					    EPOLL_CTL_MOD, fd, &epe);
-#endif
-				}
-			} else {
-				TAILQ_REMOVE(&eloop->events, e, next);
-#if defined(HAVE_KQUEUE)
-				EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ,
-				    EV_DELETE, 0, 0, UPTR(NULL));
-				if (e->write_cb)
-					EV_SET(&ke[1], (uintptr_t)fd,
-					    EVFILT_WRITE, EV_DELETE,
-					    0, 0, UPTR(NULL));
-				kevent(eloop->poll_fd, ke, e->write_cb ? 2 : 1,
-				    NULL, 0, NULL);
-#elif defined(HAVE_EPOLL)
-				/* NULL event is safe because we
-				 * rely on epoll_pwait which as added
-				 * after the delete without event was fixed. */
-				epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL,
-				    fd, NULL);
+	if (fd > eloop->events_maxfd ||
+	    (e = eloop->event_fds[fd]) == NULL)
+		return;
+
+	if (write_only) {
+		if (e->write_cb == NULL)
+			return;
+		if (e->read_cb == NULL)
+			goto remove;
+		e->write_cb = NULL;
+		e->write_cb_arg = NULL;
+#if defined(HAVE_KQUEUE)
+		EV_SET(&ke[0], (uintptr_t)e->fd,
+		    EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL));
+		kevent(eloop->poll_fd, ke, 1, NULL, 0, NULL);
+#elif defined(HAVE_EPOLL)
+		memset(&epe, 0, sizeof(epe));
+		epe.data.fd = e->fd;
+		epe.data.ptr = e;
+		epe.events = EPOLLIN;
+		epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD, fd, &epe);
 #endif
-				TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
-				eloop->events_len--;
-			}
-			eloop_event_setup_fds(eloop);
-			break;
-		}
+		eloop_event_setup_fds(eloop);
+		return;
 	}
+
+remove:
+	TAILQ_REMOVE(&eloop->events, e, next);
+	eloop->event_fds[e->fd] = NULL;
+	TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
+	eloop->events_len--;
+
+#if defined(HAVE_KQUEUE)
+	EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ,
+	    EV_DELETE, 0, 0, UPTR(NULL));
+	if (e->write_cb)
+		EV_SET(&ke[1], (uintptr_t)fd,
+		    EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL));
+	kevent(eloop->poll_fd, ke, e->write_cb ? 2 : 1, NULL, 0, NULL);
+#elif defined(HAVE_EPOLL)
+	/* NULL event is safe because we
+	 * rely on epoll_pwait which as added
+	 * after the delete without event was fixed. */
+	epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL, fd, NULL);
+#endif
+
+	eloop_event_setup_fds(eloop);
 }
 
 int
@@ -335,7 +498,7 @@ eloop_q_timeout_add_tv(struct eloop *elo
 		return -1;
 	}
 
-	/* Remove existing timeout if present */
+	/* Remove existing timeout if present. */
 	TAILQ_FOREACH(t, &eloop->timeouts, next) {
 		if (t->callback == callback && t->arg == arg) {
 			TAILQ_REMOVE(&eloop->timeouts, t, next);
@@ -344,7 +507,7 @@ eloop_q_timeout_add_tv(struct eloop *elo
 	}
 
 	if (t == NULL) {
-		/* No existing, so allocate or grab one from the free pool */
+		/* No existing, so allocate or grab one from the free pool. */
 		if ((t = TAILQ_FIRST(&eloop->free_timeouts))) {
 			TAILQ_REMOVE(&eloop->free_timeouts, t, next);
 		} else {
@@ -459,10 +622,16 @@ eloop_open(struct eloop *eloop)
 	return (eloop->poll_fd = epoll_create1(EPOLL_CLOEXEC));
 #endif
 }
+#endif
 
 int
 eloop_requeue(struct eloop *eloop)
 {
+#if defined(HAVE_POLL)
+
+	UNUSED(eloop);
+	return 0;
+#else /* !HAVE_POLL */
 	struct eloop_event *e;
 	int error;
 #if defined(HAVE_KQUEUE)
@@ -523,8 +692,8 @@ eloop_requeue(struct eloop *eloop)
 #endif
 
 	return error;
+#endif /* HAVE_POLL */
 }
-#endif
 
 int
 eloop_signal_set_cb(struct eloop *eloop,
@@ -615,13 +784,17 @@ eloop_new(void)
 	eloop = calloc(1, sizeof(*eloop));
 	if (eloop) {
 		TAILQ_INIT(&eloop->events);
+		eloop->events_maxfd = -1;
 		TAILQ_INIT(&eloop->free_events);
 		TAILQ_INIT(&eloop->timeouts);
 		TAILQ_INIT(&eloop->free_timeouts);
 		eloop->exitcode = EXIT_FAILURE;
 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
 		eloop->poll_fd = -1;
-		eloop_open(eloop);
+		if (eloop_open(eloop) == -1) {
+			eloop_free(eloop);
+			return NULL;
+		}
 #endif
 	}
 
@@ -636,6 +809,7 @@ void eloop_free(struct eloop *eloop)
 	if (eloop == NULL)
 		return;
 
+	free(eloop->event_fds);
 	while ((e = TAILQ_FIRST(&eloop->events))) {
 		TAILQ_REMOVE(&eloop->events, e, next);
 		free(e);
@@ -654,7 +828,7 @@ void eloop_free(struct eloop *eloop)
 	}
 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
 	close(eloop->poll_fd);
-#else
+#elif defined(HAVE_POLL)
 	free(eloop->fds);
 #endif
 	free(eloop);
@@ -686,7 +860,7 @@ eloop_start(struct eloop *eloop, sigset_
 		if (eloop->exitnow)
 			break;
 
-		/* Run all timeouts first */
+		/* Run all timeouts first. */
 		if (eloop->timeout0) {
 			t0 = eloop->timeout0;
 			eloop->timeout0 = NULL;
@@ -704,7 +878,7 @@ eloop_start(struct eloop *eloop, sigset_
 			timespecsub(&t->when, &now, &ts);
 			tsp = &ts;
 		} else
-			/* No timeouts, so wait forever */
+			/* No timeouts, so wait forever. */
 			tsp = NULL;
 
 		if (tsp == NULL && eloop->events_len == 0)
@@ -730,9 +904,9 @@ eloop_start(struct eloop *eloop, sigset_
 			    timeout, signals);
 		else
 			n = epoll_wait(eloop->poll_fd, &epe, 1, timeout);
-#else
+#elif defined(HAVE_POLL)
 		if (signals)
-			n = pollts(eloop->fds, (nfds_t)eloop->events_len,
+			n = POLLTS(eloop->fds, (nfds_t)eloop->events_len,
 			    tsp, signals);
 		else
 			n = poll(eloop->fds, (nfds_t)eloop->events_len,
@@ -778,18 +952,24 @@ eloop_start(struct eloop *eloop, sigset_
 				continue;
 			}
 		}
-#else
+#elif defined(HAVE_POLL)
 		if (n > 0) {
-			TAILQ_FOREACH(e, &eloop->events, next) {
-				if (e->pollfd->revents & POLLOUT &&
-				    e->write_cb != NULL)
-				{
-					e->write_cb(e->write_cb_arg);
-					break;
+			size_t i;
+
+			for (i = 0; i < eloop->events_len; i++) {
+				if (eloop->fds[i].revents & POLLOUT) {
+					e = eloop->event_fds[eloop->fds[i].fd];
+					if (e->write_cb != NULL) {
+						e->write_cb(e->write_cb_arg);
+						break;
+					}
 				}
-				if (e->pollfd->revents && e->read_cb != NULL) {
-					e->read_cb(e->read_cb_arg);
-					break;
+				if (eloop->fds[i].revents) {
+					e = eloop->event_fds[eloop->fds[i].fd];
+					if (e->read_cb != NULL) {
+						e->read_cb(e->read_cb_arg);
+						break;
+					}
 				}
 			}
 		}

Index: src/external/bsd/dhcpcd/dist/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.31 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.32
--- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.31	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/dhcpcd.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd.c,v 1.31 2016/01/20 19:42:33 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd.c,v 1.32 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -67,6 +67,10 @@ const char dhcpcd_copyright[] = "Copyrig
 #include "ipv6nd.h"
 #include "script.h"
 
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
 #ifdef USE_SIGNALS
 const int dhcpcd_signals[] = {
 	SIGTERM,
@@ -80,34 +84,6 @@ const int dhcpcd_signals[] = {
 const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
 #endif
 
-#if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK)
-static pid_t
-read_pid(const char *pidfile)
-{
-	FILE *fp;
-	pid_t pid;
-
-	if ((fp = fopen(pidfile, "r")) == NULL) {
-		errno = ENOENT;
-		return 0;
-	}
-	if (fscanf(fp, "%d", &pid) != 1)
-		pid = 0;
-	fclose(fp);
-	return pid;
-}
-
-static int
-write_pid(int fd, pid_t pid)
-{
-
-	if (ftruncate(fd, (off_t)0) == -1)
-		return -1;
-	lseek(fd, (off_t)0, SEEK_SET);
-	return dprintf(fd, "%d\n", (int)pid);
-}
-#endif
-
 static void
 usage(void)
 {
@@ -229,7 +205,7 @@ dhcpcd_ifafwaiting(const struct interfac
 {
 	unsigned long long opts;
 
-	if (!ifp->active)
+	if (ifp->active != IF_ACTIVE_USER)
 		return AF_MAX;
 
 	opts = ifp->options->options;
@@ -310,7 +286,7 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 	errno = ENOSYS;
 	return 0;
 #else
-	pid_t pid;
+	pid_t pid, lpid;
 	char buf = '\0';
 	int sidpipe[2], fd;
 
@@ -351,6 +327,9 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 		logger(ctx, LOG_ERR, "fork: %m");
 		return 0;
 	case 0:
+		if ((lpid = pidfile_lock(ctx->pidfile)) != 0)
+			logger(ctx, LOG_ERR, "%s: pidfile_lock %d: %m",
+			    __func__, lpid);
 		setsid();
 		/* Notify parent it's safe to exit as we've detached. */
 		close(sidpipe[0]);
@@ -381,9 +360,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 	/* Done with the fd now */
 	if (pid != 0) {
 		logger(ctx, LOG_INFO, "forked to background, child pid %d", pid);
-		write_pid(ctx->pid_fd, pid);
-		close(ctx->pid_fd);
-		ctx->pid_fd = -1;
 		ctx->options |= DHCPCD_FORKED;
 		eloop_exit(ctx->eloop, EXIT_SUCCESS);
 		return pid;
@@ -427,7 +403,8 @@ stop_interface(struct interface *ifp)
 	eloop_q_timeout_delete(ctx->eloop, 0, NULL, ifp);
 
 	/* De-activate the interface */
-	ifp->active = 0;
+	ifp->active = IF_INACTIVE;
+	ifp->options->options &= ~DHCPCD_STOPPING;
 
 stop:
 	if (!(ctx->options & (DHCPCD_MASTER | DHCPCD_TEST)))
@@ -674,13 +651,21 @@ dhcpcd_pollup(void *arg)
 }
 
 static void
-dhcpcd_initstate1(struct interface *ifp, int argc, char **argv,
-    unsigned long long options)
+dhcpcd_initstate2(struct interface *ifp, unsigned long long options)
 {
 	struct if_options *ifo;
 
-	configure_interface(ifp, argc, argv, options);
-	ifo = ifp->options;
+	if (options) {
+		if ((ifo = default_config(ifp->ctx)) == NULL) {
+			logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
+			    ifp->name, __func__);
+			return;
+		}
+		ifo->options |= options;
+		free(ifp->options);
+		ifp->options = ifo;
+	} else
+		ifo = ifp->options;
 
 	if (ifo->options & DHCPCD_IPV4 && ipv4_init(ifp->ctx) == -1) {
 		logger(ifp->ctx, LOG_ERR, "ipv4_init: %m");
@@ -702,6 +687,15 @@ dhcpcd_initstate1(struct interface *ifp,
 }
 
 static void
+dhcpcd_initstate1(struct interface *ifp, int argc, char **argv,
+    unsigned long long options)
+{
+
+	configure_interface(ifp, argc, argv, options);
+	dhcpcd_initstate2(ifp, 0);
+}
+
+static void
 dhcpcd_initstate(struct interface *ifp, unsigned long long options)
 {
 
@@ -775,7 +769,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 			dhcpcd_handleinterface(ctx, 0, ifp->name);
 #endif
 			if (ifp->wireless) {
-				uint8_t ossid[IF_SSIDSIZE];
+				uint8_t ossid[IF_SSIDLEN];
 #ifdef NOCARRIER_PRESERVE_IP
 				size_t olen;
 
@@ -911,6 +905,8 @@ dhcpcd_startinterface(void *arg)
 	}
 
 	if (ifo->options & DHCPCD_IPV6) {
+		ipv6_startstatic(ifp);
+
 		if (ifo->options & DHCPCD_IPV6RS)
 			ipv6nd_startrs(ifp);
 
@@ -948,11 +944,13 @@ dhcpcd_startinterface(void *arg)
 		}
 	}
 
+#ifdef INET
 	if (ifo->options & DHCPCD_IPV4) {
 		/* Ensure we have an IPv4 state before starting DHCP */
 		if (ipv4_getstate(ifp) != NULL)
 			dhcp_start(ifp);
 	}
+#endif
 }
 
 static void
@@ -1000,12 +998,13 @@ run_preinit(struct interface *ifp)
 }
 
 void
-dhcpcd_activateinterface(struct interface *ifp)
+dhcpcd_activateinterface(struct interface *ifp, unsigned long long options)
 {
 
 	if (!ifp->active) {
-		ifp->active = 1;
-		dhcpcd_initstate(ifp, 0);
+		ifp->active = IF_ACTIVE;
+		dhcpcd_initstate2(ifp, options);
+		configure_interface1(ifp);
 		run_preinit(ifp);
 		dhcpcd_prestartinterface(ifp);
 	}
@@ -1068,7 +1067,7 @@ dhcpcd_handleinterface(void *arg, int ac
 				if (strcmp(ctx->ifv[i], ifname) == 0)
 					break;
 			if (i >= ctx->ifc)
-				ifp->active = 0;
+				ifp->active = IF_INACTIVE;
 		}
 
 		i = 0;
@@ -1185,7 +1184,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in
 			else
 				ipv4_applyaddr(ifp);
 		} else if (i != argc) {
-			ifp->active = 1;
+			ifp->active = IF_ACTIVE_USER;
 			dhcpcd_initstate1(ifp, argc, argv, 0);
 			run_preinit(ifp);
 			dhcpcd_prestartinterface(ifp);
@@ -1309,6 +1308,8 @@ dhcpcd_getinterfaces(void *arg)
 			len++;
 		if (IPV4LL_STATE_RUNNING(ifp))
 			len++;
+		if (IPV6_STATE_RUNNING(ifp))
+			len++;
 		if (RS_STATE_RUNNING(ifp))
 			len++;
 		if (D6_STATE_RUNNING(ifp))
@@ -1347,7 +1348,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 		return control_queue(fd, UNCONST(fd->ctx->cffile),
 		    strlen(fd->ctx->cffile) + 1, 0);
 	} else if (strcmp(*argv, "--getinterfaces") == 0) {
-		eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
+		eloop_event_add_w(fd->ctx->eloop, fd->fd,
 		    dhcpcd_getinterfaces, fd);
 		return 0;
 	} else if (strcmp(*argv, "--listen") == 0) {
@@ -1482,11 +1483,8 @@ main(int argc, char **argv)
 
 	ifo = NULL;
 	ctx.cffile = CONFIG;
-	ctx.pid_fd = ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
+	ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
 	ctx.pf_inet_fd = -1;
-#if defined(INET6) && defined(BSD)
-	ctx.pf_inet6_fd = -1;
-#endif
 #ifdef IFLR_ACTIVE
 	ctx.pf_link_fd = -1;
 #endif
@@ -1766,14 +1764,14 @@ printpidfile:
 
 #ifdef USE_SIGNALS
 	if (sig != 0) {
-		pid = read_pid(ctx.pidfile);
-		if (pid != 0)
+		pid = pidfile_read(ctx.pidfile);
+		if (pid != 0 && pid != -1)
 			logger(&ctx, LOG_INFO, "sending signal %s to pid %d",
 			    siga, pid);
-		if (pid == 0 || kill(pid, sig) != 0) {
+		if (pid == 0 || pid == -1 || kill(pid, sig) != 0) {
 			if (sig != SIGHUP && sig != SIGUSR1 && errno != EPERM)
 				logger(&ctx, LOG_ERR, ""PACKAGE" not running");
-			if (pid != 0 && errno != ESRCH) {
+			if (pid != 0 && pid != -1 && errno != ESRCH) {
 				logger(&ctx, LOG_ERR, "kill: %m");
 				goto exit_failure;
 			}
@@ -1792,7 +1790,7 @@ printpidfile:
 			ts.tv_nsec = 100000000; /* 10th of a second */
 			for(i = 0; i < 100; i++) {
 				nanosleep(&ts, NULL);
-				if (read_pid(ctx.pidfile) == 0)
+				if (pidfile_read(ctx.pidfile) == -1)
 					goto exit_success;
 			}
 			logger(&ctx, LOG_ERR, "pid %d failed to exit", pid);
@@ -1801,12 +1799,14 @@ printpidfile:
 	}
 
 	if (!(ctx.options & DHCPCD_TEST)) {
-		if ((pid = read_pid(ctx.pidfile)) > 0 &&
-		    kill(pid, 0) == 0)
-		{
-			logger(&ctx, LOG_ERR, ""PACKAGE
-			    " already running on pid %d (%s)",
-			    pid, ctx.pidfile);
+		if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
+			if (pid == -1)
+				logger(&ctx, LOG_ERR, "%s: pidfile_lock: %m",
+				    __func__);
+			else	
+				logger(&ctx, LOG_ERR, ""PACKAGE
+				    " already running on pid %d (%s)",
+				    pid, ctx.pidfile);
 			goto exit_failure;
 		}
 
@@ -1815,40 +1815,6 @@ printpidfile:
 			logger(&ctx, LOG_ERR, "mkdir `%s': %m", RUNDIR);
 		if (mkdir(DBDIR, 0755) == -1 && errno != EEXIST)
 			logger(&ctx, LOG_ERR, "mkdir `%s': %m", DBDIR);
-
-		opt = O_WRONLY | O_CREAT | O_NONBLOCK;
-#ifdef O_CLOEXEC
-		opt |= O_CLOEXEC;
-#endif
-		ctx.pid_fd = open(ctx.pidfile, opt, 0664);
-		if (ctx.pid_fd == -1)
-			logger(&ctx, LOG_ERR, "open `%s': %m", ctx.pidfile);
-		else {
-#ifdef LOCK_EX
-			/* Lock the file so that only one instance of dhcpcd
-			 * runs on an interface */
-			if (flock(ctx.pid_fd, LOCK_EX | LOCK_NB) == -1) {
-				logger(&ctx, LOG_ERR, "flock `%s': %m",
-				    ctx.pidfile);
-				/* We don't want to unlink the pidfile as
-				 * another dhcpcd instance could be using it. */
-				ctx.pidfile[0] = '\0';
-				goto exit_failure;
-			}
-#endif
-#ifndef O_CLOEXEC
-			if (fcntl(ctx.pid_fd, F_GETFD, &opt) == -1 ||
-			    fcntl(ctx.pid_fd, F_SETFD, opt | FD_CLOEXEC) == -1)
-			{
-				logger(&ctx, LOG_ERR, "fcntl: %m");
-				/* We don't want to unlink the pidfile as
-				 * another dhcpcd instance could be using it. */
-				ctx.pidfile[0] = '\0';
-				goto exit_failure;
-			}
-#endif
-			write_pid(ctx.pid_fd, getpid());
-		}
 	}
 
 	if (ctx.options & DHCPCD_MASTER) {
@@ -1888,7 +1854,7 @@ printpidfile:
 
 	/* Start handling kernel messages for interfaces, addreses and
 	 * routes. */
-	eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx, NULL, NULL);
+	eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx);
 
 	/* Start any dev listening plugin which may want to
 	 * change the interface name provided by the kernel */
@@ -1909,7 +1875,7 @@ printpidfile:
 			    ctx.ifv[i]);
 	}
 	TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-		if (ifp->active)
+		if (ifp->active == IF_ACTIVE_USER)
 			break;
 	}
 	if (ifp == NULL) {
@@ -2008,17 +1974,7 @@ exit1:
 		eloop_event_delete(ctx.eloop, ctx.link_fd);
 		close(ctx.link_fd);
 	}
-	if (ctx.pf_inet_fd != -1)
-		close(ctx.pf_inet_fd);
-#if defined(INET6) && defined(BSD)
-	if (ctx.pf_inet6_fd != -1)
-		close(ctx.pf_inet6_fd);
-#endif
-#ifdef IFLR_ACTIVE
-	if (ctx.pf_link_fd != -1)
-		close(ctx.pf_link_fd);
-#endif
-
+	if_closesockets(&ctx);
 	free_options(ifo);
 	free_globals(&ctx);
 	ipv4_ctxfree(&ctx);
@@ -2026,16 +1982,15 @@ exit1:
 	dev_stop(&ctx);
 	if (control_stop(&ctx) == -1)
 		logger(&ctx, LOG_ERR, "control_stop: %m:");
-	if (ctx.pid_fd != -1) {
-		close(ctx.pid_fd);
-		if (ctx.pidfile[0] != '\0')
-			unlink(ctx.pidfile);
-	}
 	eloop_free(ctx.eloop);
 
 	if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED))
 		logger(&ctx, LOG_INFO, PACKAGE " exited");
 	logger_close(&ctx);
 	free(ctx.logfile);
+#ifdef USE_SIGNALS
+	if (ctx.options & DHCPCD_FORKED)
+		_exit(i); /* so atexit won't remove our pidfile */
+#endif
 	return i;
 }

Index: src/external/bsd/dhcpcd/dist/dhcpcd.h
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.h:1.15 src/external/bsd/dhcpcd/dist/dhcpcd.h:1.16
--- src/external/bsd/dhcpcd/dist/dhcpcd.h:1.15	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/dhcpcd.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcpcd.h,v 1.15 2016/01/20 19:42:33 roy Exp $ */
+/* $NetBSD: dhcpcd.h,v 1.16 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -43,10 +43,14 @@
 #include "if-options.h"
 
 #define HWADDR_LEN	20
-#define IF_SSIDSIZE	33
+#define IF_SSIDLEN	32
 #define PROFILE_LEN	64
 #define SECRET_LEN	64
 
+#define IF_INACTIVE	0
+#define IF_ACTIVE	1
+#define IF_ACTIVE_USER	2
+
 #define LINK_UP		1
 #define LINK_UNKNOWN	0
 #define LINK_DOWN	-1
@@ -85,7 +89,7 @@ struct interface {
 	unsigned int metric;
 	int carrier;
 	int wireless;
-	uint8_t ssid[IF_SSIDSIZE];
+	uint8_t ssid[IF_SSIDLEN + 1]; /* NULL terminated */
 	unsigned int ssid_len;
 
 	char profile[PROFILE_LEN];
@@ -95,7 +99,6 @@ struct interface {
 TAILQ_HEAD(if_head, interface);
 
 struct dhcpcd_ctx {
-	int pid_fd;
 	char pidfile[sizeof(PIDFILE) + IF_NAMESIZE + 1];
 	const char *cffile;
 	unsigned long long options;
@@ -116,12 +119,10 @@ struct dhcpcd_ctx {
 	struct if_head *ifaces;
 
 	int pf_inet_fd;
-#if defined(INET6) && defined(BSD)
-	int pf_inet6_fd;
-#endif
 #ifdef IFLR_ACTIVE
 	int pf_link_fd;
 #endif
+	void *priv;
 	int link_fd;
 	int seq;	/* route message sequence no */
 	int sseq;	/* successful seq no sent */
@@ -204,6 +205,6 @@ void dhcpcd_dropinterface(struct interfa
 int dhcpcd_selectprofile(struct interface *, const char *);
 
 void dhcpcd_startinterface(void *);
-void dhcpcd_activateinterface(struct interface *);
+void dhcpcd_activateinterface(struct interface *, unsigned long long);
 
 #endif
Index: src/external/bsd/dhcpcd/dist/ipv4.h
diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.15 src/external/bsd/dhcpcd/dist/ipv4.h:1.16
--- src/external/bsd/dhcpcd/dist/ipv4.h:1.15	Mon Feb  1 16:47:00 2016
+++ src/external/bsd/dhcpcd/dist/ipv4.h	Sun Apr 10 21:00:53 2016
@@ -1,8 +1,8 @@
-/* $NetBSD: ipv4.h,v 1.15 2016/02/01 16:47:00 christos Exp $ */
+/* $NetBSD: ipv4.h,v 1.16 2016/04/10 21:00:53 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
@@ -116,7 +116,7 @@ int ipv4_preferanother(struct interface 
 struct ipv4_addr *ipv4_addaddr(struct interface *,
     const struct in_addr *, const struct in_addr *, const struct in_addr *);
 void ipv4_applyaddr(void *);
-int ipv4_handlert(struct dhcpcd_ctx *, int, struct rt *);
+int ipv4_handlert(struct dhcpcd_ctx *, int, const struct rt *, int);
 void ipv4_freerts(struct rt_head *);
 
 struct ipv4_addr *ipv4_iffindaddr(struct interface *,
@@ -142,7 +142,7 @@ void ipv4_ctxfree(struct dhcpcd_ctx *);
 #define ipv4_free(a) {}
 #define ipv4_ctxfree(a) {}
 #define ipv4_hasaddr(a) (0)
-#define ipv4_preferanother(a) (0)
+#define ipv4_preferanother(a) {}
 #endif
 
 #endif

Index: src/external/bsd/dhcpcd/dist/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.27 src/external/bsd/dhcpcd/dist/if-bsd.c:1.28
--- src/external/bsd/dhcpcd/dist/if-bsd.c:1.27	Mon Feb  1 16:47:00 2016
+++ src/external/bsd/dhcpcd/dist/if-bsd.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-bsd.c,v 1.27 2016/02/01 16:47:00 christos Exp $");
+ __RCSID("$NetBSD: if-bsd.c,v 1.28 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -60,7 +60,6 @@
 #  include <net80211/ieee80211_ioctl.h>
 #endif
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fnmatch.h>
@@ -97,18 +96,22 @@
 
 #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) = ((struct sockaddr_in *)(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) = ((struct sockaddr_in6 *)(void *)(sa))->sin6_addr;     \
 	} while (0)
 
 #ifndef CLLADDR
 #  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
 #endif
 
+struct priv {
+	int pf_inet6_fd;
+};
+
 int
 if_init(__unused struct interface *iface)
 {
@@ -124,10 +127,36 @@ if_conf(__unused struct interface *iface
 }
 
 int
-if_openlinksocket(void)
+if_opensockets_os(struct dhcpcd_ctx *ctx)
 {
+	struct priv *priv;
+
+	if ((priv = malloc(sizeof(*priv))) == NULL)
+		return -1;
+	ctx->priv = priv;
+
+#ifdef INET6
+	priv->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM, 0, SOCK_CLOEXEC);
+	/* Don't return an error so we at least work on kernels witout INET6
+	 * even though we expect INET6 support.
+	 * We will fail noisily elsewhere anyway. */
+#else
+	priv->pf_inet6_fd = -1;
+#endif
 
-	return xsocket(PF_ROUTE, SOCK_RAW, 0, O_NONBLOCK|O_CLOEXEC);
+	ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW, 0,
+	    SOCK_CLOEXEC | SOCK_NONBLOCK);
+	return ctx->link_fd == -1 ? -1 : 0;
+}
+
+void
+if_closesockets_os(struct dhcpcd_ctx *ctx)
+{
+	struct priv *priv;
+
+	priv = (struct priv *)ctx->priv;
+	if (priv->pf_inet6_fd != -1)
+		close(priv->pf_inet6_fd);
 }
 
 #if defined(INET) || defined(INET6)
@@ -152,7 +181,7 @@ if_getssid1(int s, const char *ifname, u
 	struct ieee80211_nwid nwid;
 #elif defined(IEEE80211_IOC_SSID)
 	struct ieee80211req ireq;
-	char nwid[IEEE80211_NWID_LEN + 1];
+	char nwid[IEEE80211_NWID_LEN];
 #endif
 
 #if defined(SIOCG80211NWID) /* NetBSD */
@@ -163,13 +192,11 @@ if_getssid1(int s, const char *ifname, u
 	if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
 		if (ssid == NULL)
 			retval = nwid.i_len;
-		else if (nwid.i_len > IF_SSIDSIZE) {
+		else if (nwid.i_len > IF_SSIDLEN)
 			errno = ENOBUFS;
-			retval = -1;
-		} else {
+		else {
 			retval = nwid.i_len;
 			memcpy(ssid, nwid.i_nwid, nwid.i_len);
-			ssid[nwid.i_len] = '\0';
 		}
 	}
 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
@@ -182,15 +209,15 @@ if_getssid1(int s, const char *ifname, u
 	if (ioctl(s, SIOCG80211, &ireq) == 0) {
 		if (ssid == NULL)
 			retval = ireq.i_len;
-		else if (ireq.i_len > IF_SSIDSIZE) {
+		else if (ireq.i_len > IF_SSIDLEN)
 			errno = ENOBUFS;
-			retval = -1;
-		} else  {
+		else  {
 			retval = ireq.i_len;
 			memcpy(ssid, nwid, ireq.i_len);
-			ssid[ireq.i_len] = '\0';
 		}
 	}
+#else
+	errno = ENOSYS;
 #endif
 
 	return retval;
@@ -204,6 +231,9 @@ if_getssid(struct interface *ifp)
 	r = if_getssid1(ifp->ctx->pf_inet_fd, ifp->name, ifp->ssid);
 	if (r != -1)
 		ifp->ssid_len = (unsigned int)r;
+	else
+		ifp->ssid_len = 0;
+	ifp->ssid[ifp->ssid_len] = '\0';
 	return r;
 }
 
@@ -294,21 +324,40 @@ if_openrawsocket(struct interface *ifp, 
 #ifdef BIOCIMMEDIATE
 	int flags;
 #endif
+#ifndef O_CLOEXEC
+	int fd_opts;
+#endif
+
 #ifdef _PATH_BPF
-	fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+	fd = open(_PATH_BPF, O_RDWR | O_NONBLOCK
+#ifdef O_CLOEXEC
+		| O_CLOEXEC
+#endif
+	);
 #else
 	char device[32];
 	int n = 0;
 
 	do {
 		snprintf(device, sizeof(device), "/dev/bpf%d", n++);
-		fd = open(device, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+		fd = open(device, O_RDWR | O_NONBLOCK
+#ifdef O_CLOEXEC
+				| O_CLOEXEC
+#endif
+		);
 	} while (fd == -1 && errno == EBUSY);
 #endif
 
 	if (fd == -1)
 		return -1;
 
+#ifndef O_CLOEXEC
+	if ((fd_opts = fcntl(fd, F_GETFD)) == -1 ||
+	    fcntl(fd, F_SETFD, fd_opts | FD_CLOEXEC) == -1) {
+		close(fd);
+		return -1;
+	}
+#endif
 	state = IPV4_STATE(ifp);
 	memset(&pv, 0, sizeof(pv));
 	if (ioctl(fd, BIOCVERSION, &pv) == -1)
@@ -469,8 +518,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	struct sockaddr_in *sin;
 	struct ipv4_addr *ia;
 
-	cp = (char *)(void *)(rtm + 1);
-	sa = (struct sockaddr *)(void *)cp;
+	cp = (void *)(rtm + 1);
+	sa = (void *)cp;
 	if (sa->sa_family != AF_INET)
 		return -1;
 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
@@ -503,7 +552,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	if (rtm->rtm_index)
 		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
 	else if (rtm->rtm_addrs & RTA_IFP) {
-		sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
+		sdl = (void *)rti_info[RTAX_IFP];
 		rt->iface = if_findsdl(ctx, sdl);
 	} else if (rtm->rtm_addrs & RTA_GATEWAY) {
 		sa = rti_info[RTAX_GATEWAY];
@@ -518,8 +567,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 				rt->iface = ia->iface;
 			break;
 		default:
-			logger(ctx, LOG_ERR, "%s: Bad family %d", __func__,
-			    sa->sa_family);
+			errno = EAFNOSUPPORT;
+			logger(ctx, LOG_ERR, "%s: %m", __func__);
 			return -1;
 		}
 	}
@@ -533,8 +582,10 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 			rt->iface = ia->iface;
 	}
 
-	assert(rt->iface != NULL);
-
+	if (rt->iface == NULL) {
+		errno = ESRCH;
+		return -1;
+	}
 	return 0;
 }
 
@@ -596,6 +647,9 @@ if_route(unsigned char cmd, const struct
 #ifdef RTF_CLONING
 			rtm.hdr.rtm_flags |= RTF_CLONING;
 #endif
+#ifdef RTF_CONNECTED
+			rtm.hdr.rtm_flags |= RTF_CONNECTED;
+#endif
 #ifdef RTP_CONNECTED
 			rtm.hdr.rtm_priority = RTP_CONNECTED;
 #endif
@@ -644,6 +698,9 @@ if_route(unsigned char cmd, const struct
 #ifdef RTF_CLONING
 		    rtm.hdr.rtm_flags & RTF_CLONING ||
 #endif
+#ifdef RTF_CONNECTED
+		    rtm.hdr.rtm_flags & RTF_CONNECTED ||
+#endif
 		    !(rtm.hdr.rtm_flags & RTF_STATIC))
 		{
 			if_linkaddr(&su.sdl, rt->iface);
@@ -712,9 +769,9 @@ if_initrt(struct interface *ifp)
 
 	end = buf + needed;
 	for (p = buf; p < end; p += rtm->rtm_msglen) {
-		rtm = (struct rt_msghdr *)(void *)p;
+		rtm = (void *)p;
 		if (if_copyrt(ifp->ctx, &rt, rtm) == 0)
-			ipv4_handlert(ifp->ctx, RTM_ADD, &rt);
+			ipv4_handlert(ifp->ctx, RTM_ADD, &rt, 1);
 	}
 	free(buf);
 	return 0;
@@ -729,7 +786,7 @@ if_addrflags(const struct in_addr *addr,
 
 	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
-	sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
+	sin = (void *)&ifr.ifr_addr;
 	sin->sin_family = AF_INET;
 	sin->sin_addr = *addr;
 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
@@ -784,6 +841,7 @@ if_address6(const struct ipv6_addr *ia, 
 {
 	struct in6_aliasreq ifa;
 	struct in6_addr mask;
+	struct priv *priv;
 
 	memset(&ifa, 0, sizeof(ifa));
 	strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name));
@@ -818,7 +876,8 @@ if_address6(const struct ipv6_addr *ia, 
 	ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
 #undef ADDADDR
 
-	return ioctl(ia->iface->ctx->pf_inet6_fd,
+	priv = (struct priv *)ia->iface->ctx->priv;
+	return ioctl(priv->pf_inet6_fd,
 	    action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
 }
 
@@ -829,9 +888,11 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 	char *cp;
 	struct sockaddr *sa, *rti_info[RTAX_MAX];
 	struct sockaddr_dl *sdl;
+	struct sockaddr_in6 *sin;
+	struct ipv6_addr *ia;
 
-	cp = (char *)(void *)(rtm + 1);
-	sa = (struct sockaddr *)(void *)cp;
+	cp = (void *)(rtm + 1);
+	sa = (void *)cp;
 	if (sa->sa_family != AF_INET6)
 		return -1;
 	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
@@ -852,6 +913,7 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 	memset(rt, 0, sizeof(*rt));
 	rt->flags = (unsigned int)rtm->rtm_flags;
 	COPYOUT6(rt->dest, rti_info[RTAX_DST]);
+	DESCOPE(&rt->dest);
 	if (rtm->rtm_addrs & RTA_NETMASK) {
 		/*
 		 * We need to zero out the struct beyond sin6_len and
@@ -861,19 +923,25 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 		 * Either way it needs to be zeroed out.
 		 */
 		struct sockaddr_in6 *sin6;
-		size_t e, i, len = 0, final = 0;
+		size_t e, i, final = 0, illegal = 0;
+		const unsigned char *p;
 
-		sin6 = (struct sockaddr_in6 *)(void *)rti_info[RTAX_NETMASK];
+		sin6 = (void *)rti_info[RTAX_NETMASK];
 		rt->net = sin6->sin6_addr;
 		e = sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr);
 		if (e > sizeof(struct in6_addr))
 			e = sizeof(struct in6_addr);
-		for (i = 0; i < e; i++) {
-			switch (rt->net.s6_addr[i] & 0xff) {
+		for (p = (const unsigned char *)&sin6->sin6_addr, i = 0;
+		    i < e;
+		    p++)
+		{
+			if (final && *p) {
+				illegal = 1;
+				rt->net.s6_addr[i++] = 0x00;
+				continue;
+			}
+			switch (*p & 0xff) {
 			case 0xff:
-				/* We don't really want the length,
-				 * just that it's valid */
-				len++;
 				break;
 			case 0xfe:
 			case 0xfc:
@@ -882,35 +950,48 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 			case 0xe0:
 			case 0xc0:
 			case 0x80:
-				len++;
 				final = 1;
 				break;
 			default:
-				rt->net.s6_addr[i] = 0x00;
 				final = 1;
+				illegal = 1;
 				break;
 			}
-			if (final)
-				break;
+			if (!illegal)
+				rt->net.s6_addr[i++] &= *p;
+			else
+				rt->net.s6_addr[i++] = 0x00;
 		}
-		if (len == 0)
-			i = 0;
 		while (i < sizeof(rt->net.s6_addr))
 			rt->net.s6_addr[i++] = 0x00;
 	} else
 		ipv6_mask(&rt->net, 128);
 	COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
+	DESCOPE(&rt->gate);
 	rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
 
 	if (rtm->rtm_index)
 		rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
 	else if (rtm->rtm_addrs & RTA_IFP) {
-		sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
+		sdl = (void *)rti_info[RTAX_IFP];
 		rt->iface = if_findsdl(ctx, sdl);
 	} else if (rtm->rtm_addrs & RTA_GATEWAY) {
-		sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_GATEWAY];
-		if (sdl->sdl_family == AF_LINK)
+		sa = rti_info[RTAX_GATEWAY];
+		switch (sa->sa_family) {
+		case AF_LINK:
+			sdl = (void *)sa;
 			rt->iface = if_findsdl(ctx, sdl);
+			break;
+		case AF_INET6:
+			sin = (void *)sa;
+			if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr)))
+				rt->iface = ia->iface;
+			break;
+		default:
+			errno = EAFNOSUPPORT;
+			logger(ctx, LOG_ERR, "%s: %m", __func__);
+			return -1;
+		}
 	}
 
 	/* If we don't have an interface and it's a host route, it maybe
@@ -918,14 +999,14 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struc
 	if (rt->iface == NULL &&
 	    !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY)))
 	{
-		struct ipv6_addr *ia;
-
 		if ((ia = ipv6_findaddr(ctx, &rt->dest, 0)))
 			rt->iface = ia->iface;
 	}
 
-	assert(rt->iface != NULL);
-
+	if (rt->iface == NULL) {
+		errno = ESRCH;
+		return -1;
+	}
 	return 0;
 }
 
@@ -982,16 +1063,20 @@ if_route6(unsigned char cmd, const struc
 #ifdef RTF_CLONING
 		rtm.hdr.rtm_flags |= RTF_CLONING;
 #endif
+#ifdef RTF_CONNECTED
+		rtm.hdr.rtm_flags |= RTF_CONNECTED;
+#endif
 #ifdef RTP_CONNECTED
 		rtm.hdr.rtm_priority = RTP_CONNECTED;
 #endif
 	} else
 		rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
 
-	if (cmd == RTM_ADD)
+	if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
 		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
-	if (cmd == RTM_ADD && !(rtm.hdr.rtm_flags & RTF_REJECT))
-		rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
+	    	if (!(rtm.hdr.rtm_flags & RTF_REJECT))
+			rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
+	}
 
 	ADDADDR(&rt->dest);
 	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
@@ -1006,9 +1091,7 @@ if_route6(unsigned char cmd, const struc
 	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
 		ADDADDR(&rt->net);
 
-	if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
-	    (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)))
-	{
+	if (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA)) {
 		rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
 		if (rtm.hdr.rtm_addrs & RTA_IFP) {
 			if_linkaddr(&su.sdl, rt->iface);
@@ -1018,7 +1101,7 @@ if_route6(unsigned char cmd, const struc
 		if (rtm.hdr.rtm_addrs & RTA_IFA) {
 			const struct ipv6_addr *lla;
 
-			lla = ipv6_linklocal(rt->iface);
+			lla = ipv6_linklocal(UNCONST(rt->iface));
 			if (lla == NULL) /* unlikely */
 					return -1;
 			ADDADDRS(&lla->addr, rt->iface->index);
@@ -1069,7 +1152,7 @@ if_initrt6(struct interface *ifp)
 
 	end = buf + needed;
 	for (p = buf; p < end; p += rtm->rtm_msglen) {
-		rtm = (struct rt_msghdr *)(void *)p;
+		rtm = (void *)p;
 		if (if_copyrt6(ifp->ctx, &rt, rtm) == 0)
 			ipv6_handlert(ifp->ctx, RTM_ADD, &rt);
 	}
@@ -1082,13 +1165,15 @@ if_addrflags6(const struct in6_addr *add
 {
 	int flags;
 	struct in6_ifreq ifr6;
+	struct priv *priv;
 
 	memset(&ifr6, 0, sizeof(ifr6));
 	strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
 	ifr6.ifr_addr.sin6_family = AF_INET6;
 	ifr6.ifr_addr.sin6_addr = *addr;
 	ifa_scope(&ifr6.ifr_addr, ifp->index);
-	if (ioctl(ifp->ctx->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
+	priv = (struct priv *)ifp->ctx->priv;
+	if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
 		flags = ifr6.ifr_ifru.ifru_flags6;
 	else
 		flags = -1;
@@ -1101,14 +1186,15 @@ if_getlifetime6(struct ipv6_addr *ia)
 	struct in6_ifreq ifr6;
 	time_t t;
 	struct in6_addrlifetime *lifetime;
+	struct priv *priv;
 
 	memset(&ifr6, 0, sizeof(ifr6));
 	strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
 	ifr6.ifr_addr.sin6_family = AF_INET6;
 	ifr6.ifr_addr.sin6_addr = ia->addr;
 	ifa_scope(&ifr6.ifr_addr, ia->iface->index);
-	if (ioctl(ia->iface->ctx->pf_inet6_fd,
-	    SIOCGIFALIFETIME_IN6, &ifr6) == -1)
+	priv = (struct priv *)ia->iface->ctx->priv;
+	if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1)
 		return -1;
 
 	t = time(NULL);
@@ -1161,7 +1247,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
 		return -1;
 	e = msg + bytes;
 	for (p = msg; p < e; p += rtm->rtm_msglen) {
-		rtm = (struct rt_msghdr *)(void *)p;
+		rtm = (void *)p;
 		if (rtm->rtm_type == RTM_MISS)
 			continue;
 		/* Ignore messages generated by us */
@@ -1185,7 +1271,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
 		switch(rtm->rtm_type) {
 #ifdef RTM_IFANNOUNCE
 		case RTM_IFANNOUNCE:
-			ifan = (struct if_announcemsghdr *)(void *)p;
+			ifan = (void *)p;
 			switch(ifan->ifan_what) {
 			case IFAN_ARRIVAL:
 				dhcpcd_handleinterface(ctx, 1,
@@ -1199,7 +1285,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
 			break;
 #endif
 		case RTM_IFINFO:
-			ifm = (struct if_msghdr *)(void *)p;
+			ifm = (void *)p;
 			ifp = if_findindex(ctx->ifaces, ifm->ifm_index);
 			if (ifp == NULL)
 				break;
@@ -1227,13 +1313,13 @@ if_managelink(struct dhcpcd_ctx *ctx)
 		case RTM_ADD:
 		case RTM_CHANGE:
 		case RTM_DELETE:
-			cp = (char *)(void *)(rtm + 1);
-			sa = (struct sockaddr *)(void *)cp;
+			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);
+					ipv4_handlert(ctx, rtm->rtm_type,&rt,0);
 				break;
 #endif
 #ifdef INET6
@@ -1276,11 +1362,11 @@ if_managelink(struct dhcpcd_ctx *ctx)
 #endif
 		case RTM_DELADDR:	/* FALLTHROUGH */
 		case RTM_NEWADDR:
-			ifam = (struct ifa_msghdr *)(void *)p;
+			ifam = (void *)p;
 			ifp = if_findindex(ctx->ifaces, ifam->ifam_index);
 			if (ifp == NULL)
 				break;
-			cp = (char *)(void *)(ifam + 1);
+			cp = (void *)(ifam + 1);
 			get_addrs(ifam->ifam_addrs, cp, rti_info);
 			if (rti_info[RTAX_IFA] == NULL)
 				break;
@@ -1318,12 +1404,10 @@ if_managelink(struct dhcpcd_ctx *ctx)
 #endif
 #ifdef INET6
 			case AF_INET6:
-				sin6 = (struct sockaddr_in6*)(void *)
-				    rti_info[RTAX_IFA];
+				sin6 = (void *)rti_info[RTAX_IFA];
 				ia6 = sin6->sin6_addr;
 				DESCOPE(&ia6);
-				sin6 = (struct sockaddr_in6*)(void *)
-				    rti_info[RTAX_NETMASK];
+				sin6 = (void *)rti_info[RTAX_NETMASK];
 				net6 = sin6->sin6_addr;
 				DESCOPE(&net6);
 				if (rtm->rtm_type == RTM_NEWADDR) {
@@ -1691,7 +1775,9 @@ _if_checkipv6(int s, struct dhcpcd_ctx *
 int
 if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
 {
+	struct priv *priv;
 
-	return _if_checkipv6(ctx->pf_inet6_fd, ctx, ifp, own);
+	priv = (struct priv *)ctx->priv;
+	return _if_checkipv6(priv->pf_inet6_fd, ctx, ifp, own);
 }
 #endif
Index: src/external/bsd/dhcpcd/dist/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.27 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.28
--- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.27	Thu Jan  7 20:09:43 2016
+++ src/external/bsd/dhcpcd/dist/ipv6nd.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6nd.c,v 1.27 2016/01/07 20:09:43 roy Exp $");
+ __RCSID("$NetBSD: ipv6nd.c,v 1.28 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -192,8 +192,9 @@ ipv6nd_open(struct dhcpcd_ctx *dctx)
 	ctx = dctx->ipv6;
 	if (ctx->nd_fd != -1)
 		return ctx->nd_fd;
-	ctx->nd_fd = xsocket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
-	    O_NONBLOCK|O_CLOEXEC);
+#define SOCK_FLAGS	SOCK_CLOEXEC | SOCK_NONBLOCK
+	ctx->nd_fd = xsocket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, SOCK_FLAGS);
+#undef SOCK_FLAGS
 	if (ctx->nd_fd == -1)
 		return -1;
 
@@ -220,8 +221,7 @@ ipv6nd_open(struct dhcpcd_ctx *dctx)
 	    &filt, sizeof(filt)) == -1)
 		goto eexit;
 
-	eloop_event_add(dctx->eloop, ctx->nd_fd,
-	    ipv6nd_handledata, dctx, NULL, NULL);
+	eloop_event_add(dctx->eloop, ctx->nd_fd,  ipv6nd_handledata, dctx);
 	return ctx->nd_fd;
 
 eexit:
@@ -246,7 +246,7 @@ ipv6nd_makersprobe(struct interface *ifp
 	state->rs = calloc(1, state->rslen);
 	if (state->rs == NULL)
 		return -1;
-	rs = (struct nd_router_solicit *)(void *)state->rs;
+	rs = (void *)state->rs;
 	rs->nd_rs_type = ND_ROUTER_SOLICIT;
 	rs->nd_rs_code = 0;
 	rs->nd_rs_cksum = 0;
@@ -554,7 +554,7 @@ ipv6nd_scriptrun(struct ra *rap)
 		{
 			hasaddress = 1;
 			if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
-			    ipv6_iffindaddr(ap->iface, &ap->addr))
+			    ipv6_iffindaddr(ap->iface, &ap->addr, IN6_IFF_TENTATIVE))
 				ap->flags |= IPV6_AF_DADCOMPLETED;
 			if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
 				logger(ap->iface->ctx, LOG_DEBUG,
@@ -715,24 +715,6 @@ try_script:
 	}
 }
 
-static int
-ipv6nd_has_public_addr(const struct interface *ifp)
-{
-	const struct ra *rap;
-	const struct ipv6_addr *ia;
-
-	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
-		if (rap->iface == ifp) {
-			TAILQ_FOREACH(ia, &rap->addrs, next) {
-				if (ia->flags & IPV6_AF_AUTOCONF &&
-				    ipv6_publicaddr(ia))
-					return 1;
-			}
-		}
-	}
-	return 0;
-}
-
 static void
 ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
     struct icmp6_hdr *icp, size_t len, int hoplimit)
@@ -801,7 +783,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		return;
 	}
 
-	if (ipv6_iffindaddr(ifp, &ctx->from.sin6_addr)) {
+	if (ipv6_iffindaddr(ifp, &ctx->from.sin6_addr, IN6_IFF_TENTATIVE)) {
 		logger(ifp->ctx, LOG_DEBUG,
 		    "%s: ignoring RA from ourself %s", ifp->name, ctx->sfrom);
 		return;
@@ -823,15 +805,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		if (rap) {
 			free(rap->data);
 			rap->data_len = 0;
-			rap->no_public_warned = 0;
 		}
 		new_data = 1;
 	} else
 		new_data = 0;
-	if (new_data || ifp->options->options & DHCPCD_DEBUG)
-		logger(ifp->ctx, LOG_INFO, "%s: Router Advertisement from %s",
-		    ifp->name, ctx->sfrom);
-
 	if (rap == NULL) {
 		rap = calloc(1, sizeof(*rap));
 		if (rap == NULL) {
@@ -857,6 +834,14 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		rap->data_len = len;
 	}
 
+	/* We could change the debug level based on new_data, but some
+	 * routers like to decrease the advertised valid and preferred times
+	 * in accordance with the own prefix times which would result in too
+	 * much needless log spam. */
+	logger(ifp->ctx, new_rap ? LOG_INFO : LOG_DEBUG,
+	    "%s: Router Advertisement from %s",
+	    ifp->name, ctx->sfrom);
+
 	clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
 	rap->flags = nd_ra->nd_ra_flags_reserved;
 	rap->lifetime = ntohs(nd_ra->nd_ra_router_lifetime);
@@ -927,7 +912,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 
 		switch (ndo->nd_opt_type) {
 		case ND_OPT_PREFIX_INFORMATION:
-			pi = (struct nd_opt_prefix_info *)(void *)ndo;
+			pi = (void *)ndo;
 			if (pi->nd_opt_pi_len != 4) {
 				logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
 				    "%s: invalid option len for prefix",
@@ -1010,7 +995,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 				 * temporary address also exists then
 				 * extend the existing one rather than
 				 * create a new one */
-				if (ipv6_iffindaddr(ifp, &ap->addr) &&
+				if (ipv6_iffindaddr(ifp, &ap->addr,
+				    IN6_IFF_NOTUSEABLE) &&
 				    ipv6_settemptime(ap, 0))
 					new_ap = 0;
 				else
@@ -1053,7 +1039,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 			break;
 
 		case ND_OPT_MTU:
-			mtu = (struct nd_opt_mtu *)(void *)p;
+			mtu = (void *)p;
 			mtuv = ntohl(mtu->nd_opt_mtu_mtu);
 			if (mtuv < IPV6_MMTU) {
 				logger(ifp->ctx, LOG_ERR, "%s: invalid MTU %d",
@@ -1064,7 +1050,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 			break;
 
 		case ND_OPT_RDNSS:
-			rdnss = (struct nd_opt_rdnss *)(void *)p;
+			rdnss = (void *)p;
 			if (rdnss->nd_opt_rdnss_lifetime &&
 			    rdnss->nd_opt_rdnss_len > 1)
 				rap->hasdns = 1;
@@ -1095,19 +1081,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 	if (new_rap)
 		add_router(ifp->ctx->ipv6, rap);
 
-	if (!ipv6nd_has_public_addr(rap->iface) &&
-	    !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
-	    (!(rap->flags & ND_RA_FLAG_MANAGED) ||
-	    !dhcp6_has_public_addr(rap->iface)))
-	{
-		logger(rap->iface->ctx,
-		    rap->no_public_warned ? LOG_DEBUG : LOG_WARNING,
-		    "%s: ignoring RA from %s"
-		    " (no public prefix, no managed address)",
-		    rap->iface->name, rap->sfrom);
-		rap->no_public_warned = 1;
-		goto handle_flag;
-	}
 	if (ifp->ctx->options & DHCPCD_TEST) {
 		script_runreason(ifp, "TEST");
 		goto handle_flag;
@@ -1155,34 +1128,6 @@ nodhcp6:
 	ipv6nd_expirera(ifp);
 }
 
-/* Run RA's we ignored becuase they had no public addresses
- * This should only be called when DHCPv6 applies a public address */
-void
-ipv6nd_runignoredra(struct interface *ifp)
-{
-	struct ra *rap;
-
-	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
-		if (rap->iface == ifp &&
-		    !rap->expired &&
-		    rap->no_public_warned)
-		{
-			rap->no_public_warned = 0;
-			logger(rap->iface->ctx, LOG_INFO,
-			    "%s: applying ignored RA from %s",
-			    rap->iface->name, rap->sfrom);
-			if (ifp->ctx->options & DHCPCD_TEST) {
-				script_runreason(ifp, "TEST");
-				continue;
-			}
-			if (ipv6nd_scriptrun(rap))
-				return;
-			eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-			eloop_timeout_delete(ifp->ctx->eloop, NULL, rap);
-		}
-	}
-}
-
 int
 ipv6nd_hasra(const struct interface *ifp)
 {

Index: src/external/bsd/dhcpcd/dist/if-options.c
diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.30 src/external/bsd/dhcpcd/dist/if-options.c:1.31
--- src/external/bsd/dhcpcd/dist/if-options.c:1.30	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/if-options.c	Sun Apr 10 21:00:53 2016
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-options.c,v 1.30 2016/01/20 19:42:33 roy Exp $");
+ __RCSID("$NetBSD: if-options.c,v 1.31 2016/04/10 21:00:53 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -99,7 +99,6 @@
 #define O_IPV6RA_AUTOCONF	O_BASE + 38
 #define O_IPV6RA_NOAUTOCONF	O_BASE + 39
 #define O_REJECT		O_BASE + 40
-#define O_IPV6RA_ACCEPT_NOPUBLIC	O_BASE + 41
 #define O_BOOTP			O_BASE + 42
 #define O_DEFINEND		O_BASE + 43
 #define O_NODELAY		O_BASE + 44
@@ -169,7 +168,6 @@ const struct option cf_options[] = {
 	{"ipv6ra_fork",     no_argument,       NULL, O_IPV6RA_FORK},
 	{"ipv6ra_own",      no_argument,       NULL, O_IPV6RA_OWN},
 	{"ipv6ra_own_default", no_argument,    NULL, O_IPV6RA_OWN_D},
-	{"ipv6ra_accept_nopublic", no_argument, NULL, O_IPV6RA_ACCEPT_NOPUBLIC},
 	{"ipv4",            no_argument,       NULL, O_IPV4},
 	{"noipv4",          no_argument,       NULL, O_NOIPV4},
 	{"ipv6",            no_argument,       NULL, O_IPV6},
@@ -1113,6 +1111,24 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				logger(ctx, LOG_ERR, "invalid MTU %s", p);
 				return -1;
 			}
+		} else if (strncmp(arg, "ip6_address=", strlen("ip6_address=")) == 0) {
+			np = strchr(p, '/');
+			if (np)
+				*np++ = '\0';
+			if (inet_pton(AF_INET6, p, &ifo->req_addr6) == 1) {
+				if (np) {
+					ifo->req_prefix_len = (uint8_t)strtou(np,
+					    NULL, 0, 0, 128, &e);
+					if (e) {
+						logger(ctx, LOG_ERR,
+						    "%s: failed to "
+						    "convert prefix len",
+						    ifname);
+						return -1;
+					}
+				} else
+					ifo->req_prefix_len = 128;
+			}
 		} else {
 			dl = 0;
 			if (ifo->config != NULL) {
@@ -1140,6 +1156,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			}
 			nconf = realloc(ifo->config, sizeof(char *) * (dl + 2));
 			if (nconf == NULL) {
+				free(p);
 				logger(ctx, LOG_ERR, "%s: %m", __func__);
 				return -1;
 			}
@@ -1274,9 +1291,6 @@ parse_option(struct dhcpcd_ctx *ctx, con
 	case O_IPV6RA_OWN_D:
 		ifo->options |= DHCPCD_IPV6RA_OWN_DEFAULT;
 		break;
-	case O_IPV6RA_ACCEPT_NOPUBLIC:
-		ifo->options |= DHCPCD_IPV6RA_ACCEPT_NOPUBLIC;
-		break;
 	case O_IPV6RA_AUTOCONF:
 		ifo->options |= DHCPCD_IPV6RA_AUTOCONF;
 		break;
@@ -1326,7 +1340,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		ia = NULL;
 		for (sl = 0; sl < ifo->ia_len; sl++) {
 			if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
-			    (ifo->ia[sl].iaid_set &&
+			    (arg != NULL && ifo->ia[sl].iaid_set &&
 			    ifo->ia[sl].iaid[0] == iaid[0] &&
 			    ifo->ia[sl].iaid[1] == iaid[1] &&
 			    ifo->ia[sl].iaid[2] == iaid[2] &&
@@ -1374,15 +1388,15 @@ parse_option(struct dhcpcd_ctx *ctx, con
 					memset(&ia->addr, 0, sizeof(ia->addr));
 				}
 				if (p && ia->ia_type == D6_OPTION_IA_PD) {
-					i = (int)strtoi(p, NULL, 0, 8, 120, &e);
+					ia->prefix_len = (uint8_t)strtou(p,
+					    NULL, 0, 8, 120, &e);
 					if (e) {
 						logger(ctx, LOG_ERR,
 						    "%s: failed to convert"
 						    " prefix len",
 						    p);
 						ia->prefix_len = 0;
-					} else
-						ia->prefix_len = (uint8_t)i;
+					}
 				}
 			}
 			ia->sla_max = 0;
@@ -1411,18 +1425,19 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			if (strlcpy(sla->ifname, p,
 			    sizeof(sla->ifname)) >= sizeof(sla->ifname))
 			{
-				logger(ctx, LOG_ERR, "%s: interface name too long",
-				    arg);
+				logger(ctx, LOG_ERR,
+				    "%s: interface name too long", arg);
 				goto err_sla;
 			}
+			sla->sla_set = 0;
+			sla->prefix_len = 0;
+			sla->suffix = 1;
 			p = np;
 			if (p) {
 				np = strchr(p, '/');
 				if (np)
 					*np++ = '\0';
-				if (*p == '\0')
-					sla->sla_set = 0;
-				else {
+				if (*p != '\0') {
 					sla->sla = (uint32_t)strtou(p, NULL,
 					    0, 0, UINT32_MAX, &e);
 					sla->sla_set = 1;
@@ -1433,20 +1448,40 @@ parse_option(struct dhcpcd_ctx *ctx, con
 						goto err_sla;
 					}
 				}
-				if (np) {
-					sla->prefix_len = (uint8_t)strtoi(np,
-					    NULL, 0, 0, 128, &e);
+				p = np;
+			}
+			if (p) {
+				np = strchr(p, '/');
+				if (np)
+					*np++ = '\0';
+				if (*p != '\0') {
+					sla->prefix_len = (uint8_t)strtou(p,
+				    NULL, 0, 0, 120, &e);
 					if (e) {
-						logger(ctx, LOG_ERR, "%s: failed to "
+						logger(ctx, LOG_ERR,
+						    "%s: failed to "
 						    "convert prefix len",
 						    ifname);
 						goto err_sla;
 					}
-				} else
-					sla->prefix_len = 0;
-			} else {
-				sla->sla_set = 0;
-				sla->prefix_len = 0;
+				}
+				p = np;
+			}
+			if (p) {
+				np = strchr(p, '/');
+				if (np)
+					*np = '\0';
+				if (*p != '\0') {
+					sla->suffix = (uint64_t)strtou(p, NULL,
+					    0, 0, UINT64_MAX, &e);
+					if (e) {
+						logger(ctx, LOG_ERR,
+						    "%s: failed to "
+						    "convert suffix",
+						    ifname);
+						goto err_sla;
+					}
+				}
 			}
 			/* Sanity check */
 			for (sl = 0; sl < ia->sla_len - 1; sl++) {
@@ -1468,7 +1503,9 @@ parse_option(struct dhcpcd_ctx *ctx, con
 					    sla->ifname);
 					goto err_sla;
 				}
-				if (slap->sla == 0 || sla->sla == 0) {
+				if (slap->sla_set &&
+				    (slap->sla == 0 || sla->sla == 0))
+				{
 					logger(ctx, LOG_ERR, "%s: cannot"
 					    " assign multiple prefixes"
 					    " with a SLA of 0",
@@ -2105,8 +2142,9 @@ static char *
 get_line(char ** __restrict buf, size_t * __restrict buflen,
     FILE * __restrict fp)
 {
-	char *p;
+	char *p, *c;
 	ssize_t bytes;
+	int quoted;
 
 	do {
 		bytes = getline(buf, buflen, fp);
@@ -2117,10 +2155,51 @@ get_line(char ** __restrict buf, size_t 
 	} while (*p == '\0' || *p == '\n' || *p == '#' || *p == ';');
 	if ((*buf)[--bytes] == '\n')
 		(*buf)[bytes] = '\0';
+
+	/* Strip embedded comments unless in a quoted string or escaped */
+	quoted = 0;
+	for (c = p; *c != '\0'; c++) {
+		if (*c == '\\') {
+			c++; /* escaped */
+			continue;
+		}
+		if (*c == '"')
+			quoted = !quoted;
+		else if (*c == '#' && !quoted) {
+			*c = '\0';
+			break;
+		}
+	}
 	return p;
 }
 
 struct if_options *
+default_config(struct dhcpcd_ctx *ctx)
+{
+	struct if_options *ifo;
+
+	/* Seed our default options */
+	if ((ifo = calloc(1, sizeof(*ifo))) == NULL) {
+		logger(ctx, LOG_ERR, "%s: %m", __func__);
+		return NULL;
+	}
+	ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
+	ifo->timeout = DEFAULT_TIMEOUT;
+	ifo->reboot = DEFAULT_REBOOT;
+	ifo->metric = -1;
+	ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
+	TAILQ_INIT(&ifo->auth.tokens);
+
+	/* Inherit some global defaults */
+	if (ctx->options & DHCPCD_PERSISTENT)
+		ifo->options |= DHCPCD_PERSISTENT;
+	if (ctx->options & DHCPCD_SLAACPRIVATE)
+		ifo->options |= DHCPCD_SLAACPRIVATE;
+
+	return ifo;
+}
+
+struct if_options *
 read_config(struct dhcpcd_ctx *ctx,
     const char *ifname, const char *ssid, const char *profile)
 {
@@ -2142,13 +2221,9 @@ read_config(struct dhcpcd_ctx *ctx,
 	struct dhcp_opt *ldop, *edop;
 
 	/* Seed our default options */
-	ifo = calloc(1, sizeof(*ifo));
-	if (ifo == NULL) {
-		logger(ctx, LOG_ERR, "%s: %m", __func__);
+	if ((ifo = default_config(ctx)) == NULL)
 		return NULL;
-	}
-	ifo->options |= DHCPCD_DAEMONISE | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
-	ifo->options |= DHCPCD_IF_UP;
+	ifo->options |= DHCPCD_DAEMONISE;
 #ifdef PLUGIN_DEV
 	ifo->options |= DHCPCD_DEV;
 #endif
@@ -2161,11 +2236,6 @@ read_config(struct dhcpcd_ctx *ctx,
 	ifo->options |= DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS;
 	ifo->options |= DHCPCD_DHCP6;
 #endif
-	ifo->timeout = DEFAULT_TIMEOUT;
-	ifo->reboot = DEFAULT_REBOOT;
-	ifo->metric = -1;
-	ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
-	TAILQ_INIT(&ifo->auth.tokens);
 
 	vlen = dhcp_vendor((char *)ifo->vendorclassid + 1,
 	            sizeof(ifo->vendorclassid) - 1);

Index: src/external/bsd/dhcpcd/dist/if-options.h
diff -u src/external/bsd/dhcpcd/dist/if-options.h:1.17 src/external/bsd/dhcpcd/dist/if-options.h:1.18
--- src/external/bsd/dhcpcd/dist/if-options.h:1.17	Wed Jan 20 19:42:33 2016
+++ src/external/bsd/dhcpcd/dist/if-options.h	Sun Apr 10 21:00:53 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if-options.h,v 1.17 2016/01/20 19:42:33 roy Exp $ */
+/* $NetBSD: if-options.h,v 1.18 2016/04/10 21:00:53 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -112,7 +112,7 @@
 #define DHCPCD_RTM_PPID			(1ULL << 53)
 #define DHCPCD_IPV6RA_AUTOCONF		(1ULL << 54)
 #define DHCPCD_ROUTER_HOST_ROUTE_WARNED	(1ULL << 55)
-#define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC	(1ULL << 56)
+// unassigned	(1ULL << 56)
 #define DHCPCD_BOOTP			(1ULL << 57)
 #define DHCPCD_INITIAL_DELAY		(1ULL << 58)
 #define DHCPCD_PRINT_PIDFILE		(1ULL << 59)
@@ -131,6 +131,7 @@ struct if_sla {
 	char ifname[IF_NAMESIZE];
 	uint32_t sla;
 	uint8_t prefix_len;
+	uint64_t suffix;
 	int8_t sla_set;
 };
 
@@ -177,6 +178,8 @@ struct if_options {
 	struct in_addr req_addr;
 	struct in_addr req_mask;
 	struct rt_head *routes;
+	struct in6_addr req_addr6;
+	uint8_t req_prefix_len;
 	unsigned int mtu;
 	char **config;
 
@@ -216,6 +219,7 @@ struct if_options {
 	struct auth auth;
 };
 
+struct if_options *default_config(struct dhcpcd_ctx *);
 struct if_options *read_config(struct dhcpcd_ctx *,
     const char *, const char *, const char *);
 int add_options(struct dhcpcd_ctx *, const char *,

Index: src/external/bsd/dhcpcd/dist/ipv4.c
diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.20 src/external/bsd/dhcpcd/dist/ipv4.c:1.21
--- src/external/bsd/dhcpcd/dist/ipv4.c:1.20	Mon Feb  1 16:47:00 2016
+++ src/external/bsd/dhcpcd/dist/ipv4.c	Sun Apr 10 21:00:53 2016
@@ -1,9 +1,9 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4.c,v 1.20 2016/02/01 16:47:00 christos Exp $");
+ __RCSID("$NetBSD: ipv4.c,v 1.21 2016/04/10 21:00:53 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
@@ -132,8 +132,8 @@ ipv4_iffindaddr(struct interface *ifp,
 	return NULL;
 }
 
-static struct ipv4_addr *
-ipv4_iffindmaskaddr(struct interface *ifp, const struct in_addr *addr)
+struct ipv4_addr *
+ipv4_iffindlladdr(struct interface *ifp)
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
@@ -141,24 +141,24 @@ 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 (IN_LINKLOCAL(htonl(ap->addr.s_addr)))
 				return ap;
 		}
 	}
 	return NULL;
 }
 
-struct ipv4_addr *
-ipv4_iffindlladdr(struct interface *ifp)
+static struct ipv4_addr *
+ipv4_iffindmaskaddr(struct interface *ifp, const struct in_addr *addr)
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
 
 	state = IPV4_STATE(ifp);
 	if (state) {
-		TAILQ_FOREACH(ap, &state->addrs, next) {
-			if (IN_LINKLOCAL(htonl(ap->addr.s_addr)))
+		TAILQ_FOREACH (ap, &state->addrs, next) {
+			if ((ap->addr.s_addr & ap->net.s_addr) ==
+			    (addr->s_addr & ap->net.s_addr))
 				return ap;
 		}
 	}
@@ -400,7 +400,7 @@ ipv4_findrt(struct dhcpcd_ctx *ctx, cons
 	TAILQ_FOREACH(r, ctx->ipv4_kroutes, next) {
 		if (rt->dest.s_addr == r->dest.s_addr &&
 #ifdef HAVE_ROUTE_METRIC
-		    rt->iface == r->iface &&
+		    (rt->iface == NULL || rt->iface == r->iface) &&
 		    (!flags || rt->metric == r->metric) &&
 #else
 		    (!flags || rt->iface == r->iface) &&
@@ -425,7 +425,7 @@ ipv4_freerts(struct rt_head *routes)
 /* If something other than dhcpcd removes a route,
  * we need to remove it from our internal table. */
 int
-ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, struct rt *rt)
+ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, const struct rt *rt, int flags)
 {
 	struct rt *f;
 
@@ -456,7 +456,8 @@ ipv4_handlert(struct dhcpcd_ctx *ctx, in
 		}
 		break;
 	}
-	return 0;
+
+	return flags ? 0 : ipv4ll_handlert(ctx, cmd, rt);
 }
 
 #define n_route(a)	 nc_route(NULL, a)
@@ -872,15 +873,21 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
 		ipv4_freeroutes(dnr);
 	}
 
-	/* If we don't manage a default route, grab one without a
+	/* If there is no default route, grab one without a
 	 * gateway for any IPv4LL enabled interfaces. */
 	if (!has_default) {
-		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-			if ((rt = ipv4ll_default_route(ifp)) != NULL) {
-				if (ipv4_doroute(rt, nrs) == 1)
-					TAILQ_INSERT_TAIL(nrs, rt, next);
-				else
-					free(rt);
+		struct rt def;
+
+		memset(&def, 0, sizeof(def));
+		if (ipv4_findrt(ctx, &def, 0) == NULL) {
+			TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+				if ((rt = ipv4ll_default_route(ifp)) != NULL) {
+					if (ipv4_doroute(rt, nrs) == 1) {
+						TAILQ_INSERT_TAIL(nrs, rt, next);
+						break;
+					} else
+						free(rt);
+				}
 			}
 		}
 	}

Reply via email to