Module Name:    src
Committed By:   roy
Date:           Sat May 16 23:31:32 UTC 2015

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

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/arp.c \
    src/external/bsd/dhcpcd/dist/common.c \
    src/external/bsd/dhcpcd/dist/dhcp6.c src/external/bsd/dhcpcd/dist/ipv6.h
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/arp.h
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/auth.h \
    src/external/bsd/dhcpcd/dist/common.h \
    src/external/bsd/dhcpcd/dist/config.h \
    src/external/bsd/dhcpcd/dist/control.c \
    src/external/bsd/dhcpcd/dist/dhcp-common.c \
    src/external/bsd/dhcpcd/dist/dhcp-common.h \
    src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c \
    src/external/bsd/dhcpcd/dist/eloop.h
cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/defs.h
cvs rdiff -u -r1.30 -r1.31 src/external/bsd/dhcpcd/dist/dhcp.c
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf \
    src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in
cvs rdiff -u -r1.41 -r1.42 src/external/bsd/dhcpcd/dist/dhcpcd.8.in
cvs rdiff -u -r1.24 -r1.25 src/external/bsd/dhcpcd/dist/dhcpcd.c
cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in \
    src/external/bsd/dhcpcd/dist/if-bsd.c
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/dhcpcd.h \
    src/external/bsd/dhcpcd/dist/eloop.c \
    src/external/bsd/dhcpcd/dist/if-options.h \
    src/external/bsd/dhcpcd/dist/ipv4.h
cvs rdiff -u -r1.23 -r1.24 src/external/bsd/dhcpcd/dist/if-options.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.c
cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/ipv4.c
cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/ipv6.c \
    src/external/bsd/dhcpcd/dist/ipv6nd.h
cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/script.c
cvs rdiff -u -r1.6 -r1.7 \
    src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf

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.12 src/external/bsd/dhcpcd/dist/arp.c:1.13
--- src/external/bsd/dhcpcd/dist/arp.c:1.12	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/arp.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: arp.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
+ __RCSID("$NetBSD: arp.c,v 1.13 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -297,17 +297,19 @@ arp_probe(struct arp_state *astate)
 	arp_probe1(astate);
 }
 
-static struct arp_state *
+struct arp_state *
 arp_find(struct interface *ifp, const struct in_addr *addr)
 {
 	struct arp_state *astate;
 	struct dhcp_state *state;
 
-	state = D_STATE(ifp);
+	if ((state = D_STATE(ifp)) == NULL)
+		goto out;
 	TAILQ_FOREACH(astate, &state->arp_states, next) {
 		if (astate->addr.s_addr == addr->s_addr && astate->iface == ifp)
 			return astate;
 	}
+out:
 	errno = ESRCH;
 	return NULL;
 }
@@ -380,7 +382,7 @@ arp_close(struct interface *ifp)
 		return;
 
 	if (state->arp_fd != -1) {
-		eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
+		eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
 		close(state->arp_fd);
 		state->arp_fd = -1;
 	}
Index: src/external/bsd/dhcpcd/dist/common.c
diff -u src/external/bsd/dhcpcd/dist/common.c:1.12 src/external/bsd/dhcpcd/dist/common.c:1.13
--- src/external/bsd/dhcpcd/dist/common.c:1.12	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/common.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: common.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
+ __RCSID("$NetBSD: common.c,v 1.13 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -28,11 +28,6 @@
  * SUCH DAMAGE.
  */
 
-#ifdef __APPLE__
-#  include <mach/mach_time.h>
-#  include <mach/kern_return.h>
-#endif
-
 #include <sys/param.h>
 #include <sys/time.h>
 
@@ -84,64 +79,6 @@ get_hostname(char *buf, size_t buflen, i
 	return buf;
 }
 
-/* Handy function to get the time.
- * We only care about time advancements, not the actual time itself
- * Which is why we use CLOCK_MONOTONIC, but it is not available on all
- * platforms.
- */
-#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
-int
-get_monotonic(struct timespec *ts)
-{
-
-#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
-	return clock_gettime(CLOCK_MONOTONIC, ts);
-#elif defined(__APPLE__)
-	/* We can use mach kernel functions here.
-	 * This is crap though - why can't they implement clock_gettime?*/
-	static struct mach_timebase_info info = { 0, 0 };
-	static double factor = 0.0;
-	uint64_t nano;
-	long rem;
-
-	if (!posix_clock_set) {
-		if (mach_timebase_info(&info) == KERN_SUCCESS) {
-			factor = (double)info.numer / (double)info.denom;
-			clock_monotonic = posix_clock_set = 1;
-		}
-	}
-	if (clock_monotonic) {
-		nano = mach_absolute_time();
-		if ((info.denom != 1 || info.numer != 1) && factor != 0.0)
-			nano *= factor;
-		ts->tv_sec = nano / NSEC_PER_SEC;
-		ts->tv_nsec = nano % NSEC_PER_SEC;
-		if (ts->tv_nsec < 0) {
-			ts->tv_sec--;
-			ts->tv_nsec += NSEC_PER_SEC;
-		}
-		return 0;
-	}
-#endif
-
-#if 0
-	/* Something above failed, so fall back to gettimeofday */
-	if (!posix_clock_set) {
-		logger(NULL, LOG_WARNING, NO_MONOTONIC);
-		posix_clock_set = 1;
-	}
-#endif
-	{
-		struct timeval tv;
-		if (gettimeofday(&tv, NULL) == 0) {
-			TIMEVAL_TO_TIMESPEC(&tv, ts);
-			return 0;
-		}
-	}
-
-	return -1;
-}
-
 #if USE_LOGFILE
 void
 logger_open(struct dhcpcd_ctx *ctx)
@@ -269,42 +206,64 @@ logger(struct dhcpcd_ctx *ctx, int pri, 
 
 ssize_t
 setvar(struct dhcpcd_ctx *ctx,
-    char ***e, const char *prefix, const char *var, const char *value)
+    char **e, const char *prefix, const char *var, const char *value)
 {
 	size_t len = strlen(var) + strlen(value) + 3;
 
 	if (prefix)
 		len += strlen(prefix) + 1;
-	**e = malloc(len);
-	if (**e == NULL) {
+	*e = malloc(len);
+	if (*e == NULL) {
 		logger(ctx, LOG_ERR, "%s: %m", __func__);
 		return -1;
 	}
 	if (prefix)
-		snprintf(**e, len, "%s_%s=%s", prefix, var, value);
+		snprintf(*e, len, "%s_%s=%s", prefix, var, value);
 	else
-		snprintf(**e, len, "%s=%s", var, value);
-	(*e)++;
+		snprintf(*e, len, "%s=%s", var, value);
 	return (ssize_t)len;
 }
 
 ssize_t
 setvard(struct dhcpcd_ctx *ctx,
-    char ***e, const char *prefix, const char *var, size_t value)
+    char **e, const char *prefix, const char *var, size_t value)
 {
+
 	char buffer[32];
 
 	snprintf(buffer, sizeof(buffer), "%zu", value);
 	return setvar(ctx, e, prefix, var, buffer);
 }
 
+ssize_t
+addvar(struct dhcpcd_ctx *ctx,
+    char ***e, const char *prefix, const char *var, const char *value)
+{
+	ssize_t len;
+
+	len = setvar(ctx, *e, prefix, var, value);
+	if (len != -1)
+		(*e)++;
+	return (ssize_t)len;
+}
+
+ssize_t
+addvard(struct dhcpcd_ctx *ctx,
+    char ***e, const char *prefix, const char *var, size_t value)
+{
+	char buffer[32];
+
+	snprintf(buffer, sizeof(buffer), "%zu", value);
+	return addvar(ctx, e, prefix, var, buffer);
+}
+
 
 time_t
 uptime(void)
 {
 	struct timespec tv;
 
-	if (get_monotonic(&tv) == -1)
+	if (clock_gettime(CLOCK_MONOTONIC, &tv) == -1)
 		return -1;
 	return tv.tv_sec;
 }
Index: src/external/bsd/dhcpcd/dist/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/dhcp6.c:1.12 src/external/bsd/dhcpcd/dist/dhcp6.c:1.13
--- src/external/bsd/dhcpcd/dist/dhcp6.c:1.12	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/dhcp6.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp6.c,v 1.12 2015/05/02 15:18:36 roy Exp $");
+ __RCSID("$NetBSD: dhcp6.c,v 1.13 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -1022,6 +1022,9 @@ dhcp6_sendmessage(struct interface *ifp,
 	const char *broad_uni;
 	const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT;
 
+	if (!callback && ifp->carrier == LINK_DOWN)
+		return 0;
+
 	memset(&dst, 0, sizeof(dst));
 	dst.sin6_family = AF_INET6;
 	dst.sin6_port = htons(DHCP6_SERVER_PORT);
@@ -1109,16 +1112,17 @@ dhcp6_sendmessage(struct interface *ifp,
 		}
 
 logsend:
-		logger(ifp->ctx, LOG_DEBUG,
-		    "%s: %s %s (xid 0x%02x%02x%02x),"
-		    " next in %0.1f seconds",
-		    ifp->name,
-		    broad_uni,
-		    dhcp6_get_op(state->send->type),
-		    state->send->xid[0],
-		    state->send->xid[1],
-		    state->send->xid[2],
-		    timespec_to_double(&state->RT));
+		if (ifp->carrier != LINK_DOWN)
+			logger(ifp->ctx, LOG_DEBUG,
+			    "%s: %s %s (xid 0x%02x%02x%02x),"
+			    " next in %0.1f seconds",
+			    ifp->name,
+			    broad_uni,
+			    dhcp6_get_op(state->send->type),
+			    state->send->xid[0],
+			    state->send->xid[1],
+			    state->send->xid[2],
+			    timespec_to_double(&state->RT));
 
 		/* Wait the initial delay */
 		if (state->IMD) {
@@ -1129,6 +1133,9 @@ logsend:
 		}
 	}
 
+	if (ifp->carrier == LINK_DOWN)
+		return 0;
+
 	/* Update the elapsed time */
 	dhcp6_updateelapsed(ifp, state->send, state->send_len);
 	if (ifp->options->auth.options & DHCPCD_AUTH_SEND &&
@@ -2109,7 +2116,7 @@ dhcp6_validatelease(struct interface *if
 	state->renew = state->rebind = state->expire = 0;
 	state->lowpl = ND6_INFINITE_LIFETIME;
 	if (!acquired) {
-		get_monotonic(&aq);
+		clock_gettime(CLOCK_MONOTONIC, &aq);
 		acquired = &aq;
 	}
 	nia = dhcp6_findia(ifp, m, len, sfrom, acquired);
@@ -2184,7 +2191,7 @@ dhcp6_readlease(struct interface *ifp, i
 	if ((now = time(NULL)) == -1)
 		goto ex;
 
-	get_monotonic(&acquired);
+	clock_gettime(CLOCK_MONOTONIC, &acquired);
 	acquired.tv_sec -= now - st.st_mtime;
 
 	/* Check to see if the lease is still valid */
@@ -2618,7 +2625,7 @@ dhcp6_handledata(void *arg)
 	if (bytes == -1) {
 		logger(dctx, LOG_ERR, "%s: recvmsg: %m", __func__);
 		close(ctx->dhcp_fd);
-		eloop_event_delete(dctx->eloop, ctx->dhcp_fd, 0);
+		eloop_event_delete(dctx->eloop, ctx->dhcp_fd);
 		ctx->dhcp_fd = -1;
 		return;
 	}
@@ -3394,7 +3401,7 @@ dhcp6_freedrop(struct interface *ifp, in
 	}
 	if (ifp == NULL && ctx->ipv6) {
 		if (ctx->ipv6->dhcp_fd != -1) {
-			eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd, 0);
+			eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd);
 			close(ctx->ipv6->dhcp_fd);
 			ctx->ipv6->dhcp_fd = -1;
 		}
Index: src/external/bsd/dhcpcd/dist/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/ipv6.h:1.12 src/external/bsd/dhcpcd/dist/ipv6.h:1.13
--- src/external/bsd/dhcpcd/dist/ipv6.h:1.12	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6.h,v 1.12 2015/05/02 15:18:37 roy Exp $ */
+/* $NetBSD: ipv6.h,v 1.13 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -33,6 +33,19 @@
 #include <sys/uio.h>
 #include <netinet/in.h>
 
+#ifndef __linux__
+#  ifndef __QNX__
+#    include <sys/endian.h>
+#  endif
+#  include <net/if.h>
+#  ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
+#    include <net/if_var.h>
+#  endif
+#  ifndef __sun
+#    include <netinet6/in6_var.h>
+#  endif
+#endif
+
 #include "config.h"
 #include "dhcpcd.h"
 
@@ -268,6 +281,7 @@ void ipv6_buildroutes(struct dhcpcd_ctx 
 #else
 #define ipv6_init(a) (NULL)
 #define ipv6_start(a) (-1)
+#define ipv6_iffindaddr(a, b) (NULL)
 #define ipv6_free_ll_callbacks(a) {}
 #define ipv6_free(a) {}
 #define ipv6_drop(a) {}

Index: src/external/bsd/dhcpcd/dist/arp.h
diff -u src/external/bsd/dhcpcd/dist/arp.h:1.9 src/external/bsd/dhcpcd/dist/arp.h:1.10
--- src/external/bsd/dhcpcd/dist/arp.h:1.9	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/arp.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: arp.h,v 1.9 2015/05/02 15:18:36 roy Exp $ */
+/* $NetBSD: arp.h,v 1.10 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -75,6 +75,7 @@ struct arp_state *arp_new(struct interfa
 void arp_cancel(struct arp_state *);
 void arp_free(struct arp_state *);
 void arp_free_but(struct arp_state *);
+struct arp_state *arp_find(struct interface *, const struct in_addr *);
 void arp_close(struct interface *);
 
 void arp_handleifa(int, struct interface *, const struct in_addr *, int);

Index: src/external/bsd/dhcpcd/dist/auth.h
diff -u src/external/bsd/dhcpcd/dist/auth.h:1.8 src/external/bsd/dhcpcd/dist/auth.h:1.9
--- src/external/bsd/dhcpcd/dist/auth.h:1.8	Fri Jan 30 09:47:05 2015
+++ src/external/bsd/dhcpcd/dist/auth.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: auth.h,v 1.8 2015/01/30 09:47:05 roy Exp $ */
+/* $NetBSD: auth.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -32,6 +32,10 @@
 
 #include "config.h"
 
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
+
 #define DHCPCD_AUTH_SEND	(1 << 0)
 #define DHCPCD_AUTH_REQUIRE	(1 << 1)
 #define DHCPCD_AUTH_RDM_COUNTER	(1 << 2)
Index: src/external/bsd/dhcpcd/dist/common.h
diff -u src/external/bsd/dhcpcd/dist/common.h:1.8 src/external/bsd/dhcpcd/dist/common.h:1.9
--- src/external/bsd/dhcpcd/dist/common.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/common.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: common.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: common.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -56,8 +56,8 @@
 #define USEC_PER_SEC		1000000L
 #define USEC_PER_NSEC		1000L
 #define NSEC_PER_SEC		1000000000L
+#define NSEC_PER_MSEC		1000000L
 #define MSEC_PER_SEC		1000L
-#define MSEC_PER_NSEC		1000000L
 
 /* Some systems don't define timespec macros */
 #ifndef timespecclear
@@ -97,12 +97,12 @@
 } while (0 /* CONSTCOND */);
 #define ts_to_ms(ms, tv) do {						     \
 	ms = (tv)->tv_sec * MSEC_PER_SEC;				     \
-	ms += (tv)->tv_nsec / MSEC_PER_NSEC;				     \
+	ms += (tv)->tv_nsec / NSEC_PER_MSEC;				     \
 } while (0 /* CONSTCOND */);
 #define ms_to_ts(tv, ms) do {						     \
 	(tv)->tv_sec = ms / MSEC_PER_SEC;				     \
 	(tv)->tv_nsec = (suseconds_t)(ms - ((tv)->tv_sec * MSEC_PER_SEC))    \
-	    * MSEC_PER_NSEC;						     \
+	    * NSEC_PER_MSEC;						     \
 } while (0 /* CONSTCOND */);
 
 #ifndef TIMEVAL_TO_TIMESPEC
@@ -140,6 +140,10 @@
 # endif
 #endif
 
+#ifndef __arraycount
+#define __arraycount(__x)       (sizeof(__x) / sizeof(__x[0]))
+#endif
+
 /* We don't really need this as our supported systems define __restrict
  * automatically for us, but it is here for completeness. */
 #ifndef __restrict
@@ -182,8 +186,12 @@ void logger_close(struct dhcpcd_ctx *);
 #endif
 
 ssize_t setvar(struct dhcpcd_ctx *,
-    char ***, const char *, const char *, const char *);
+    char **, const char *, const char *, const char *);
 ssize_t setvard(struct dhcpcd_ctx *,
+    char **, const char *, const char *, size_t);
+ssize_t addvar(struct dhcpcd_ctx *,
+    char ***, const char *, const char *, const char *);
+ssize_t addvard(struct dhcpcd_ctx *,
     char ***, const char *, const char *, size_t);
 time_t uptime(void);
 
Index: src/external/bsd/dhcpcd/dist/config.h
diff -u src/external/bsd/dhcpcd/dist/config.h:1.8 src/external/bsd/dhcpcd/dist/config.h:1.9
--- src/external/bsd/dhcpcd/dist/config.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/config.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: config.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: config.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
 
 /* netbsd */
 #define SYSCONFDIR	"/etc"
@@ -7,7 +7,7 @@
 #define LIBEXECDIR	"/libexec"
 #define DBDIR		"/var/db"
 #define RUNDIR		"/var/run"
-#include		<sys/queue.h>
+#define HAVE_SYS_QUEUE_H
 #define HAVE_SPAWN_H
 #define HAVE_KQUEUE
 #define HAVE_KQUEUE1
Index: src/external/bsd/dhcpcd/dist/control.c
diff -u src/external/bsd/dhcpcd/dist/control.c:1.8 src/external/bsd/dhcpcd/dist/control.c:1.9
--- src/external/bsd/dhcpcd/dist/control.c:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/control.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: control.c,v 1.8 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: control.c,v 1.9 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -95,7 +95,7 @@ control_delete(struct fd_list *fd)
 {
 
 	TAILQ_REMOVE(&fd->ctx->control_fds, fd, next);
-	eloop_event_delete(fd->ctx->eloop, fd->fd, 0);
+	eloop_event_delete(fd->ctx->eloop, fd->fd);
 	close(fd->fd);
 	control_queue_free(fd);
 	free(fd);
@@ -306,14 +306,14 @@ control_stop(struct dhcpcd_ctx *ctx)
 
 	if (ctx->control_fd == -1)
 		return 0;
-	eloop_event_delete(ctx->eloop, ctx->control_fd, 0);
+	eloop_event_delete(ctx->eloop, ctx->control_fd);
 	close(ctx->control_fd);
 	ctx->control_fd = -1;
 	if (unlink(ctx->control_sock) == -1)
 		retval = -1;
 
 	if (ctx->control_unpriv_fd != -1) {
-		eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd, 0);
+		eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd);
 		close(ctx->control_unpriv_fd);
 		ctx->control_unpriv_fd = -1;
 		if (unlink(UNPRIVSOCKET) == -1)
@@ -323,7 +323,7 @@ control_stop(struct dhcpcd_ctx *ctx)
 freeit:
 	while ((l = TAILQ_FIRST(&ctx->control_fds))) {
 		TAILQ_REMOVE(&ctx->control_fds, l, next);
-		eloop_event_delete(ctx->eloop, l->fd, 0);
+		eloop_event_delete(ctx->eloop, l->fd);
 		close(l->fd);
 		control_queue_free(l);
 		free(l);
@@ -402,7 +402,7 @@ control_writeone(void *arg)
 	TAILQ_INSERT_TAIL(&fd->free_queue, data, next);
 
 	if (TAILQ_FIRST(&fd->queue) == NULL)
-		eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
+		eloop_event_remove_writecb(fd->ctx->eloop, fd->fd);
 }
 
 int
Index: src/external/bsd/dhcpcd/dist/dhcp-common.c
diff -u src/external/bsd/dhcpcd/dist/dhcp-common.c:1.8 src/external/bsd/dhcpcd/dist/dhcp-common.c:1.9
--- src/external/bsd/dhcpcd/dist/dhcp-common.c:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcp-common.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp-common.c,v 1.8 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: dhcp-common.c,v 1.9 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -79,6 +79,8 @@ dhcp_print_option_encoding(const struct 
 		printf(" ip6address");
 	else if (opt->type & FLAG)
 		printf(" flag");
+	else if (opt->type & BITFLAG)
+		printf(" bitflags");
 	else if (opt->type & RFC3397)
 		printf(" domain");
 	else if (opt->type & DOMAIN)
@@ -89,9 +91,9 @@ dhcp_print_option_encoding(const struct 
 		printf(" raw");
 	else if (opt->type & BINHEX)
 		printf(" binhex");
-	else if (opt->type & STRING)	
+	else if (opt->type & STRING)
 		printf(" string");
-	if (opt->type & RFC3361)	
+	if (opt->type & RFC3361)
 		printf(" rfc3361");
 	if (opt->type & RFC3442)
 		printf(" rfc3442");
@@ -562,7 +564,7 @@ dhcp_optlen(const struct dhcp_opt *opt, 
 		sz = sizeof(uint32_t);
 	else if (opt->type & UINT16)
 		sz = sizeof(uint16_t);
-	else if (opt->type & UINT8)
+	else if (opt->type & (UINT8 | BITFLAG))
 		sz = sizeof(uint8_t);
 	else if (opt->type & ADDRIPV6)
 		sz = ADDR6SZ;
@@ -572,15 +574,9 @@ dhcp_optlen(const struct dhcp_opt *opt, 
 	return (dl < sz ? 0 : sz);
 }
 
-#ifdef INET6
-#define PO_IFNAME
-#else
-#define PO_IFNAME __unused
-#endif
-
-ssize_t
-print_option(char *s, size_t len, int type, const uint8_t *data, size_t dl,
-    PO_IFNAME const char *ifname)
+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)
 {
 	const uint8_t *e, *t;
 	uint16_t u16;
@@ -592,7 +588,11 @@ print_option(char *s, size_t len, int ty
 	size_t l;
 	char *tmp;
 
-	if (type & RFC3397) {
+#ifndef INET6
+	UNUSED(ifname);
+#endif
+
+	if (opt->type & RFC3397) {
 		sl = decode_rfc3397(NULL, 0, data, dl);
 		if (sl == 0 || sl == -1)
 			return sl;
@@ -601,32 +601,32 @@ print_option(char *s, size_t len, int ty
 		if (tmp == NULL)
 			return -1;
 		decode_rfc3397(tmp, l, data, dl);
-		sl = print_string(s, len, type, (uint8_t *)tmp, l - 1);
+		sl = print_string(s, len, opt->type, (uint8_t *)tmp, l - 1);
 		free(tmp);
 		return sl;
 	}
 
 #ifdef INET
-	if (type & RFC3361) {
+	if (opt->type & RFC3361) {
 		if ((tmp = decode_rfc3361(data, dl)) == NULL)
 			return -1;
 		l = strlen(tmp);
-		sl = print_string(s, len, type, (uint8_t *)tmp, l);
+		sl = print_string(s, len, opt->type, (uint8_t *)tmp, l);
 		free(tmp);
 		return sl;
 	}
 
-	if (type & RFC3442)
+	if (opt->type & RFC3442)
 		return decode_rfc3442(s, len, data, dl);
 
-	if (type & RFC5969)
+	if (opt->type & RFC5969)
 		return decode_rfc5969(s, len, data, dl);
 #endif
 
-	if (type & STRING)
-		return print_string(s, len, type, data, dl);
+	if (opt->type & STRING)
+		return print_string(s, len, opt->type, data, dl);
 
-	if (type & FLAG) {
+	if (opt->type & FLAG) {
 		if (s) {
 			*s++ = '1';
 			*s = '\0';
@@ -634,27 +634,50 @@ print_option(char *s, size_t len, int ty
 		return 1;
 	}
 
+	if (opt->type & BITFLAG) {
+		/* bitflags are a string, MSB first, such as ABCDEFGH
+		 * where A is 10000000, B is 01000000, etc. */
+		bytes = 0;
+		for (l = 0, sl = sizeof(opt->bitflags) - 1;
+		    l < sizeof(opt->bitflags);
+		    l++, sl--)
+		{
+			/* Don't print NULL or 0 flags */
+			if (opt->bitflags[l] != '\0' &&
+			    opt->bitflags[l] != '0' &&
+			    *data & (1 << sl))
+			{
+				if (s)
+					*s++ = opt->bitflags[l];
+				bytes++;
+			}
+		}
+		if (s)
+			*s = '\0';
+		return bytes;
+	}
+
 	if (!s) {
-		if (type & UINT8)
+		if (opt->type & UINT8)
 			l = 3;
-		else if (type & UINT16) {
+		else if (opt->type & UINT16) {
 			l = 5;
 			dl /= 2;
-		} else if (type & SINT16) {
+		} else if (opt->type & SINT16) {
 			l = 6;
 			dl /= 2;
-		} else if (type & UINT32) {
+		} else if (opt->type & UINT32) {
 			l = 10;
 			dl /= 4;
-		} else if (type & SINT32) {
+		} else if (opt->type & SINT32) {
 			l = 11;
 			dl /= 4;
-		} else if (type & ADDRIPV4) {
+		} else if (opt->type & ADDRIPV4) {
 			l = 16;
 			dl /= 4;
 		}
 #ifdef INET6
-		else if (type & ADDRIPV6) {
+		else if (opt->type & ADDRIPV6) {
 			e = data + dl;
 			l = 0;
 			while (data < e) {
@@ -683,36 +706,36 @@ print_option(char *s, size_t len, int ty
 			bytes++;
 			len--;
 		}
-		if (type & UINT8) {
+		if (opt->type & UINT8) {
 			sl = snprintf(s, len, "%u", *data);
 			data++;
-		} else if (type & UINT16) {
+		} else if (opt->type & UINT16) {
 			memcpy(&u16, data, sizeof(u16));
 			u16 = ntohs(u16);
 			sl = snprintf(s, len, "%u", u16);
 			data += sizeof(u16);
-		} else if (type & SINT16) {
+		} else if (opt->type & SINT16) {
 			memcpy(&u16, data, sizeof(u16));
 			s16 = (int16_t)ntohs(u16);
 			sl = snprintf(s, len, "%d", s16);
 			data += sizeof(u16);
-		} else if (type & UINT32) {
+		} else if (opt->type & UINT32) {
 			memcpy(&u32, data, sizeof(u32));
 			u32 = ntohl(u32);
 			sl = snprintf(s, len, "%u", u32);
 			data += sizeof(u32);
-		} else if (type & SINT32) {
+		} else if (opt->type & SINT32) {
 			memcpy(&u32, data, sizeof(u32));
 			s32 = (int32_t)ntohl(u32);
 			sl = snprintf(s, len, "%d", s32);
 			data += sizeof(u32);
-		} else if (type & ADDRIPV4) {
+		} else if (opt->type & ADDRIPV4) {
 			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 (type & ADDRIPV6) {
+		else if (opt->type & ADDRIPV6) {
 			ssize_t r;
 
 			r = ipv6_printaddr(s, len, data, ifname);
@@ -776,7 +799,7 @@ dhcp_envoption1(struct dhcpcd_ctx *ctx, 
 
 	if (opt->len && opt->len < ol)
 		ol = opt->len;
-	len = print_option(NULL, 0, opt->type, od, ol, ifname);
+	len = print_option(NULL, 0, opt, od, ol, ifname);
 	if (len < 0)
 		return 0;
 	if (vname)
@@ -798,7 +821,7 @@ dhcp_envoption1(struct dhcpcd_ctx *ctx, 
 	else
 		v += snprintf(val, e, "%s=", prefix);
 	if (len != 0)
-		print_option(v, (size_t)len + 1, opt->type, od, ol, ifname);
+		print_option(v, (size_t)len + 1, opt, od, ol, ifname);
 	return e;
 }
 
@@ -819,7 +842,8 @@ dhcp_envoption(struct dhcpcd_ctx *ctx, c
 
 	/* If no embedded or encapsulated options, it's easy */
 	if (opt->embopts_len == 0 && opt->encopts_len == 0) {
-		if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[0],
+		if (!(opt->type & RESERVED) &&
+		    dhcp_envoption1(ctx, env == NULL ? NULL : &env[0],
 		    prefix, opt, 1, od, ol, ifname))
 			return 1;
 		return 0;
@@ -860,10 +884,12 @@ dhcp_envoption(struct dhcpcd_ctx *ctx, c
 		/* Use the option prefix if the embedded option
 		 * name is different.
 		 * This avoids new_fqdn_fqdn which would be silly. */
-		ov = strcmp(opt->var, eopt->var);
-		if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[n],
-		    pfx, eopt, ov, od, e, ifname))
-			n++;
+		if (!(eopt->type & RESERVED)) {
+			ov = strcmp(opt->var, eopt->var);
+			if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[n],
+			    pfx, eopt, ov, od, e, ifname))
+				n++;
+		}
 		od += e;
 		ol -= e;
 	}
Index: src/external/bsd/dhcpcd/dist/dhcp-common.h
diff -u src/external/bsd/dhcpcd/dist/dhcp-common.h:1.8 src/external/bsd/dhcpcd/dist/dhcp-common.h:1.9
--- src/external/bsd/dhcpcd/dist/dhcp-common.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcp-common.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcp-common.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: dhcp-common.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -68,6 +68,8 @@
 #define RAW		(1 << 23)
 #define ESCSTRING	(1 << 24)
 #define ESCFILE		(1 << 25)
+#define BITFLAG		(1 << 26)
+#define RESERVED	(1 << 27)
 
 struct dhcp_opt {
 	uint32_t option; /* Also used for IANA Enterpise Number */
@@ -76,6 +78,7 @@ struct dhcp_opt {
 	char *var;
 
 	int index; /* Index counter for many instances of the same option */
+	char bitflags[8];
 
 	/* Embedded options.
 	 * The option code is irrelevant here. */
@@ -105,8 +108,6 @@ int make_option_mask(const struct dhcp_o
 size_t encode_rfc1035(const char *src, uint8_t *dst);
 ssize_t decode_rfc3397(char *, size_t, const uint8_t *, size_t);
 ssize_t print_string(char *, size_t, int, const uint8_t *, size_t);
-ssize_t print_option(char *, size_t, int, const uint8_t *, size_t,
-    const char *);
 int dhcp_set_leasefile(char *, size_t, int,
     const struct interface *, const char *);
 
Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.8 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.9
--- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.8 2015/03/26 10:26:37 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd-embedded.c,v 1.9 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * DO NOT EDIT!
@@ -122,7 +122,7 @@ const char * const dhcpcd_embedded_conf[
 "embed ascii scope_list",
 "define 80 norequest flag rapid_commit",
 "define 81 embed fqdn",
-"embed byte flags",
+"embed bitflags=0000NEOS flags",
 "embed byte rcode1",
 "embed byte rcode2",
 "embed domain fqdn",
@@ -201,6 +201,26 @@ const char * const dhcpcd_embedded_conf[
 "encap 0 string nvt",
 "encap 1 binhex vpn_id",
 "encap 255 flag global",
+"definend 1 binhex source_address",
+"definend 2 binhex target_address",
+"definend 3 index embed prefix_information",
+"embed byte length",
+"embed bitflags=LA flags",
+"embed uint32 vltime",
+"embed uint32 pltime",
+"embed uint32 reserved",
+"embed array ip6address prefix",
+"definend 5 embed mtu",
+"embed uint16 reserved",
+"embed uint32 mtu",
+"definend 25 index embed rdnss",
+"embed uint16 reserved",
+"embed uint32 lifetime",
+"embed array ip6address servers",
+"definend 31 index embed dnssl",
+"embed uint16 reserved",
+"embed uint32 lifetime",
+"embed domain search",
 "define6 1 binhex client_id",
 "define6 2 binhex server_id",
 "define6 3 norequest index embed ia_na",
@@ -272,7 +292,7 @@ const char * const dhcpcd_embedded_conf[
 "embed binhex remote_id",
 "define6 38 binhex subscriber_id",
 "define6 39 embed fqdn",
-"embed byte flags",
+"embed bitflags=00000NOS flags",
 "embed domain fqdn",
 "define6 40 array ip6address pana_agent",
 "define6 41 string posix_timezone",
Index: src/external/bsd/dhcpcd/dist/eloop.h
diff -u src/external/bsd/dhcpcd/dist/eloop.h:1.8 src/external/bsd/dhcpcd/dist/eloop.h:1.9
--- src/external/bsd/dhcpcd/dist/eloop.h:1.8	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/eloop.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: eloop.h,v 1.8 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: eloop.h,v 1.9 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -32,16 +32,79 @@
 
 #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)
+#define timespecisset(tsp)      ((tsp)->tv_sec || (tsp)->tv_nsec)
+#define timespeccmp(tsp, usp, cmp)                                      \
+        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
+            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
+            ((tsp)->tv_sec cmp (usp)->tv_sec))
+#define timespecadd(tsp, usp, vsp)                                      \
+        do {                                                            \
+                (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;          \
+                (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;       \
+                if ((vsp)->tv_nsec >= 1000000000L) {                    \
+                        (vsp)->tv_sec++;                                \
+                        (vsp)->tv_nsec -= 1000000000L;                  \
+                }                                                       \
+        } while (/* CONSTCOND */ 0)
+#define timespecsub(tsp, usp, vsp)                                      \
+        do {                                                            \
+                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
+                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
+                if ((vsp)->tv_nsec < 0) {                               \
+                        (vsp)->tv_sec--;                                \
+                        (vsp)->tv_nsec += 1000000000L;                  \
+                }                                                       \
+        } while (/* CONSTCOND */ 0)
+#endif
+
+/* eloop queues are really only for deleting timeouts registered
+ * for a function or object.
+ * The idea being that one interface as different timeouts for
+ * say DHCP and DHCPv6. */
 #ifndef ELOOP_QUEUE
   #define ELOOP_QUEUE 1
 #endif
 
-/* EXIT_FAILURE is a non zero value and EXIT_SUCCESS is zero.
- * To add a CONTINUE definition, simply do the opposite of EXIT_FAILURE. */
-#define ELOOP_CONTINUE	-EXIT_FAILURE
-
 struct eloop_event {
 	TAILQ_ENTRY(eloop_event) next;
 	int fd;
@@ -62,9 +125,7 @@ struct eloop_timeout {
 	int queue;
 };
 
-struct eloop_ctx {
-	struct dhcpcd_ctx *ctx;
-
+struct eloop {
 	size_t events_len;
 	TAILQ_HEAD (event_head, eloop_event) events;
 	struct event_head free_events;
@@ -74,6 +135,10 @@ struct eloop_ctx {
 
 	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;
@@ -86,33 +151,43 @@ struct eloop_ctx {
 	int exitcode;
 };
 
-#define eloop_timeout_add_tv(a, b, c, d) \
-    eloop_q_timeout_add_tv(a, ELOOP_QUEUE, b, c, d)
-#define eloop_timeout_add_sec(a, b, c, d) \
-    eloop_q_timeout_add_sec(a, ELOOP_QUEUE, b, c, d)
-#define eloop_timeout_delete(a, b, c) \
-    eloop_q_timeout_delete(a, ELOOP_QUEUE, b, c)
-
-int eloop_event_add(struct eloop_ctx *, int,
+int eloop_event_add(struct eloop *, int,
     void (*)(void *), void *,
     void (*)(void *), void *);
-void eloop_event_delete(struct eloop_ctx *, int, int);
-int eloop_q_timeout_add_sec(struct eloop_ctx *, int queue,
-    time_t, void (*)(void *), void *);
-int eloop_q_timeout_add_tv(struct eloop_ctx *, int queue,
+#define eloop_event_delete(eloop, fd) \
+    eloop_event_delete_write((eloop), (fd), 0)
+#define eloop_event_remove_writecb(eloop, fd) \
+    eloop_event_delete_write((eloop), (fd), 1)
+void eloop_event_delete_write(struct eloop *, int, int);
+
+#define eloop_timeout_add_tv(eloop, tv, cb, ctx) \
+    eloop_q_timeout_add_tv((eloop), ELOOP_QUEUE, (tv), (cb), (ctx))
+#define eloop_timeout_add_sec(eloop, tv, cb, ctx) \
+    eloop_q_timeout_add_sec((eloop), ELOOP_QUEUE, (tv), (cb), (ctx))
+#define eloop_timeout_add_msec(eloop, ms, cb, ctx) \
+    eloop_q_timeout_add_msec((eloop), ELOOP_QUEUE, (ms), (cb), (ctx))
+#define eloop_timeout_delete(eloop, cb, ctx) \
+    eloop_q_timeout_delete((eloop), ELOOP_QUEUE, (cb), (ctx))
+int eloop_q_timeout_add_tv(struct eloop *, int,
     const struct timespec *, void (*)(void *), void *);
-#if !defined(HAVE_KQUEUE)
-int eloop_timeout_add_now(struct eloop_ctx *, void (*)(void *), void *);
-#endif
-void eloop_q_timeout_delete(struct eloop_ctx *, int, void (*)(void *), void *);
-struct eloop_ctx * eloop_init(struct dhcpcd_ctx *);
+int eloop_q_timeout_add_sec(struct eloop *, int,
+    time_t, void (*)(void *), void *);
+int eloop_q_timeout_add_msec(struct eloop *, int,
+    long, void (*)(void *), void *);
+void eloop_q_timeout_delete(struct eloop *, int, void (*)(void *), void *);
+
+int eloop_signal_set_cb(struct eloop *, const int *, size_t,
+    void (*)(int, void *), void *);
+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_ctx *);
+int eloop_requeue(struct eloop *);
 #else
-#define eloop_requeue(a) (0)
+#define eloop_requeue(eloop) (0)
 #endif
-void eloop_free(struct eloop_ctx *);
-void eloop_exit(struct eloop_ctx *, int);
-int eloop_start(struct eloop_ctx *);
+void eloop_free(struct eloop *);
+void eloop_exit(struct eloop *, int);
+int eloop_start(struct eloop *, sigset_t *);
 
 #endif

Index: src/external/bsd/dhcpcd/dist/defs.h
diff -u src/external/bsd/dhcpcd/dist/defs.h:1.17 src/external/bsd/dhcpcd/dist/defs.h:1.18
--- src/external/bsd/dhcpcd/dist/defs.h:1.17	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/defs.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: defs.h,v 1.17 2015/05/02 15:18:36 roy Exp $ */
+/* $NetBSD: defs.h,v 1.18 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,7 +30,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"6.8.2"
+#define VERSION			"6.9.0"
 
 #ifndef CONFIG
 # define CONFIG			SYSCONFDIR "/" PACKAGE ".conf"

Index: src/external/bsd/dhcpcd/dist/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/dhcp.c:1.30 src/external/bsd/dhcpcd/dist/dhcp.c:1.31
--- src/external/bsd/dhcpcd/dist/dhcp.c:1.30	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/dhcp.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcp.c,v 1.30 2015/05/02 15:18:36 roy Exp $");
+ __RCSID("$NetBSD: dhcp.c,v 1.31 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -1277,35 +1277,35 @@ dhcp_env(char **env, const char *prefix,
 		/* Set some useful variables that we derive from the DHCP
 		 * message but are not necessarily in the options */
 		addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr;
-		setvar(ifp->ctx, &ep, prefix, "ip_address", inet_ntoa(addr));
+		addvar(ifp->ctx, &ep, prefix, "ip_address", inet_ntoa(addr));
 		if (get_option_addr(ifp->ctx, &net,
 		    dhcp, DHO_SUBNETMASK) == -1) {
 			net.s_addr = ipv4_getnetmask(addr.s_addr);
-			setvar(ifp->ctx, &ep, prefix,
+			addvar(ifp->ctx, &ep, prefix,
 			    "subnet_mask", inet_ntoa(net));
 		}
 		snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
-		setvar(ifp->ctx, &ep, prefix, "subnet_cidr", cidr);
+		addvar(ifp->ctx, &ep, prefix, "subnet_cidr", cidr);
 		if (get_option_addr(ifp->ctx, &brd,
 		    dhcp, DHO_BROADCAST) == -1) {
 			brd.s_addr = addr.s_addr | ~net.s_addr;
-			setvar(ifp->ctx, &ep, prefix,
+			addvar(ifp->ctx, &ep, prefix,
 			    "broadcast_address", inet_ntoa(brd));
 		}
 		addr.s_addr = dhcp->yiaddr & net.s_addr;
-		setvar(ifp->ctx, &ep, prefix,
+		addvar(ifp->ctx, &ep, prefix,
 		    "network_number", inet_ntoa(addr));
 	}
 
 	if (*dhcp->bootfile && !(overl & 1)) {
 		print_string(safe, sizeof(safe), STRING,
 		    dhcp->bootfile, sizeof(dhcp->bootfile));
-		setvar(ifp->ctx, &ep, prefix, "filename", safe);
+		addvar(ifp->ctx, &ep, prefix, "filename", safe);
 	}
 	if (*dhcp->servername && !(overl & 2)) {
 		print_string(safe, sizeof(safe), STRING | DOMAIN,
 		    dhcp->servername, sizeof(dhcp->servername));
-		setvar(ifp->ctx, &ep, prefix, "server_name", safe);
+		addvar(ifp->ctx, &ep, prefix, "server_name", safe);
 	}
 
 	/* Zero our indexes */
@@ -1440,7 +1440,7 @@ dhcp_close(struct interface *ifp)
 		return;
 
 	if (state->raw_fd != -1) {
-		eloop_event_delete(ifp->ctx->eloop, state->raw_fd, 0);
+		eloop_event_delete(ifp->ctx->eloop, state->raw_fd);
 		close(state->raw_fd);
 		state->raw_fd = -1;
 	}
@@ -1596,12 +1596,16 @@ send_message(struct interface *ifp, uint
 	struct ipv4_addr *ia;
 #endif
 
-	if (!callback)
+	s = -1;
+	if (!callback) {
+		/* No carrier? Don't bother sending the packet. */
+		if (ifp->carrier == LINK_DOWN)
+			return;
 		logger(ifp->ctx, LOG_DEBUG, "%s: sending %s with xid 0x%x",
 		    ifp->name,
 		    ifo->options & DHCPCD_BOOTP ? "BOOTP" : get_dhcp_op(type),
 		    state->xid);
-	else {
+	} else {
 		if (state->interval == 0)
 			state->interval = 4;
 		else {
@@ -1613,6 +1617,10 @@ send_message(struct interface *ifp, uint
 		tv.tv_nsec = (suseconds_t)arc4random_uniform(
 		    (DHCP_RAND_MAX - DHCP_RAND_MIN) * NSEC_PER_SEC);
 		timespecnorm(&tv);
+		/* No carrier? Don't bother sending the packet.
+		 * However, we do need to advance the timeout. */
+		if (ifp->carrier == LINK_DOWN)
+			goto fail;
 		logger(ifp->ctx, LOG_DEBUG,
 		    "%s: sending %s (xid 0x%x), next in %0.1f seconds",
 		    ifp->name,
@@ -1638,8 +1646,7 @@ send_message(struct interface *ifp, uint
 		if (s == -1 && errno != EADDRINUSE)
 			logger(ifp->ctx, LOG_ERR,
 			    "%s: dhcp_openudp: %m", ifp->name);
-	} else
-		s = -1;
+	}
 
 	/* If we couldn't open a UDP port for our IP address
 	 * then we cannot renew.
@@ -1862,6 +1869,104 @@ dhcp_rebind(void *arg)
 	send_rebind(ifp);
 }
 
+static void
+dhcp_arp_probed(struct arp_state *astate)
+{
+	struct dhcp_state *state;
+	struct if_options *ifo;
+
+	/* We didn't find a profile for this
+	 * address or hwaddr, so move to the next
+	 * arping profile */
+	state = D_STATE(astate->iface);
+	ifo = astate->iface->options;
+	if (state->arping_index < ifo->arping_len) {
+		if (++state->arping_index < ifo->arping_len) {
+			astate->addr.s_addr =
+			    ifo->arping[state->arping_index - 1];
+			arp_probe(astate);
+		}
+		dhcpcd_startinterface(astate->iface);
+		return;
+	}
+	dhcp_close(astate->iface);
+	eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate->iface);
+#ifdef IN_IFF_TENTATIVE
+	ipv4_finaliseaddr(astate->iface);
+	arp_close(astate->iface);
+#else
+	dhcp_bind(astate->iface, astate);
+#endif
+}
+
+static void
+dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
+{
+	struct dhcp_state *state;
+	struct if_options *ifo;
+
+	state = D_STATE(astate->iface);
+	ifo = astate->iface->options;
+	if (state->arping_index &&
+	    state->arping_index <= ifo->arping_len &&
+	    amsg &&
+	    (amsg->sip.s_addr == ifo->arping[state->arping_index - 1] ||
+	    (amsg->sip.s_addr == 0 &&
+	    amsg->tip.s_addr == ifo->arping[state->arping_index - 1])))
+	{
+		char buf[HWADDR_LEN * 3];
+
+		astate->failed.s_addr = ifo->arping[state->arping_index - 1];
+		arp_report_conflicted(astate, amsg);
+		hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf));
+		if (dhcpcd_selectprofile(astate->iface, buf) == -1 &&
+		    dhcpcd_selectprofile(astate->iface,
+		        inet_ntoa(astate->failed)) == -1)
+		{
+			/* We didn't find a profile for this
+			 * address or hwaddr, so move to the next
+			 * arping profile */
+			dhcp_arp_probed(astate);
+			return;
+		}
+		dhcp_close(astate->iface);
+		arp_close(astate->iface);
+		eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
+		    astate->iface);
+		dhcpcd_startinterface(astate->iface);
+	}
+
+	/* RFC 2131 3.1.5, Client-server interaction
+	 * NULL amsg means IN_IFF_DUPLICATED */
+	if (amsg == NULL || (state->offer &&
+	    (amsg->sip.s_addr == state->offer->yiaddr ||
+	    (amsg->sip.s_addr == 0 &&
+	    amsg->tip.s_addr == state->offer->yiaddr))))
+	{
+#ifdef IN_IFF_DUPLICATED
+		struct ipv4_addr *ia;
+#endif
+
+		if (amsg)
+			astate->failed.s_addr = state->offer->yiaddr;
+		else
+			astate->failed = astate->addr;
+		arp_report_conflicted(astate, amsg);
+		unlink(state->leasefile);
+		if (!state->lease.frominfo)
+			dhcp_decline(astate->iface);
+#ifdef IN_IFF_DUPLICATED
+		ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL);
+		if (ia)
+			ipv4_deladdr(astate->iface, &ia->addr, &ia->net);
+#endif
+		eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
+		    astate->iface);
+		eloop_timeout_add_sec(astate->iface->ctx->eloop,
+		    DHCP_RAND_MAX, dhcp_discover, astate->iface);
+	}
+}
+
 void
 dhcp_bind(struct interface *ifp, struct arp_state *astate)
 {
@@ -1872,6 +1977,9 @@ dhcp_bind(struct interface *ifp, struct 
 
 	if (state->state == DHS_BOUND)
 		goto applyaddr;
+#ifdef IN_IFF_TENTATIVE
+	state->added |= STATE_TENTATIVE;
+#endif
 	state->reason = NULL;
 	free(state->old);
 	state->old = state->new;
@@ -1989,6 +2097,16 @@ dhcp_bind(struct interface *ifp, struct 
 			    "%s: write_lease: %m", __func__);
 
 applyaddr:
+#ifdef IN_IFF_TENTATIVE
+	if (astate == NULL) {
+		astate = arp_new(ifp, &lease->addr);
+		if (astate) {
+			astate->probed_cb = dhcp_arp_probed;
+			astate->conflicted_cb = dhcp_arp_conflicted;
+		}
+	}
+#endif
+
 	ipv4_applyaddr(ifp);
 	if (ifo->options & DHCPCD_ARP &&
 	    !(ifp->ctx->options & DHCPCD_FORKED))
@@ -2345,104 +2463,6 @@ whitelisted_ip(const struct if_options *
 }
 
 static void
-dhcp_arp_probed(struct arp_state *astate)
-{
-	struct dhcp_state *state;
-	struct if_options *ifo;
-
-	/* We didn't find a profile for this
-	 * address or hwaddr, so move to the next
-	 * arping profile */
-	state = D_STATE(astate->iface);
-	ifo = astate->iface->options;
-	if (state->arping_index < ifo->arping_len) {
-		if (++state->arping_index < ifo->arping_len) {
-			astate->addr.s_addr =
-			    ifo->arping[state->arping_index - 1];
-			arp_probe(astate);
-		}
-		dhcpcd_startinterface(astate->iface);
-		return;
-	}
-	dhcp_close(astate->iface);
-	eloop_timeout_delete(astate->iface->ctx->eloop, NULL, astate->iface);
-#ifdef IN_IFF_TENTATIVE
-	ipv4_finaliseaddr(astate->iface);
-	arp_close(astate->iface);
-#else
-	dhcp_bind(astate->iface, astate);
-#endif
-}
-
-static void
-dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
-{
-	struct dhcp_state *state;
-	struct if_options *ifo;
-
-	state = D_STATE(astate->iface);
-	ifo = astate->iface->options;
-	if (state->arping_index &&
-	    state->arping_index <= ifo->arping_len &&
-	    amsg &&
-	    (amsg->sip.s_addr == ifo->arping[state->arping_index - 1] ||
-	    (amsg->sip.s_addr == 0 &&
-	    amsg->tip.s_addr == ifo->arping[state->arping_index - 1])))
-	{
-		char buf[HWADDR_LEN * 3];
-
-		astate->failed.s_addr = ifo->arping[state->arping_index - 1];
-		arp_report_conflicted(astate, amsg);
-		hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf));
-		if (dhcpcd_selectprofile(astate->iface, buf) == -1 &&
-		    dhcpcd_selectprofile(astate->iface,
-		        inet_ntoa(astate->failed)) == -1)
-		{
-			/* We didn't find a profile for this
-			 * address or hwaddr, so move to the next
-			 * arping profile */
-			dhcp_arp_probed(astate);
-			return;
-		}
-		dhcp_close(astate->iface);
-		arp_close(astate->iface);
-		eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
-		    astate->iface);
-		dhcpcd_startinterface(astate->iface);
-	}
-
-	/* RFC 2131 3.1.5, Client-server interaction
-	 * NULL amsg means IN_IFF_DUPLICATED */
-	if (amsg == NULL || (state->offer &&
-	    (amsg->sip.s_addr == state->offer->yiaddr ||
-	    (amsg->sip.s_addr == 0 &&
-	    amsg->tip.s_addr == state->offer->yiaddr))))
-	{
-#ifdef IN_IFF_DUPLICATED
-		struct ipv4_addr *ia;
-#endif
-
-		if (amsg)
-			astate->failed.s_addr = state->offer->yiaddr;
-		else
-			astate->failed = astate->addr;
-		arp_report_conflicted(astate, amsg);
-		unlink(state->leasefile);
-		if (!state->lease.frominfo)
-			dhcp_decline(astate->iface);
-#ifdef IN_IFF_DUPLICATED
-		ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL);
-		if (ia)
-			ipv4_deladdr(astate->iface, &ia->addr, &ia->net);
-#endif
-		eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
-		    astate->iface);
-		eloop_timeout_add_sec(astate->iface->ctx->eloop,
-		    DHCP_RAND_MAX, dhcp_discover, astate->iface);
-	}
-}
-
-static void
 dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
     const struct in_addr *from)
 {
@@ -2762,28 +2782,22 @@ dhcp_handledhcp(struct interface *ifp, s
 #ifndef IN_IFF_TENTATIVE
 	if (ifo->options & DHCPCD_ARP
 	    && state->addr.s_addr != state->offer->yiaddr)
-#endif
 	{
 		addr.s_addr = state->offer->yiaddr;
-#ifndef IN_IFF_TENTATIVE
 		/* If the interface already has the address configured
 		 * then we can't ARP for duplicate detection. */
 		ia = ipv4_findaddr(ifp->ctx, &addr);
 		if (ia) {
-#endif
 			astate = arp_new(ifp, &addr);
 			if (astate) {
 				astate->probed_cb = dhcp_arp_probed;
 				astate->conflicted_cb = dhcp_arp_conflicted;
-#ifndef IN_IFF_TENTATIVE
 				arp_probe(astate);
-#endif
 			}
-#ifndef IN_IFF_TENTATIVE
 			return;
 		}
-#endif
 	}
+#endif
 
 	dhcp_bind(ifp, astate);
 }
@@ -2954,7 +2968,7 @@ dhcp_handleudp(void *arg)
 	 * from the raw fd */
 	if (read(ctx->udp_fd, buffer, sizeof(buffer)) == -1) {
 		logger(ctx, LOG_ERR, "%s: %m", __func__);
-		eloop_event_delete(ctx->eloop, ctx->udp_fd, 0);
+		eloop_event_delete(ctx->eloop, ctx->udp_fd);
 		close(ctx->udp_fd);
 		ctx->udp_fd = -1;
 	}
@@ -3049,7 +3063,7 @@ dhcp_free(struct interface *ifp)
 	}
 	if (ifp == NULL) {
 		if (ctx->udp_fd != -1) {
-			eloop_event_delete(ctx->eloop, ctx->udp_fd, 0);
+			eloop_event_delete(ctx->eloop, ctx->udp_fd);
 			close(ctx->udp_fd);
 			ctx->udp_fd = -1;
 		}

Index: src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.7 src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.8
--- src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf:1.7	Fri Jan 30 09:47:05 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-definitions.conf	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-# $NetBSD: dhcpcd-definitions.conf,v 1.7 2015/01/30 09:47:05 roy Exp $
+# $NetBSD: dhcpcd-definitions.conf,v 1.8 2015/05/16 23:31:32 roy Exp $
 
 # Copyright (c) 2006-2015 Roy Marples
 # All rights reserved
@@ -109,7 +109,7 @@ define 80	norequest flag		rapid_commit
 
 # DHCP Fully Qualified Domain Name, RFC4702
 define 81	embed			fqdn
-embed		byte			flags
+embed		bitflags=0000NEOS	flags
 embed		byte			rcode1
 embed		byte			rcode2
 embed		domain			fqdn
@@ -289,6 +289,36 @@ encap 255	flag			global
 # Option 255 End
 
 ##############################################################################
+# ND6 options, RFC4861
+definend 1	binhex			source_address
+definend 2	binhex			target_address
+
+definend 3	index embed		prefix_information
+embed		byte			length
+embed		bitflags=LA		flags
+embed		uint32			vltime
+embed		uint32			pltime
+embed		uint32			reserved
+embed		array ip6address	prefix
+
+# option 4 is only for Redirect messages
+
+definend 5	embed			mtu
+embed		uint16			reserved
+embed		uint32			mtu
+
+# ND6 options, RFC6101
+definend 25	index embed		rdnss
+embed		uint16			reserved
+embed		uint32			lifetime
+embed		array ip6address	servers
+
+definend 31	index embed		dnssl
+embed		uint16			reserved
+embed		uint32			lifetime
+embed		domain			search
+
+##############################################################################
 # DHCPv6 options, RFC3315
 define6 1	binhex			client_id
 define6 2	binhex			server_id
@@ -399,7 +429,7 @@ define6 38	binhex			subscriber_id
 
 # DHCPv6 Fully Qualified Domain Name, RFC4704
 define6 39	embed			fqdn
-embed		byte			flags
+embed		bitflags=00000NOS	flags
 embed		domain			fqdn
 
 # DHCPv6 PANA Authentication Agnet, RC5192
Index: src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.7 src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.8
--- src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h:1.7	Fri Jan 30 09:47:05 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-embedded.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcpcd-embedded.h,v 1.7 2015/01/30 09:47:05 roy Exp $ */
+/* $NetBSD: dhcpcd-embedded.h,v 1.8 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -28,6 +28,7 @@
  */
 
 #define INITDEFINES	     121
+#define INITDEFINENDS	       6
 #define INITDEFINE6S	      68
 
 extern const char * const dhcpcd_embedded_conf[];

Index: src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.13 src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.14
--- src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in:1.13	Fri Jan 30 09:47:05 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd-run-hooks.8.in,v 1.13 2015/01/30 09:47:05 roy Exp $
+.\"     $NetBSD: dhcpcd-run-hooks.8.in,v 1.14 2015/05/16 23:31:32 roy Exp $
 .\" Copyright (c) 2006-2015 Roy Marples
 .\" All rights reserved
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd October 3, 2014
+.Dd May 14, 2015
 .Dt DHCPCD-RUN-HOOKS 8
 .Os
 .Sh NAME
@@ -187,11 +187,6 @@ is down, otherwise
 .It Ev $if_oneup
 .Dv true
 if any interface is up, otherwise false.
-.It Ev $if_ipwaited
-.Dv true
-if any interface has been assigned an IP address which matches any wait
-requirements specified in
-.Xr dhcpcd.conf 5 .
 .It Ev $profile
 the name of the profile selected from
 .Xr dhcpcd.conf 5 .

Index: src/external/bsd/dhcpcd/dist/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.41 src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.42
--- src/external/bsd/dhcpcd/dist/dhcpcd.8.in:1.41	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.8.in	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.8.in,v 1.41 2015/03/26 10:26:37 roy Exp $
+.\"     $NetBSD: dhcpcd.8.in,v 1.42 2015/05/16 23:31:32 roy Exp $
 .\" Copyright (c) 2006-2015 Roy Marples
 .\" All rights reserved
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd March 17, 2015
+.Dd May 9, 2015
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -418,7 +418,7 @@ If
 fails to contact a DHCP server then it returns a failure instead of falling
 back on IPv4LL.
 .It Fl S, Fl Fl static Ar value
-Configures a static
+Configures a static DHCP
 .Ar value .
 If you set
 .Ic ip_address
@@ -432,6 +432,11 @@ Here is an example which configures a st
 .D1 -S routers=192.168.0.1 \e
 .D1 -S domain_name_servers=192.168.0.1 \e
 .D1 eth0
+.Pp
+You cannot presently set static DHCPv6 values.
+Use the
+.Fl e , Fl Fl env
+option instead.
 .It Fl t , Fl Fl timeout Ar seconds
 Timeout after
 .Ar seconds ,

Index: src/external/bsd/dhcpcd/dist/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.c:1.24 src/external/bsd/dhcpcd/dist/dhcpcd.c:1.25
--- src/external/bsd/dhcpcd/dist/dhcpcd.c:1.24	Sat May  2 15:18:36 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: dhcpcd.c,v 1.24 2015/05/02 15:18:36 roy Exp $");
+ __RCSID("$NetBSD: dhcpcd.c,v 1.25 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -69,19 +69,16 @@ const char dhcpcd_copyright[] = "Copyrig
 #include "script.h"
 
 #ifdef USE_SIGNALS
-const int dhcpcd_handlesigs[] = {
+const int dhcpcd_signals[] = {
 	SIGTERM,
 	SIGINT,
 	SIGALRM,
 	SIGHUP,
 	SIGUSR1,
 	SIGUSR2,
-	SIGPIPE,
-	0
+	SIGPIPE
 };
-
-/* Handling signals needs *some* context */
-static struct dhcpcd_ctx *dhcpcd_ctx;
+const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
 #endif
 
 #if defined(USE_SIGNALS) || !defined(THERE_IS_NO_FORK)
@@ -170,6 +167,14 @@ free_globals(struct dhcpcd_ctx *ctx)
 	}
 #endif
 #ifdef INET6
+	if (ctx->nd_opts) {
+		for (opt = ctx->nd_opts;
+		    ctx->nd_opts_len > 0;
+		    opt++, ctx->nd_opts_len--)
+			free_dhcp_opt_embenc(opt);
+		free(ctx->nd_opts);
+		ctx->nd_opts = NULL;
+	}
 	if (ctx->dhcp6_opts) {
 		for (opt = ctx->dhcp6_opts;
 		    ctx->dhcp6_opts_len > 0;
@@ -218,26 +223,50 @@ dhcpcd_oneup(struct dhcpcd_ctx *ctx)
 	return 0;
 }
 
-int
-dhcpcd_ipwaited(struct dhcpcd_ctx *ctx)
+static int
+dhcpcd_ifipwaited(struct interface *ifp, unsigned long long opts)
 {
 
-	if (ctx->options & DHCPCD_WAITIP4 &&
-	    !ipv4_addrexists(ctx, NULL))
+	if (opts & DHCPCD_WAITIP4 && !ipv4_ifaddrexists(ifp))
 		return 0;
-	if (ctx->options & DHCPCD_WAITIP6 &&
-	    !ipv6nd_findaddr(ctx, NULL, 0) &&
-	    !dhcp6_findaddr(ctx, NULL, 0))
+	if (opts & DHCPCD_WAITIP6 && !ipv6_iffindaddr(ifp, NULL))
 		return 0;
-	if (ctx->options & DHCPCD_WAITIP &&
-	    !(ctx->options & (DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) &&
-	    !ipv4_addrexists(ctx, NULL) &&
-	    !ipv6nd_findaddr(ctx, NULL, 0) &&
-	    !dhcp6_findaddr(ctx, NULL, 0))
+	if (opts & DHCPCD_WAITIP &&
+	    !(opts & (DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) &&
+	    !ipv4_ifaddrexists(ifp) &&
+	    !ipv6_iffindaddr(ifp, NULL))
 		return 0;
 	return 1;
 }
 
+static int
+dhcpcd_ipwaited(struct dhcpcd_ctx *ctx)
+{
+	struct interface *ifp;
+
+	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+		if (ifp->options->options & DHCPCD_WAITOPTS) {
+			if (!dhcpcd_ifipwaited(ifp, ifp->options->options)) {
+				logger(ctx, LOG_DEBUG,
+				    "%s: waiting for an ip address",
+				    ifp->name);
+				return 0;
+			}
+		}
+	}
+
+	if (!(ctx->options & DHCPCD_WAITOPTS))
+		return 1;
+
+	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+		if (dhcpcd_ifipwaited(ifp, ctx->options))
+			return 1;
+	}
+
+	logger(ctx, LOG_DEBUG, "waiting for an ip address");
+	return 0;
+}
+
 /* Returns the pid of the child, otherwise 0. */
 pid_t
 dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
@@ -590,7 +619,7 @@ dhcpcd_pollup(void *arg)
 		struct timespec tv;
 
 		tv.tv_sec = 0;
-		tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC;
+		tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC;
 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp);
 		return;
 	}
@@ -643,7 +672,8 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 			script_runreason(ifp, "NOCARRIER");
 #ifdef NOCARRIER_PRESERVE_IP
 			arp_close(ifp);
-			ipv4_buildroutes(ifp->ctx);
+			if_sortinterfaces(ctx);
+			ipv4_preferanother(ifp);
 			ipv6nd_expire(ifp, 0);
 #else
 			dhcpcd_drop(ifp, 0);
@@ -757,7 +787,7 @@ dhcpcd_startinterface(void *arg)
 			 * Loop until both IFF_UP and IFF_RUNNING are set */
 			if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) {
 				tv.tv_sec = 0;
-				tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC;
+				tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC;
 				eloop_timeout_add_tv(ifp->ctx->eloop,
 				    &tv, dhcpcd_startinterface, ifp);
 			} else
@@ -877,7 +907,7 @@ handle_link(void *arg)
 	ctx = arg;
 	if (if_managelink(ctx) == -1) {
 		logger(ctx, LOG_ERR, "if_managelink: %m");
-		eloop_event_delete(ctx->eloop, ctx->link_fd, 0);
+		eloop_event_delete(ctx->eloop, ctx->link_fd);
 		close(ctx->link_fd);
 		ctx->link_fd = -1;
 	}
@@ -1119,21 +1149,17 @@ stop_all_interfaces(struct dhcpcd_ctx *c
 }
 
 #ifdef USE_SIGNALS
-struct dhcpcd_siginfo dhcpcd_siginfo;
 #define sigmsg "received %s, %s"
-void
-dhcpcd_handle_signal(void *arg)
+static void
+signal_cb(int sig, void *arg)
 {
-	struct dhcpcd_ctx *ctx;
-	struct dhcpcd_siginfo *si;
+	struct dhcpcd_ctx *ctx = arg;
 	struct interface *ifp;
-	int do_release, exit_code;;
+	int do_release, exit_code;
 
-	ctx = dhcpcd_ctx;
-	si = arg;
 	do_release = 0;
 	exit_code = EXIT_FAILURE;
-	switch (si->signo) {
+	switch (sig) {
 	case SIGINT:
 		logger(ctx, LOG_INFO, sigmsg, "SIGINT", "stopping");
 		break;
@@ -1172,7 +1198,7 @@ dhcpcd_handle_signal(void *arg)
 		logger(ctx, LOG_ERR,
 		    "received signal %d, "
 		    "but don't know what to do with it",
-		    si->signo);
+		    sig);
 		return;
 	}
 
@@ -1180,47 +1206,6 @@ dhcpcd_handle_signal(void *arg)
 		stop_all_interfaces(ctx, do_release);
 	eloop_exit(ctx->eloop, exit_code);
 }
-
-#ifndef HAVE_KQUEUE
-static void
-handle_signal(int sig, __unused siginfo_t *siginfo, __unused void *context)
-{
-
-	/* So that we can operate safely under a signal we instruct
-	 * eloop to pass a copy of the siginfo structure to handle_signal1
-	 * as the very first thing to do. */
-	dhcpcd_siginfo.signo = sig;
-	eloop_timeout_add_now(dhcpcd_ctx->eloop,
-	    dhcpcd_handle_signal, &dhcpcd_siginfo);
-}
-#endif
-
-static int
-signal_init(sigset_t *oldset)
-{
-	sigset_t newset;
-#ifndef HAVE_KQUEUE
-	int i;
-	struct sigaction sa;
-#endif
-
-	sigfillset(&newset);
-	if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1)
-		return -1;
-
-#ifndef HAVE_KQUEUE
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handle_signal;
-	sa.sa_flags = SA_SIGINFO;
-	sigemptyset(&sa.sa_mask);
-
-	for (i = 0; dhcpcd_handlesigs[i]; i++) {
-		if (sigaction(dhcpcd_handlesigs[i], &sa, NULL) == -1)
-			return -1;
-	}
-#endif
-	return 0;
-}
 #endif
 
 static void
@@ -1242,7 +1227,7 @@ dhcpcd_getinterfaces(void *arg)
 	}
 	if (write(fd->fd, &len, sizeof(len)) != sizeof(len))
 		return;
-	eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
+	eloop_event_remove_writecb(fd->ctx->eloop, fd->fd);
 	TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
 		if (send_interface(fd, ifp) == -1)
 			logger(ifp->ctx, LOG_ERR,
@@ -1344,7 +1329,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 
 	reload_config(ctx);
 	/* XXX: Respect initial commandline options? */
-	reconf_reboot(ctx, do_reboot, argc, argv, optind);
+	reconf_reboot(ctx, do_reboot, argc, argv, optind - 1);
 	return 0;
 }
 
@@ -1362,8 +1347,8 @@ main(int argc, char **argv)
 	pid_t pid;
 #endif
 #ifdef USE_SIGNALS
-	int sig;
-	const char *siga;
+	int sig = 0;
+	const char *siga = NULL;
 #endif
 
 	/* Test for --help and --version */
@@ -1378,11 +1363,6 @@ main(int argc, char **argv)
 	}
 
 	memset(&ctx, 0, sizeof(ctx));
-#ifdef USE_SIGNALS
-	dhcpcd_ctx = &ctx;
-	sig = 0;
-	siga = NULL;
-#endif
 	closefrom(3);
 
 	ctx.log_fd = -1;
@@ -1486,6 +1466,9 @@ main(int argc, char **argv)
 #endif
 #ifdef INET6
 		if (family == 0 || family == AF_INET6) {
+			printf("\nND options:\n");
+			ipv6nd_printoptions(&ctx,
+			    ifo->nd_override, ifo->nd_override_len);
 			printf("\nDHCPv6 options:\n");
 			dhcp6_printoptions(&ctx,
 			    ifo->dhcp6_override, ifo->dhcp6_override_len);
@@ -1558,8 +1541,7 @@ main(int argc, char **argv)
 
 	/* Freeing allocated addresses from dumping leases can trigger
 	 * eloop removals as well, so init here. */
-	ctx.eloop = eloop_init(&ctx);
-	if (ctx.eloop == NULL) {
+	if ((ctx.eloop = eloop_new()) == NULL) {
 		logger(&ctx, LOG_ERR, "%s: eloop_init: %m", __func__);
 		goto exit_failure;
 	}
@@ -1747,9 +1729,16 @@ main(int argc, char **argv)
 	logger(&ctx, LOG_DEBUG, PACKAGE "-" VERSION " starting");
 	ctx.options |= DHCPCD_STARTED;
 #ifdef USE_SIGNALS
+	if (eloop_signal_set_cb(ctx.eloop,
+	    dhcpcd_signals, dhcpcd_signals_len,
+	    signal_cb, &ctx) == -1)
+	{
+		logger(&ctx, LOG_ERR, "eloop_signal_mask: %m");
+		goto exit_failure;
+	}
 	/* Save signal mask, block and redirect signals to our handler */
-	if (signal_init(&ctx.sigset) == -1) {
-		logger(&ctx, LOG_ERR, "signal_setup: %m");
+	if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
+		logger(&ctx, LOG_ERR, "eloop_signal_mask: %m");
 		goto exit_failure;
 	}
 #endif
@@ -1846,7 +1835,11 @@ main(int argc, char **argv)
 		    dhcpcd_prestartinterface, ifp);
 	}
 
-	i = eloop_start(ctx.eloop);
+	i = eloop_start(ctx.eloop, &ctx.sigset);
+	if (i < 0) {
+		syslog(LOG_ERR, "eloop_start: %m");
+		goto exit_failure;
+	}
 	goto exit1;
 
 exit_success:
@@ -1867,7 +1860,7 @@ exit1:
 	}
 	free(ctx.duid);
 	if (ctx.link_fd != -1) {
-		eloop_event_delete(ctx.eloop, ctx.link_fd, 0);
+		eloop_event_delete(ctx.eloop, ctx.link_fd);
 		close(ctx.link_fd);
 	}
 

Index: src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.20 src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.21
--- src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in:1.20	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.conf.5.in	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-.\"     $NetBSD: dhcpcd.conf.5.in,v 1.20 2015/05/02 15:18:37 roy Exp $
+.\"     $NetBSD: dhcpcd.conf.5.in,v 1.21 2015/05/16 23:31:32 roy Exp $
 .\" Copyright (c) 2006-2015 Roy Marples
 .\" All rights reserved
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 6, 2015
+.Dd May 15, 2015
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -463,14 +463,39 @@ You can specify more
 separated by commas, spaces or more
 .Ic option
 lines.
+.Ar option
 Prepend dhcp6_ to
 .Ar option
 to request a DHCPv6 option.
 DHCPv4 options are mapped to DHCPv6 where applicable.
+.Pp
+Prepend nd_ to
+.Ar option
+to handle ND options, but this only works for the
+.Ic nooption ,
+.Ic reject
+and
+.Ic require
+options.
 .It Ic nooption Ar option
-Remove the option from the DHCP message.
-This should only be used when a DHCP server sends a non requested option
-that should not be processed.
+Remove the option from the message before it's processed.
+.It Ic require Ar option
+Requires the
+.Ar option
+to be present in all messages, otherwise the message is ignored.
+To enforce that
+.Nm dhcpcd
+only responds to DHCP servers and not BOOTP servers, you can
+.Ic require
+.Ar dhcp_message_type .
+This isn't an exact science though because a BOOTP server can send DHCP like
+options.
+.It Ic reject Ar option
+Reject a message that contains the
+.Ar option .
+This is useful when you cannot use
+.Ic require
+to select / de-select BOOTP messages.
 .It Ic destination Ar option
 If
 .Nm
@@ -500,27 +525,6 @@ will timeout before moving back to the D
 .It Ic release
 .Nm dhcpcd
 will release the lease prior to stopping the interface.
-.It Ic require Ar option
-Requires the
-.Ar option
-to be present in all DHCP messages, otherwise the message is ignored.
-It can be a variable to be used in
-.Xr dhcpcd-run-hooks 8
-or the numerical value.
-You can specify more options separated by commas, spaces or more require lines.
-To enforce that
-.Nm dhcpcd
-only responds to DHCP servers and not BOOTP servers, you can
-.Ic require
-.Ar dhcp_message_type .
-This isn't an exact science though because a BOOTP server can send DHCP like
-options.
-.It Ic reject Ar option
-Reject a DHCP message that contains the
-.Ar option .
-This is useful when you cannot use
-.Ic require
-to select / de-select BOOTP messages.
 .It Ic script Ar script
 Use
 .Ar script
@@ -631,9 +635,10 @@ Use the last four bytes of the hardware 
 of a randomly generated number.
 .El
 .Ss Defining new options
-DHCP allows for the use of custom options.
+DHCP, ND and DHCPv6 allow for the use of custom options.
 Each option needs to be started with the
-.Ic define
+.Ic define ,
+.If definend
 or
 .Ic define6
 directive.
@@ -656,6 +661,17 @@ with a name of
 .Ar variable
 exported to
 .Xr dhcpcd-run-hooks 8 .
+.It Ic definend Ar code Ar type Ar variable
+Defines the ND option
+.Ar code
+of
+.Ar type
+with a name of
+.Ar variable
+exported to
+.Xr dhcpcd-run-hooks 8 ,
+with a prefix of
+.Va _nd .
 .It Ic define6 Ar code Ar type Ar variable
 Defines the DHCPv6 option
 .Ar code
@@ -688,6 +704,11 @@ is not the same as defined in the parent
 it is prefixed with the parent
 .Ar variable
 first with an underscore.
+If the
+.Ar variable
+has the name of
+.Ar reserved
+then it is not processed.
 .It Ic encap Ar code Ar type Ar variable
 Defines an encapsulated variable within the defined option.
 The length is determined by the
@@ -721,35 +742,42 @@ Lengths can be specified for string and 
 with other data embedded afterwards in the same option.
 .Bl -tag -width indent
 .It Ic ipaddress
-An IPv4 address, 4 bytes
+An IPv4 address, 4 bytes.
 .It Ic ip6address
-An IPv6 address, 16 bytes
+An IPv6 address, 16 bytes.
 .It Ic string Op : Ic length
 A NVT ASCII string of printable characters.
 .It Ic byte
-A byte
+A byte.
+.It Ic bitflags : Ic flags
+A byte represented as a string of flags, most significant bit first.
+For example, using ABCDEFGH then A would equal 10000000, B 01000000,
+C 00100000, etc.
+If the bit is not set, the flag is not printed.
+A flag of 0 is not printed even if the bit postition is set.
+This is to allow reservation of the first bits while assinging the last bits.
 .It Ic int16
-A signed 16bit integer, 2 bytes
+A signed 16bit integer, 2 bytes.
 .It Ic uint16
-An unsigned 16bit integer, 2 bytes
+An unsigned 16bit integer, 2 bytes.
 .It Ic int32
-A signed 32bit integer, 4 bytes
+A signed 32bit integer, 4 bytes.
 .It Ic uint32
-An unsigned 32bit integer, 4 bytes
-.It Ic flag 
-A fixed value (1) to indicate that the option is present, 0 bytes
+An unsigned 32bit integer, 4 bytes.
+.It Ic flag
+A fixed value (1) to indicate that the option is present, 0 bytes.
 .It Ic domain
-A RFC 3397 encoded string
+A RFC 3397 encoded string.
 .It Ic dname
-A RFC 1035 validated string
+A RFC 1035 validated string.
 .It Ic binhex Op : Ic length
-Binary data expressed as hexadecimal
+Binary data expressed as hexadecimal.
 .It Ic embed
-Contains embedded options (implies encap as well)
+Contains embedded options (implies encap as well).
 .It Ic encap
-Contains encapsulated options (implies embed as well)
+Contains encapsulated options (implies embed as well).
 .It Ic option
-References an option from the global definition
+References an option from the global definition.
 .El
 .Ss Example definition
 .D1 # DHCP option 81, Fully Qualified Domain Name, RFC4702
Index: src/external/bsd/dhcpcd/dist/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/if-bsd.c:1.20 src/external/bsd/dhcpcd/dist/if-bsd.c:1.21
--- src/external/bsd/dhcpcd/dist/if-bsd.c:1.20	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/if-bsd.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-bsd.c,v 1.20 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: if-bsd.c,v 1.21 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -1128,7 +1128,7 @@ if_getlifetime6(struct ipv6_addr *ia)
 				    (uint32_t)(lifetime->ia6t_expire -
 				    MIN(t, lifetime->ia6t_expire));
 				/* Calculate the created time */
-				get_monotonic(&ia->created);
+				clock_gettime(CLOCK_MONOTONIC, &ia->created);
 				ia->created.tv_sec -=
 				    lifetime->ia6t_vltime - ia->prefix_vltime;
 			} else

Index: src/external/bsd/dhcpcd/dist/dhcpcd.h
diff -u src/external/bsd/dhcpcd/dist/dhcpcd.h:1.10 src/external/bsd/dhcpcd/dist/dhcpcd.h:1.11
--- src/external/bsd/dhcpcd/dist/dhcpcd.h:1.10	Thu Mar 26 10:26:37 2015
+++ src/external/bsd/dhcpcd/dist/dhcpcd.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dhcpcd.h,v 1.10 2015/03/26 10:26:37 roy Exp $ */
+/* $NetBSD: dhcpcd.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -34,6 +34,10 @@
 #include <net/if.h>
 
 #include "config.h"
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
+
 #include "defs.h"
 #include "control.h"
 #include "if-options.h"
@@ -107,7 +111,7 @@ struct dhcpcd_ctx {
 #ifdef USE_SIGNALS
 	sigset_t sigset;
 #endif
-	struct eloop_ctx *eloop;
+	struct eloop *eloop;
 
 	int control_fd;
 	int control_unpriv_fd;
@@ -137,6 +141,8 @@ struct dhcpcd_ctx {
 	unsigned char secret[SECRET_LEN];
 	size_t secret_len;
 
+	struct dhcp_opt *nd_opts;
+	size_t nd_opts_len;
 	struct dhcp_opt *dhcp6_opts;
 	size_t dhcp6_opts_len;
 	struct ipv6_ctx *ipv6;
@@ -154,16 +160,11 @@ struct dhcpcd_ctx {
 };
 
 #ifdef USE_SIGNALS
-struct dhcpcd_siginfo {
-	int signo;
-};
-
-extern const int dhcpcd_handlesigs[];
-void dhcpcd_handle_signal(void *);
+extern const int dhcpcd_signals[];
+extern const size_t dhcpcd_signals_len;
 #endif
 
 int dhcpcd_oneup(struct dhcpcd_ctx *);
-int dhcpcd_ipwaited(struct dhcpcd_ctx *);
 pid_t dhcpcd_daemonise(struct dhcpcd_ctx *);
 
 int dhcpcd_handleargs(struct dhcpcd_ctx *, struct fd_list *, int, char **);
Index: src/external/bsd/dhcpcd/dist/eloop.c
diff -u src/external/bsd/dhcpcd/dist/eloop.c:1.10 src/external/bsd/dhcpcd/dist/eloop.c:1.11
--- src/external/bsd/dhcpcd/dist/eloop.c:1.10	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/eloop.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: eloop.c,v 1.10 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: eloop.c,v 1.11 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -30,6 +30,7 @@
 
 #include <sys/time.h>
 
+#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <signal.h>
@@ -37,11 +38,26 @@
 #include <string.h>
 #include <unistd.h>
 
+/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc */
 #include "config.h"
-#include "common.h"
-#include "dhcpcd.h"
 #include "eloop.h"
 
+#ifndef UNUSED
+#define UNUSED(a) (void)((a))
+#endif
+#ifndef __unused
+#ifdef __GNUC__
+#define __unused   __attribute__((__unused__))
+#else
+#define __unused
+#endif
+#endif
+
+#ifndef MSEC_PER_SEC
+#define MSEC_PER_SEC	1000L
+#define NSEC_PER_MSEC	1000000L
+#endif
+
 #if defined(HAVE_KQUEUE)
 #include <sys/event.h>
 #include <fcntl.h>
@@ -54,35 +70,67 @@
 #define UPTR(x)	(x)
 #define LENC(x)	((int)(x))
 #endif
-#define eloop_event_setup_fds(ctx)
+#define eloop_event_setup_fds(eloop)
 #elif defined(HAVE_EPOLL)
 #include <sys/epoll.h>
-#define eloop_event_setup_fds(ctx)
+#define eloop_event_setup_fds(eloop)
 #else
 #include <poll.h>
 static void
-eloop_event_setup_fds(struct eloop_ctx *ctx)
+eloop_event_setup_fds(struct eloop *eloop)
 {
 	struct eloop_event *e;
 	size_t i;
 
 	i = 0;
-	TAILQ_FOREACH(e, &ctx->events, next) {
-		ctx->fds[i].fd = e->fd;
-		ctx->fds[i].events = 0;
+	TAILQ_FOREACH(e, &eloop->events, next) {
+		eloop->fds[i].fd = e->fd;
+		eloop->fds[i].events = 0;
 		if (e->read_cb)
-			ctx->fds[i].events |= POLLIN;
+			eloop->fds[i].events |= POLLIN;
 		if (e->write_cb)
-			ctx->fds[i].events |= POLLOUT;
-		ctx->fds[i].revents = 0;
-		e->pollfd = &ctx->fds[i];
+			eloop->fds[i].events |= POLLOUT;
+		eloop->fds[i].revents = 0;
+		e->pollfd = &eloop->fds[i];
 		i++;
 	}
 }
+
+#ifndef pollts
+/* Wrapper around pselect, to imitate the NetBSD pollts call. */
+static int
+pollts(struct pollfd * fds, nfds_t nfds,
+    const struct timespec *ts, const sigset_t *sigmask)
+{
+	fd_set read_fds;
+	nfds_t n;
+	int maxfd, r;
+
+	FD_ZERO(&read_fds);
+	maxfd = 0;
+	for (n = 0; n < nfds; n++) {
+		if (fds[n].events & POLLIN) {
+			FD_SET(fds[n].fd, &read_fds);
+			if (fds[n].fd > maxfd)
+				maxfd = fds[n].fd;
+		}
+	}
+
+	r = pselect(maxfd + 1, &read_fds, NULL, NULL, ts, sigmask);
+	if (r > 0) {
+		for (n = 0; n < nfds; n++) {
+			fds[n].revents =
+			    FD_ISSET(fds[n].fd, &read_fds) ? POLLIN : 0;
+		}
+	}
+
+	return r;
+}
+#endif
 #endif
 
 int
-eloop_event_add(struct eloop_ctx *ctx, int fd,
+eloop_event_add(struct eloop *eloop, int fd,
     void (*read_cb)(void *), void *read_cb_arg,
     void (*write_cb)(void *), void *write_cb_arg)
 {
@@ -95,6 +143,13 @@ eloop_event_add(struct eloop_ctx *ctx, i
 	struct pollfd *nfds;
 #endif
 
+	assert(eloop != NULL);
+	assert(read_cb != NULL || write_cb != NULL);
+	if (fd == -1) {
+		errno = EINVAL;
+		return -1;
+	}
+
 #ifdef HAVE_EPOLL
 	memset(&epe, 0, sizeof(epe));
 	epe.data.fd = fd;
@@ -104,7 +159,7 @@ eloop_event_add(struct eloop_ctx *ctx, i
 #endif
 
 	/* We should only have one callback monitoring the fd */
-	TAILQ_FOREACH(e, &ctx->events, next) {
+	TAILQ_FOREACH(e, &eloop->events, next) {
 		if (e->fd == fd) {
 			int error;
 
@@ -117,11 +172,11 @@ eloop_event_add(struct eloop_ctx *ctx, i
 			else if (e->write_cb)
 				EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE,
 				    EV_DELETE, 0, 0, UPTR(e));
-			error = kevent(ctx->poll_fd, ke,
+			error = kevent(eloop->poll_fd, ke,
 			    e->write_cb || write_cb ? 2 : 1, NULL, 0, NULL);
 #elif defined(HAVE_EPOLL)
 			epe.data.ptr = e;
-			error = epoll_ctl(ctx->poll_fd, EPOLL_CTL_MOD,
+			error = epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD,
 			    fd, &epe);
 #else
 			error = 0;
@@ -134,14 +189,14 @@ eloop_event_add(struct eloop_ctx *ctx, i
 				e->write_cb = write_cb;
 				e->write_cb_arg = write_cb_arg;
 			}
-			eloop_event_setup_fds(ctx);
+			eloop_event_setup_fds(eloop);
 			return error;
 		}
 	}
 
 	/* Allocate a new event if no free ones already allocated */
-	if ((e = TAILQ_FIRST(&ctx->free_events))) {
-		TAILQ_REMOVE(&ctx->free_events, e, next);
+	if ((e = TAILQ_FIRST(&eloop->free_events))) {
+		TAILQ_REMOVE(&eloop->free_events, e, next);
 	} else {
 		e = malloc(sizeof(*e));
 		if (e == NULL)
@@ -149,14 +204,15 @@ eloop_event_add(struct eloop_ctx *ctx, i
 	}
 
 	/* Ensure we can actually listen to it */
-	ctx->events_len++;
+	eloop->events_len++;
 #if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL)
-	if (ctx->events_len > ctx->fds_len) {
-		nfds = realloc(ctx->fds, sizeof(*ctx->fds) * (ctx->fds_len+5));
+	if (eloop->events_len > eloop->fds_len) {
+		nfds = realloc(eloop->fds,
+		    sizeof(*eloop->fds) * (eloop->fds_len + 5));
 		if (nfds == NULL)
 			goto err;
-		ctx->fds_len += 5;
-		ctx->fds = nfds;
+		eloop->fds_len += 5;
+		eloop->fds = nfds;
 	}
 #endif
 
@@ -168,15 +224,17 @@ eloop_event_add(struct eloop_ctx *ctx, i
 	e->write_cb_arg = write_cb_arg;
 
 #if defined(HAVE_KQUEUE)
-	EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e));
-	if (write_cb)
+	if (read_cb != NULL)
+		EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ,
+		    EV_ADD, 0, 0, UPTR(e));
+	if (write_cb != NULL)
 		EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE,
 		    EV_ADD, 0, 0, UPTR(e));
-	if (kevent(ctx->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1)
+	if (kevent(eloop->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1)
 		goto err;
 #elif defined(HAVE_EPOLL)
 	epe.data.ptr = e;
-	if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1)
+	if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1)
 		goto err;
 #endif
 
@@ -186,21 +244,20 @@ eloop_event_add(struct eloop_ctx *ctx, i
 	 * 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(&ctx->events, e, next);
-	eloop_event_setup_fds(ctx);
+	TAILQ_INSERT_HEAD(&eloop->events, e, next);
+	eloop_event_setup_fds(eloop);
 	return 0;
 
 err:
-	logger(ctx->ctx, LOG_ERR, "%s: %m", __func__);
 	if (e) {
-		ctx->events_len--;
-		TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
+		eloop->events_len--;
+		TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
 	}
 	return -1;
 }
 
 void
-eloop_event_delete(struct eloop_ctx *ctx, int fd, int write_only)
+eloop_event_delete_write(struct eloop *eloop, int fd, int write_only)
 {
 	struct eloop_event *e;
 #if defined(HAVE_KQUEUE)
@@ -209,30 +266,31 @@ eloop_event_delete(struct eloop_ctx *ctx
 	struct epoll_event epe;
 #endif
 
-	TAILQ_FOREACH(e, &ctx->events, next) {
+	assert(eloop != NULL);
+
+	TAILQ_FOREACH(e, &eloop->events, next) {
 		if (e->fd == fd) {
-			if (write_only) {
-				if (e->write_cb) {
+			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(ctx->poll_fd, ke, 1, NULL, 0,
+					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(ctx->poll_fd, EPOLL_CTL_MOD,
-					    fd, &epe);
+					epoll_ctl(eloop->poll_fd,
+					    EPOLL_CTL_MOD, fd, &epe);
 #endif
 				}
-
 			} else {
-				TAILQ_REMOVE(&ctx->events, e, next);
+				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));
@@ -240,32 +298,36 @@ eloop_event_delete(struct eloop_ctx *ctx
 					EV_SET(&ke[1], (uintptr_t)fd,
 					    EVFILT_WRITE, EV_DELETE,
 					    0, 0, UPTR(NULL));
-				kevent(ctx->poll_fd, ke, e->write_cb ? 2 : 1,
+				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(ctx->poll_fd, EPOLL_CTL_DEL,
+				epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL,
 				    fd, NULL);
 #endif
-				TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
-				ctx->events_len--;
+				TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
+				eloop->events_len--;
 			}
-			eloop_event_setup_fds(ctx);
+			eloop_event_setup_fds(eloop);
 			break;
 		}
 	}
 }
 
 int
-eloop_q_timeout_add_tv(struct eloop_ctx *ctx, int queue,
+eloop_q_timeout_add_tv(struct eloop *eloop, int queue,
     const struct timespec *when, void (*callback)(void *), void *arg)
 {
 	struct timespec now, w;
 	struct eloop_timeout *t, *tt = NULL;
 
-	get_monotonic(&now);
+	assert(eloop != NULL);
+	assert(when != NULL);
+	assert(callback != NULL);
+
+	clock_gettime(CLOCK_MONOTONIC, &now);
 	timespecadd(&now, when, &w);
 	/* Check for time_t overflow. */
 	if (timespeccmp(&w, &now, <)) {
@@ -274,23 +336,20 @@ eloop_q_timeout_add_tv(struct eloop_ctx 
 	}
 
 	/* Remove existing timeout if present */
-	TAILQ_FOREACH(t, &ctx->timeouts, next) {
+	TAILQ_FOREACH(t, &eloop->timeouts, next) {
 		if (t->callback == callback && t->arg == arg) {
-			TAILQ_REMOVE(&ctx->timeouts, t, next);
+			TAILQ_REMOVE(&eloop->timeouts, t, next);
 			break;
 		}
 	}
 
 	if (t == NULL) {
 		/* No existing, so allocate or grab one from the free pool */
-		if ((t = TAILQ_FIRST(&ctx->free_timeouts))) {
-			TAILQ_REMOVE(&ctx->free_timeouts, t, next);
+		if ((t = TAILQ_FIRST(&eloop->free_timeouts))) {
+			TAILQ_REMOVE(&eloop->free_timeouts, t, next);
 		} else {
-			t = malloc(sizeof(*t));
-			if (t == NULL) {
-				logger(ctx->ctx, LOG_ERR, "%s: %m", __func__);
+			if ((t = malloc(sizeof(*t))) == NULL)
 				return -1;
-			}
 		}
 	}
 
@@ -301,97 +360,108 @@ eloop_q_timeout_add_tv(struct eloop_ctx 
 
 	/* The timeout list should be in chronological order,
 	 * soonest first. */
-	TAILQ_FOREACH(tt, &ctx->timeouts, next) {
+	TAILQ_FOREACH(tt, &eloop->timeouts, next) {
 		if (timespeccmp(&t->when, &tt->when, <)) {
 			TAILQ_INSERT_BEFORE(tt, t, next);
 			return 0;
 		}
 	}
-	TAILQ_INSERT_TAIL(&ctx->timeouts, t, next);
+	TAILQ_INSERT_TAIL(&eloop->timeouts, t, next);
 	return 0;
 }
 
 int
-eloop_q_timeout_add_sec(struct eloop_ctx *ctx, int queue, time_t when,
+eloop_q_timeout_add_sec(struct eloop *eloop, int queue, time_t when,
     void (*callback)(void *), void *arg)
 {
 	struct timespec tv;
 
 	tv.tv_sec = when;
 	tv.tv_nsec = 0;
-	return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg);
+	return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg);
 }
 
-#if !defined(HAVE_KQUEUE)
 int
-eloop_timeout_add_now(struct eloop_ctx *ctx,
+eloop_q_timeout_add_msec(struct eloop *eloop, int queue, long when,
     void (*callback)(void *), void *arg)
 {
+	struct timespec tv;
 
-	if (ctx->timeout0 != NULL) {
-		logger(ctx->ctx, LOG_WARNING,
-		    "%s: timeout0 already set", __func__);
-		return eloop_q_timeout_add_sec(ctx, 0, 0, callback, arg);
-	}
+	tv.tv_sec = when / MSEC_PER_SEC;
+	tv.tv_nsec = (when % MSEC_PER_SEC) * NSEC_PER_MSEC;
+	return eloop_q_timeout_add_tv(eloop, queue, &tv, callback, arg);
+}
 
-	ctx->timeout0 = callback;
-	ctx->timeout0_arg = arg;
+#if !defined(HAVE_KQUEUE)
+static int
+eloop_timeout_add_now(struct eloop *eloop,
+    void (*callback)(void *), void *arg)
+{
+
+	assert(eloop->timeout0 == NULL);
+	eloop->timeout0 = callback;
+	eloop->timeout0_arg = arg;
 	return 0;
 }
 #endif
 
 void
-eloop_q_timeout_delete(struct eloop_ctx *ctx, int queue,
+eloop_q_timeout_delete(struct eloop *eloop, int queue,
     void (*callback)(void *), void *arg)
 {
 	struct eloop_timeout *t, *tt;
 
-	TAILQ_FOREACH_SAFE(t, &ctx->timeouts, next, tt) {
+	assert(eloop != NULL);
+
+	TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tt) {
 		if ((queue == 0 || t->queue == queue) &&
 		    t->arg == arg &&
 		    (!callback || t->callback == callback))
 		{
-			TAILQ_REMOVE(&ctx->timeouts, t, next);
-			TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next);
+			TAILQ_REMOVE(&eloop->timeouts, t, next);
+			TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next);
 		}
 	}
 }
 
 void
-eloop_exit(struct eloop_ctx *ctx, int code)
+eloop_exit(struct eloop *eloop, int code)
 {
 
-	ctx->exitcode = code;
-	ctx->exitnow = 1;
+	assert(eloop != NULL);
+
+	eloop->exitcode = code;
+	eloop->exitnow = 1;
 }
 
 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
 static int
-eloop_open(struct eloop_ctx *ctx)
+eloop_open(struct eloop *eloop)
 {
+
 #if defined(HAVE_KQUEUE1)
-	return (ctx->poll_fd = kqueue1(O_CLOEXEC));
+	return (eloop->poll_fd = kqueue1(O_CLOEXEC));
 #elif defined(HAVE_KQUEUE)
 	int i;
 
-	if ((ctx->poll_fd = kqueue()) == -1)
+	if ((eloop->poll_fd = kqueue()) == -1)
 		return -1;
-	if ((i = fcntl(ctx->poll_fd, F_GETFD, 0)) == -1 ||
-	    fcntl(ctx->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1)
+	if ((i = fcntl(eloop->poll_fd, F_GETFD, 0)) == -1 ||
+	    fcntl(eloop->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1)
 	{
-		close(ctx->poll_fd);
-		ctx->poll_fd = -1;
+		close(eloop->poll_fd);
+		eloop->poll_fd = -1;
 		return -1;
 	}
 
-	return ctx->poll_fd;
+	return eloop->poll_fd;
 #elif defined (HAVE_EPOLL)
-	return (ctx->poll_fd = epoll_create1(EPOLL_CLOEXEC));
+	return (eloop->poll_fd = epoll_create1(EPOLL_CLOEXEC));
 #endif
 }
 
 int
-eloop_requeue(struct eloop_ctx *ctx)
+eloop_requeue(struct eloop *eloop)
 {
 	struct eloop_event *e;
 	int error;
@@ -402,15 +472,15 @@ eloop_requeue(struct eloop_ctx *ctx)
 	struct epoll_event epe;
 #endif
 
-	if (ctx->poll_fd != -1)
-		close(ctx->poll_fd);
-	if (eloop_open(ctx) == -1)
+	assert(eloop != NULL);
+
+	if (eloop->poll_fd != -1)
+		close(eloop->poll_fd);
+	if (eloop_open(eloop) == -1)
 		return -1;
 #if defined (HAVE_KQUEUE)
-	i = 0;
-	while (dhcpcd_handlesigs[i])
-		i++;
-	TAILQ_FOREACH(e, &ctx->events, next) {
+	i = eloop->signals_len;
+	TAILQ_FOREACH(e, &eloop->events, next) {
 		i++;
 		if (e->write_cb)
 			i++;
@@ -419,11 +489,11 @@ eloop_requeue(struct eloop_ctx *ctx)
 	if ((ke = malloc(sizeof(*ke) * i)) == NULL)
 		return -1;
 
-	for (i = 0; dhcpcd_handlesigs[i]; i++)
-		EV_SET(&ke[i], (uintptr_t)dhcpcd_handlesigs[i],
+	for (i = 0; i < eloop->signals_len; i++)
+		EV_SET(&ke[i], (uintptr_t)eloop->signals[i],
 		    EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL));
 
-	TAILQ_FOREACH(e, &ctx->events, next) {
+	TAILQ_FOREACH(e, &eloop->events, next) {
 		EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_READ,
 		    EV_ADD, 0, 0, UPTR(e));
 		i++;
@@ -434,20 +504,20 @@ eloop_requeue(struct eloop_ctx *ctx)
 		}
 	}
 
-	error =  kevent(ctx->poll_fd, ke, LENC(i), NULL, 0, NULL);
+	error =  kevent(eloop->poll_fd, ke, LENC(i), NULL, 0, NULL);
 	free(ke);
 
 #elif defined(HAVE_EPOLL)
 
 	error = 0;
-	TAILQ_FOREACH(e, &ctx->events, next) {
+	TAILQ_FOREACH(e, &eloop->events, next) {
 		memset(&epe, 0, sizeof(epe));
 		epe.data.fd = e->fd;
 		epe.events = EPOLLIN;
 		if (e->write_cb)
 			epe.events |= EPOLLOUT;
 		epe.data.ptr = e;
-		if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1)
+		if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1)
 			error = -1;
 	}
 #endif
@@ -456,102 +526,179 @@ eloop_requeue(struct eloop_ctx *ctx)
 }
 #endif
 
-struct eloop_ctx *
-eloop_init(struct dhcpcd_ctx *dctx)
+int
+eloop_signal_set_cb(struct eloop *eloop,
+    const int *signals, size_t signals_len,
+    void (*signal_cb)(int, void *), void *signal_cb_ctx)
+{
+
+	assert(eloop != NULL);
+
+	eloop->signals = signals;
+	eloop->signals_len = signals_len;
+	eloop->signal_cb = signal_cb;
+	eloop->signal_cb_ctx = signal_cb_ctx;
+	return eloop_requeue(eloop);
+}
+
+#ifndef HAVE_KQUEUE
+struct eloop_siginfo {
+	int sig;
+	struct eloop *eloop;
+};
+static struct eloop_siginfo _eloop_siginfo;
+static struct eloop *_eloop;
+
+static void
+eloop_signal1(void *arg)
+{
+	struct eloop_siginfo *si = arg;
+
+	si->eloop->signal_cb(si->sig, si->eloop->signal_cb_ctx);
+}
+
+static void
+eloop_signal3(int sig, __unused siginfo_t *siginfo, __unused void *arg)
+{
+
+	/* So that we can operate safely under a signal we instruct
+	 * eloop to pass a copy of the siginfo structure to handle_signal1
+	 * as the very first thing to do. */
+	_eloop_siginfo.eloop = _eloop;
+	_eloop_siginfo.sig = sig;
+	eloop_timeout_add_now(_eloop_siginfo.eloop,
+	    eloop_signal1, &_eloop_siginfo);
+}
+#endif
+
+int
+eloop_signal_mask(struct eloop *eloop, sigset_t *oldset)
 {
-	struct eloop_ctx *ctx;
+	sigset_t newset;
+#ifndef HAVE_KQUEUE
+	size_t i;
+	struct sigaction sa;
+#endif
+
+	assert(eloop != NULL);
+
+	sigfillset(&newset);
+	if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1)
+		return -1;
+
+#ifdef HAVE_KQUEUE
+	UNUSED(eloop);
+#else
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = eloop_signal3;
+	sa.sa_flags = SA_SIGINFO;
+	sigemptyset(&sa.sa_mask);
+
+	for (i = 0; i < eloop->signals_len; i++) {
+		if (sigaction(eloop->signals[i], &sa, NULL) == -1)
+			return -1;
+	}
+#endif
+	return 0;
+}
+
+struct eloop *
+eloop_new(void)
+{
+	struct eloop *eloop;
 	struct timespec now;
 
 	/* Check we have a working monotonic clock. */
-	if (get_monotonic(&now) == -1)
+	if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
 		return NULL;
 
-	ctx = calloc(1, sizeof(*ctx));
-	if (ctx) {
-		ctx->ctx = dctx;
-		TAILQ_INIT(&ctx->events);
-		TAILQ_INIT(&ctx->free_events);
-		TAILQ_INIT(&ctx->timeouts);
-		TAILQ_INIT(&ctx->free_timeouts);
-		ctx->exitcode = EXIT_FAILURE;
+	eloop = calloc(1, sizeof(*eloop));
+	if (eloop) {
+		TAILQ_INIT(&eloop->events);
+		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)
-		ctx->poll_fd = -1;
+		eloop->poll_fd = -1;
+		eloop_open(eloop);
 #endif
-		if (eloop_requeue(ctx) == -1) {
-			free(ctx);
-			return NULL;
-		}
 	}
 
-	return ctx;
+	return eloop;
 }
 
-void eloop_free(struct eloop_ctx *ctx)
+void eloop_free(struct eloop *eloop)
 {
 	struct eloop_event *e;
 	struct eloop_timeout *t;
 
-	if (ctx == NULL)
+	if (eloop == NULL)
 		return;
 
-	while ((e = TAILQ_FIRST(&ctx->events))) {
-		TAILQ_REMOVE(&ctx->events, e, next);
+	while ((e = TAILQ_FIRST(&eloop->events))) {
+		TAILQ_REMOVE(&eloop->events, e, next);
 		free(e);
 	}
-	while ((e = TAILQ_FIRST(&ctx->free_events))) {
-		TAILQ_REMOVE(&ctx->free_events, e, next);
+	while ((e = TAILQ_FIRST(&eloop->free_events))) {
+		TAILQ_REMOVE(&eloop->free_events, e, next);
 		free(e);
 	}
-	while ((t = TAILQ_FIRST(&ctx->timeouts))) {
-		TAILQ_REMOVE(&ctx->timeouts, t, next);
+	while ((t = TAILQ_FIRST(&eloop->timeouts))) {
+		TAILQ_REMOVE(&eloop->timeouts, t, next);
 		free(t);
 	}
-	while ((t = TAILQ_FIRST(&ctx->free_timeouts))) {
-		TAILQ_REMOVE(&ctx->free_timeouts, t, next);
+	while ((t = TAILQ_FIRST(&eloop->free_timeouts))) {
+		TAILQ_REMOVE(&eloop->free_timeouts, t, next);
 		free(t);
 	}
 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
-	close(ctx->poll_fd);
+	close(eloop->poll_fd);
 #else
-	free(ctx->fds);
+	free(eloop->fds);
 #endif
-	free(ctx);
+	free(eloop);
 }
 
 int
-eloop_start(struct eloop_ctx *ctx)
+eloop_start(struct eloop *eloop, sigset_t *signals)
 {
 	int n;
 	struct eloop_event *e;
 	struct eloop_timeout *t;
 	struct timespec now, ts, *tsp;
 	void (*t0)(void *);
-#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS)
-	int timeout;
-#endif
 #if defined(HAVE_KQUEUE)
 	struct kevent ke;
+	UNUSED(signals);
 #elif defined(HAVE_EPOLL)
 	struct epoll_event epe;
 #endif
+#ifndef HAVE_KQUEUE
+	int timeout;
+
+	_eloop = eloop;
+#endif
+
+	assert(eloop != NULL);
 
 	for (;;) {
-		if (ctx->exitnow)
+		if (eloop->exitnow)
 			break;
 
 		/* Run all timeouts first */
-		if (ctx->timeout0) {
-			t0 = ctx->timeout0;
-			ctx->timeout0 = NULL;
-			t0(ctx->timeout0_arg);
+		if (eloop->timeout0) {
+			t0 = eloop->timeout0;
+			eloop->timeout0 = NULL;
+			t0(eloop->timeout0_arg);
 			continue;
 		}
-		if ((t = TAILQ_FIRST(&ctx->timeouts))) {
-			get_monotonic(&now);
+		if ((t = TAILQ_FIRST(&eloop->timeouts))) {
+			clock_gettime(CLOCK_MONOTONIC, &now);
 			if (timespeccmp(&now, &t->when, >)) {
-				TAILQ_REMOVE(&ctx->timeouts, t, next);
+				TAILQ_REMOVE(&eloop->timeouts, t, next);
 				t->callback(t->arg);
-				TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next);
+				TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next);
 				continue;
 			}
 			timespecsub(&t->when, &now, &ts);
@@ -560,12 +707,10 @@ eloop_start(struct eloop_ctx *ctx)
 			/* No timeouts, so wait forever */
 			tsp = NULL;
 
-		if (tsp == NULL && ctx->events_len == 0) {
-			logger(ctx->ctx, LOG_ERR, "nothing to do");
+		if (tsp == NULL && eloop->events_len == 0)
 			break;
-		}
 
-#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS)
+#ifndef HAVE_KQUEUE
 		if (tsp == NULL)
 			timeout = -1;
 		else if (tsp->tv_sec > INT_MAX / 1000 ||
@@ -578,27 +723,25 @@ eloop_start(struct eloop_ctx *ctx)
 #endif
 
 #if defined(HAVE_KQUEUE)
-		n = kevent(ctx->poll_fd, NULL, 0, &ke, 1, tsp);
+		n = kevent(eloop->poll_fd, NULL, 0, &ke, 1, tsp);
 #elif defined(HAVE_EPOLL)
-#ifdef USE_SIGNALS
-		n = epoll_pwait(ctx->poll_fd, &epe, 1, timeout,
-		    &ctx->ctx->sigset);
-#else
-		n = epoll_wait(ctx->poll_fd, &epe, 1, timeout);
-#endif
-#else
-#ifdef USE_SIGNALS
-		n = pollts(ctx->fds, (nfds_t)ctx->events_len, tsp,
-		    &ctx->ctx->sigset);
+		if (signals)
+			n = epoll_pwait(eloop->poll_fd, &epe, 1,
+			    timeout, signals);
+		else
+			n = epoll_wait(eloop->poll_fd, &epe, 1, timeout);
 #else
-		n = poll(ctx->fds, (nfds_t)ctx->events_len, timeout);
-#endif
+		if (signals)
+			n = pollts(eloop->fds, (nfds_t)eloop->events_len,
+			    tsp, signals);
+		else
+			n = poll(eloop->fds, (nfds_t)eloop->events_len,
+			    timeout);
 #endif
 		if (n == -1) {
 			if (errno == EINTR)
 				continue;
-			logger(ctx->ctx, LOG_ERR, "poll: %m");
-			break;
+			return -errno;
 		}
 
 		/* Process any triggered events.
@@ -607,10 +750,8 @@ eloop_start(struct eloop_ctx *ctx)
 #if defined(HAVE_KQUEUE)
 		if (n) {
 			if (ke.filter == EVFILT_SIGNAL) {
-				struct dhcpcd_siginfo si;
-
-				si.signo = (int)ke.ident;
-				dhcpcd_handle_signal(&si);
+				eloop->signal_cb((int)ke.ident,
+				    eloop->signal_cb_ctx);
 				continue;
 			}
 			e = (struct eloop_event *)ke.udata;
@@ -625,12 +766,13 @@ eloop_start(struct eloop_ctx *ctx)
 #elif defined(HAVE_EPOLL)
 		if (n) {
 			e = (struct eloop_event *)epe.data.ptr;
-			if (epe.events & EPOLLOUT && e->write_cb) {
+			if (epe.events & EPOLLOUT && e->write_cb != NULL) {
 				e->write_cb(e->write_cb_arg);
 				continue;
 			}
 			if (epe.events &
-			    (EPOLLIN | EPOLLERR | EPOLLHUP))
+			    (EPOLLIN | EPOLLERR | EPOLLHUP) &&
+			    e->read_cb != NULL)
 			{
 				e->read_cb(e->read_cb_arg);
 				continue;
@@ -638,14 +780,14 @@ eloop_start(struct eloop_ctx *ctx)
 		}
 #else
 		if (n > 0) {
-			TAILQ_FOREACH(e, &ctx->events, next) {
+			TAILQ_FOREACH(e, &eloop->events, next) {
 				if (e->pollfd->revents & POLLOUT &&
-				    e->write_cb)
+				    e->write_cb != NULL)
 				{
 					e->write_cb(e->write_cb_arg);
 					break;
 				}
-				if (e->pollfd->revents) {
+				if (e->pollfd->revents && e->read_cb != NULL) {
 					e->read_cb(e->read_cb_arg);
 					break;
 				}
@@ -654,5 +796,5 @@ eloop_start(struct eloop_ctx *ctx)
 #endif
 	}
 
-	return ctx->exitcode;
+	return eloop->exitcode;
 }
Index: src/external/bsd/dhcpcd/dist/if-options.h
diff -u src/external/bsd/dhcpcd/dist/if-options.h:1.10 src/external/bsd/dhcpcd/dist/if-options.h:1.11
--- src/external/bsd/dhcpcd/dist/if-options.h:1.10	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/if-options.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: if-options.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */
+/* $NetBSD: if-options.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -114,6 +114,8 @@
 #define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC	(1ULL << 56)
 #define DHCPCD_BOOTP			(1ULL << 57)
 
+#define DHCPCD_WAITOPTS (DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6)
+
 #define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \
 		DHCPCD_ROUTER_HOST_ROUTE_WARNED)
 #define DHCPCD_CONF (DHCPCD_NOPFXDLG | DHCPCD_PFXDLGONLY)
@@ -153,11 +155,15 @@ struct if_options {
 	uint8_t requiremask[256 / NBBY];
 	uint8_t nomask[256 / NBBY];
 	uint8_t rejectmask[256 / NBBY];
+	uint8_t dstmask[256 / NBBY];
+	uint8_t requestmasknd[(UINT16_MAX + 1) / NBBY];
+	uint8_t requiremasknd[(UINT16_MAX + 1) / NBBY];
+	uint8_t nomasknd[(UINT16_MAX + 1) / NBBY];
+	uint8_t rejectmasknd[(UINT16_MAX + 1) / NBBY];
 	uint8_t requestmask6[(UINT16_MAX + 1) / NBBY];
 	uint8_t requiremask6[(UINT16_MAX + 1) / NBBY];
 	uint8_t nomask6[(UINT16_MAX + 1) / NBBY];
 	uint8_t rejectmask6[(UINT16_MAX + 1) / NBBY];
-	uint8_t dstmask[256 / NBBY];
 	uint32_t leasetime;
 	time_t timeout;
 	time_t reboot;
@@ -191,6 +197,8 @@ struct if_options {
 
 	struct dhcp_opt *dhcp_override;
 	size_t dhcp_override_len;
+	struct dhcp_opt *nd_override;
+	size_t nd_override_len;
 	struct dhcp_opt *dhcp6_override;
 	size_t dhcp6_override_len;
 	uint32_t vivco_en;
Index: src/external/bsd/dhcpcd/dist/ipv4.h
diff -u src/external/bsd/dhcpcd/dist/ipv4.h:1.10 src/external/bsd/dhcpcd/dist/ipv4.h:1.11
--- src/external/bsd/dhcpcd/dist/ipv4.h:1.10	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv4.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv4.h,v 1.10 2015/05/02 15:18:37 roy Exp $ */
+/* $NetBSD: ipv4.h,v 1.11 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -77,15 +77,18 @@ int ipv4_ifcmp(const struct interface *,
 uint8_t inet_ntocidr(struct in_addr);
 int inet_cidrtoaddr(int, struct in_addr *);
 uint32_t ipv4_getnetmask(uint32_t);
+int ipv4_ifaddrexists(const struct interface *);
 int ipv4_addrexists(struct dhcpcd_ctx *, const struct in_addr *);
 
 #define STATE_ADDED		0x01
 #define STATE_FAKE		0x02
+#define STATE_TENTATIVE		0x04
 
 void ipv4_buildroutes(struct dhcpcd_ctx *);
 void ipv4_finaliseaddr(struct interface *);
 int ipv4_deladdr(struct interface *ifp, const struct in_addr *,
     const struct in_addr *);
+int ipv4_preferanother(struct interface *ifp);
 void ipv4_applyaddr(void *);
 int ipv4_handlert(struct dhcpcd_ctx *, int, struct rt *);
 void ipv4_freerts(struct rt_head *);
@@ -109,7 +112,7 @@ void ipv4_ctxfree(struct dhcpcd_ctx *);
 #define ipv4_freeroutes(a) {}
 #define ipv4_free(a) {}
 #define ipv4_ctxfree(a) {}
-#define ipv4_addrexists(a, b) (0)
+#define ipv4_ifaddrexists(a) (0)
 #endif
 
 #endif

Index: src/external/bsd/dhcpcd/dist/if-options.c
diff -u src/external/bsd/dhcpcd/dist/if-options.c:1.23 src/external/bsd/dhcpcd/dist/if-options.c:1.24
--- src/external/bsd/dhcpcd/dist/if-options.c:1.23	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/if-options.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: if-options.c,v 1.23 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: if-options.c,v 1.24 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -103,6 +103,7 @@
 #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
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -178,6 +179,7 @@ const struct option cf_options[] = {
 	{"dev",             required_argument, NULL, O_DEV},
 	{"nodev",           no_argument,       NULL, O_NODEV},
 	{"define",          required_argument, NULL, O_DEFINE},
+	{"definend",        required_argument, NULL, O_DEFINEND},
 	{"define6",         required_argument, NULL, O_DEFINE6},
 	{"embed",           required_argument, NULL, O_EMBED},
 	{"encap",           required_argument, NULL, O_ENCAP},
@@ -522,11 +524,22 @@ set_option_space(struct dhcpcd_ctx *ctx,
 {
 
 #if !defined(INET) && !defined(INET6)
-	/* Satisfy use */
-	ctx = NULL;
+	UNUSED(ctx);
 #endif
 
 #ifdef INET6
+	if (strncmp(arg, "nd_", strlen("nd_")) == 0) {
+		*d = ctx->nd_opts;
+		*dl = ctx->nd_opts_len;
+		*od = ifo->nd_override;
+		*odl = ifo->nd_override_len;
+		*request = ifo->requestmasknd;
+		*require = ifo->requiremasknd;
+		*no = ifo->nomasknd;
+		*reject = ifo->rejectmasknd;
+		return arg + strlen("nd_");
+	}
+
 	if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
 		*d = ctx->dhcp6_opts;
 		*dl = ctx->dhcp6_opts_len;
@@ -636,7 +649,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 	int e, i, t;
 	long l;
 	unsigned long u;
-	char *p = NULL, *fp, *np, **nconf;
+	char *p = NULL, *bp, *fp, *np, **nconf;
 	ssize_t s;
 	struct in_addr addr, addr2;
 	in_addr_t *naddr;
@@ -1469,6 +1482,12 @@ err_sla:
 		dop = &ifo->dhcp_override;
 		dop_len = &ifo->dhcp_override_len;
 		/* FALLTHROUGH */
+	case O_DEFINEND:
+		if (dop == NULL) {
+			dop = &ifo->nd_override;
+			dop_len = &ifo->nd_override_len;
+		}
+		/* FALLTHROUGH */
 	case O_DEFINE6:
 		if (dop == NULL) {
 			dop = &ifo->dhcp6_override;
@@ -1538,13 +1557,18 @@ err_sla:
 		/* length */
 		if (np) {
 			*np++ = '\0';
+			bp = NULL; /* No bitflag */
 			l = (long)strtou(np, NULL, 0, 0, LONG_MAX, &e);
 			if (e) {
-				logger(ctx, LOG_ERR, "failed to convert length");
+				logger(ctx,LOG_ERR, "failed to convert length");
 				return -1;
 			}
-		} else
+		} else {
 			l = 0;
+			bp = strchr(arg, '='); /* bitflag assignment */
+			if (bp)
+				*bp++ = '\0';
+		}
 		t = 0;
 		if (strcasecmp(arg, "request") == 0) {
 			t |= REQUEST;
@@ -1593,6 +1617,8 @@ err_sla:
 			t |= STRING;
 		else if (strcasecmp(arg, "byte") == 0)
 			t |= UINT8;
+		else if (strcasecmp(arg, "bitflags") == 0)
+			t |= BITFLAG;
 		else if (strcasecmp(arg, "uint16") == 0)
 			t |= UINT16;
 		else if (strcasecmp(arg, "int16") == 0)
@@ -1640,6 +1666,11 @@ err_sla:
 			logger(ctx, LOG_WARNING, "ignoring array for strings");
 			t &= ~ARRAY;
 		}
+		if (t & BITFLAG) {
+			if (bp == NULL)
+				logger(ctx, LOG_WARNING,
+				    "missing bitflag assignment");
+		}
 		/* variable */
 		if (!fp) {
 			if (!(t & OPTION)) {
@@ -1653,10 +1684,16 @@ err_sla:
 			fp = strwhite(arg);
 			if (fp)
 				*fp++ = '\0';
-			np = strdup(arg);
-			if (np == NULL) {
-				logger(ctx, LOG_ERR, "%s: %m", __func__);
-				return -1;
+			if (strcasecmp(arg, "reserved")) {
+				np = strdup(arg);
+				if (np == NULL) {
+					logger(ctx, LOG_ERR,
+					    "%s: %m", __func__);
+					return -1;
+				}
+			} else {
+				np = NULL;
+				t |= RESERVED;
 			}
 		}
 		if (opt != O_EMBED) {
@@ -1691,11 +1728,25 @@ err_sla:
 		ndop->type = t;
 		ndop->len = (size_t)l;
 		ndop->var = np;
+		if (bp) {
+			dl = strlen(bp);
+			memcpy(ndop->bitflags, bp, dl);
+			memset(ndop->bitflags + dl, 0,
+			    sizeof(ndop->bitflags) - dl);
+		} else
+			memset(ndop->bitflags, 0, sizeof(ndop->bitflags));
 		/* Save the define for embed and encap options */
-		if (opt == O_DEFINE || opt == O_DEFINE6 || opt == O_VENDOPT)
+		switch (opt) {
+		case O_DEFINE:
+		case O_DEFINEND:
+		case O_DEFINE6:
+		case O_VENDOPT:
 			*ldop = ndop;
-		else if (opt == O_ENCAP)
+			break;
+		case O_ENCAP:
 			*edop = ndop;
+			break;
+		}
 		break;
 	case O_VENDCLASS:
 		fp = strwhite(arg);
@@ -2103,6 +2154,14 @@ read_config(struct dhcpcd_ctx *ctx,
 			ifo->dhcp_override_len = INITDEFINES;
 #endif
 
+#if defined(INET6) && defined(INITDEFINENDS)
+		ifo->nd_override =
+		    calloc(INITDEFINENDS, sizeof(*ifo->nd_override));
+		if (ifo->nd_override == NULL)
+			logger(ctx, LOG_ERR, "%s: %m", __func__);
+		else
+			ifo->nd_override_len = INITDEFINENDS;
+#endif
 #if defined(INET6) && defined(INITDEFINE6S)
 		ifo->dhcp6_override =
 		    calloc(INITDEFINE6S, sizeof(*ifo->dhcp6_override));
@@ -2175,15 +2234,24 @@ read_config(struct dhcpcd_ctx *ctx,
 		ifo->dhcp_override_len = 0;
 
 #ifdef INET6
+		ctx->nd_opts = ifo->nd_override;
+		ctx->nd_opts_len = ifo->nd_override_len;
 		ctx->dhcp6_opts = ifo->dhcp6_override;
 		ctx->dhcp6_opts_len = ifo->dhcp6_override_len;
 #else
+		for (i = 0, opt = ifo->nd_override;
+		    i < ifo->nd_override_len;
+		    i++, opt++)
+			free_dhcp_opt_embenc(opt);
+		free(ifo->nd_override);
 		for (i = 0, opt = ifo->dhcp6_override;
 		    i < ifo->dhcp6_override_len;
 		    i++, opt++)
 			free_dhcp_opt_embenc(opt);
 		free(ifo->dhcp6_override);
 #endif
+		ifo->nd_override = NULL;
+		ifo->nd_override_len = 0;
 		ifo->dhcp6_override = NULL;
 		ifo->dhcp6_override_len = 0;
 
@@ -2337,6 +2405,11 @@ free_options(struct if_options *ifo)
 		    opt++, ifo->dhcp_override_len--)
 			free_dhcp_opt_embenc(opt);
 		free(ifo->dhcp_override);
+		for (opt = ifo->nd_override;
+		    ifo->nd_override_len > 0;
+		    opt++, ifo->nd_override_len--)
+			free_dhcp_opt_embenc(opt);
+		free(ifo->nd_override);
 		for (opt = ifo->dhcp6_override;
 		    ifo->dhcp6_override_len > 0;
 		    opt++, ifo->dhcp6_override_len--)
Index: src/external/bsd/dhcpcd/dist/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.c:1.23 src/external/bsd/dhcpcd/dist/ipv6nd.c:1.24
--- src/external/bsd/dhcpcd/dist/ipv6nd.c:1.23	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6nd.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6nd.c,v 1.23 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: ipv6nd.c,v 1.24 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -157,6 +157,31 @@ static void ipv6nd_handledata(void *);
 #define IPV6_RECVPKTINFO IPV6_PKTINFO
 #endif
 
+void
+ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
+    const struct dhcp_opt *opts, size_t opts_len)
+{
+	size_t i, j;
+	const struct dhcp_opt *opt, *opt2;
+	int cols;
+
+	for (i = 0, opt = ctx->nd_opts;
+	    i < ctx->nd_opts_len; i++, opt++)
+	{
+		for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
+			if (opt2->option == opt->option)
+				break;
+		if (j == opts_len) {
+			cols = printf("%03d %s", opt->option, opt->var);
+			dhcp_print_option_encoding(opt, cols);
+		}
+	}
+	for (i = 0, opt = opts; i < opts_len; i++, opt++) {
+		cols = printf("%03d %s", opt->option, opt->var);
+		dhcp_print_option_encoding(opt, cols);
+	}
+}
+
 static int
 ipv6nd_open(struct dhcpcd_ctx *dctx)
 {
@@ -220,7 +245,7 @@ ipv6nd_open(struct dhcpcd_ctx *dctx)
 
 eexit:
 	if (ctx->nd_fd != -1) {
-		eloop_event_delete(dctx->eloop, ctx->nd_fd, 0);
+		eloop_event_delete(dctx->eloop, ctx->nd_fd);
 		close(ctx->nd_fd);
 		ctx->nd_fd = -1;
 	}
@@ -325,14 +350,16 @@ ipv6nd_expire(struct interface *ifp, uin
 	struct ra *rap;
 	struct timespec now;
 
-	get_monotonic(&now);
+	if (ifp->ctx->ipv6 == NULL)
+		return;
+
+	clock_gettime(CLOCK_MONOTONIC, &now);
 
 	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
 		if (rap->iface == ifp) {
-			rap->received = now;
+			rap->acquired = now;
 			rap->expired = seconds ? 0 : 1;
 			if (seconds) {
-				struct ra_opt *rao;
 				struct ipv6_addr *ap;
 
 				rap->lifetime = seconds;
@@ -343,9 +370,6 @@ ipv6nd_expire(struct interface *ifp, uin
 					}
 				}
 				ipv6_addaddrs(&rap->addrs);
-				TAILQ_FOREACH(rao, &rap->options, next) {
-					timespecclear(&rao->expire);
-				}
 			}
 		}
 	}
@@ -397,18 +421,6 @@ ipv6nd_neighbour(struct dhcpcd_ctx *ctx,
 	}
 }
 
-static void
-ipv6nd_free_opts(struct ra *rap)
-{
-	struct ra_opt *rao;
-
-	while ((rao = TAILQ_FIRST(&rap->options))) {
-		TAILQ_REMOVE(&rap->options, rao, next);
-		free(rao->option);
-		free(rao);
-	}
-}
-
 struct ipv6_addr *
 ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr,
     short flags)
@@ -435,19 +447,26 @@ ipv6nd_findaddr(struct dhcpcd_ctx *ctx, 
 	return NULL;
 }
 
-void ipv6nd_freedrop_ra(struct ra *rap, int drop)
+static void
+ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra)
 {
 
 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap->iface);
 	eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
-	if (!drop)
+	if (remove_ra && !drop_ra)
 		TAILQ_REMOVE(rap->iface->ctx->ipv6->ra_routers, rap, next);
-	ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
-	ipv6nd_free_opts(rap);
+	ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL);
 	free(rap->data);
 	free(rap);
 }
 
+void
+ipv6nd_freedrop_ra(struct ra *rap, int drop)
+{
+
+	ipv6nd_removefreedrop_ra(rap, 1, drop);
+}
+
 ssize_t
 ipv6nd_free(struct interface *ifp)
 {
@@ -480,7 +499,7 @@ ipv6nd_free(struct interface *ifp)
 	}
 	if (ifp == NULL) {
 		if (ctx->ipv6->nd_fd != -1) {
-			eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd, 0);
+			eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd);
 			close(ctx->ipv6->nd_fd);
 			ctx->ipv6->nd_fd = -1;
 		}
@@ -531,7 +550,6 @@ ipv6nd_scriptrun(struct ra *rap)
 {
 	int hasdns, hasaddress, pid;
 	struct ipv6_addr *ap;
-	const struct ra_opt *rao;
 
 	hasaddress = 0;
 	/* If all addresses have completed DAD run the script */
@@ -557,16 +575,7 @@ ipv6nd_scriptrun(struct ra *rap)
 	if (!(rap->iface->options->options & DHCPCD_IPV6RA_REQRDNSS))
 		hasdns = 1;
 	else {
-		hasdns = 0;
-		TAILQ_FOREACH(rao, &rap->options, next) {
-			if (rao->type == ND_OPT_RDNSS &&
-			    rao->option &&
-			    timespecisset(&rao->expire))
-			{
-				hasdns = 1;
-				break;
-			}
-		}
+		hasdns = rap->hasdns;
 	}
 
 	script_runreason(rap->iface, "ROUTERADVERT");
@@ -729,24 +738,19 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
     struct icmp6_hdr *icp, size_t len)
 {
 	struct ipv6_ctx *ctx = dctx->ipv6;
-	size_t olen, l, n;
-	ssize_t r;
+	size_t i, olen;
 	struct nd_router_advert *nd_ra;
 	struct nd_opt_prefix_info *pi;
 	struct nd_opt_mtu *mtu;
 	struct nd_opt_rdnss *rdnss;
-	struct nd_opt_dnssl *dnssl;
-	uint32_t lifetime, mtuv;
-	uint8_t *p, *op;
-	struct in6_addr addr;
+	uint32_t mtuv;
+	uint8_t *p;
 	char buf[INET6_ADDRSTRLEN];
 	const char *cbp;
 	struct ra *rap;
 	struct nd_opt_hdr *ndo;
-	struct ra_opt *rao;
 	struct ipv6_addr *ap;
-	char *opt, *opt2, *tmp;
-	struct timespec expire;
+	struct dhcp_opt *dho;
 	uint8_t new_rap, new_data;
 #ifdef IPV6_MANAGETEMPADDR
 	uint8_t new_ap;
@@ -830,7 +834,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		rap->from = ctx->from.sin6_addr;
 		strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom));
 		TAILQ_INIT(&rap->addrs);
-		TAILQ_INIT(&rap->options);
 		new_rap = 1;
 	} else
 		new_rap = 0;
@@ -846,7 +849,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		rap->data_len = len;
 	}
 
-	get_monotonic(&rap->received);
+	clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
 	rap->flags = nd_ra->nd_ra_flags_reserved;
 	if (new_rap == 0 && rap->lifetime == 0)
 		logger(ifp->ctx, LOG_WARNING, "%s: %s router available",
@@ -861,6 +864,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 		rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
 	if (rap->lifetime)
 		rap->expired = 0;
+	rap->hasdns = 0;
 
 	ipv6_settempstale(ifp);
 	TAILQ_FOREACH(ap, &rap->addrs, next) {
@@ -869,7 +873,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 
 	len -= sizeof(struct nd_router_advert);
 	p = ((uint8_t *)icp) + sizeof(struct nd_router_advert);
-	lifetime = ~0U;
 	for (; len > 0; p += olen, len -= olen) {
 		if (len < sizeof(struct nd_opt_hdr)) {
 			logger(ifp->ctx, LOG_ERR,
@@ -889,7 +892,34 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 			break;
 		}
 
-		opt = opt2 = NULL;
+		if (has_option_mask(ifp->options->rejectmasknd,
+		    ndo->nd_opt_type))
+		{
+			for (i = 0, dho = dctx->nd_opts;
+			    i < dctx->nd_opts_len;
+			    i++, dho++)
+			{
+				if (dho->option == ndo->nd_opt_type)
+					break;
+			}
+			if (dho != NULL)		
+				logger(ifp->ctx, LOG_WARNING,
+				    "%s: reject RA (option %s) from %s",
+				    ifp->name, dho->var, ctx->sfrom);
+			else
+				logger(ifp->ctx, LOG_WARNING,
+				    "%s: reject RA (option %d) from %s",
+				    ifp->name, ndo->nd_opt_type, ctx->sfrom);
+			if (new_rap)
+				ipv6nd_removefreedrop_ra(rap, 0, 0);
+			else
+				ipv6nd_free_ra(rap);
+			return;
+		}
+
+		if (has_option_mask(ifp->options->nomasknd, ndo->nd_opt_type))
+			continue;
+
 		switch (ndo->nd_opt_type) {
 		case ND_OPT_PREFIX_INFORMATION:
 			pi = (struct nd_opt_prefix_info *)(void *)ndo;
@@ -966,7 +996,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 					ap->saddr[0] = '\0';
 				}
 				ap->dadcallback = ipv6nd_dadcallback;
-				ap->created = ap->acquired = rap->received;
+				ap->created = ap->acquired = rap->acquired;
 				TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
 
 #ifdef IPV6_MANAGETEMPADDR
@@ -986,7 +1016,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 				new_ap = 0;
 #endif
 				ap->flags &= ~IPV6_AF_STALE;
-				ap->acquired = rap->received;
+				ap->acquired = rap->acquired;
 			}
 			if (pi->nd_opt_pi_flags_reserved &
 			    ND_OPT_PI_FLAG_ONLINK)
@@ -996,16 +1026,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 			ap->prefix_pltime =
 			    ntohl(pi->nd_opt_pi_preferred_time);
 			ap->nsprobes = 0;
-			cbp = inet_ntop(AF_INET6, &ap->prefix, buf, sizeof(buf));
-			if (cbp) {
-				l = strlen(cbp);
-				opt = malloc(l + 5);
-				if (opt) {
-					snprintf(opt, l + 5, "%s/%d", cbp,
-					    ap->prefix_len);
-					opt2 = strdup(ap->saddr);
-				}
-			}
 
 #ifdef IPV6_MANAGETEMPADDR
 			/* RFC4941 Section 3.3.3 */
@@ -1025,8 +1045,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 				}
 			}
 #endif
-
-			lifetime = ap->prefix_vltime;
 			break;
 
 		case ND_OPT_MTU:
@@ -1038,140 +1056,40 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx,
 				break;
 			}
 			rap->mtu = mtuv;
-			snprintf(buf, sizeof(buf), "%d", mtuv);
-			opt = strdup(buf);
 			break;
 
 		case ND_OPT_RDNSS:
-			rdnss = (struct nd_opt_rdnss *)p;
-			lifetime = ntohl(rdnss->nd_opt_rdnss_lifetime);
-			op = (uint8_t *)ndo;
-			op += offsetof(struct nd_opt_rdnss,
-			    nd_opt_rdnss_lifetime);
-			op += sizeof(rdnss->nd_opt_rdnss_lifetime);
-			l = 0;
-			for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2,
-			    op += sizeof(addr))
-			{
-				r = ipv6_printaddr(NULL, 0, op, ifp->name);
-				if (r != -1)
-					l += (size_t)r + 1;
-			}
-			op = (uint8_t *)ndo;
-			op += offsetof(struct nd_opt_rdnss,
-			    nd_opt_rdnss_lifetime);
-			op += sizeof(rdnss->nd_opt_rdnss_lifetime);
-			tmp = opt = malloc(l);
-			if (opt == NULL)
-				continue;
-			for (n = (size_t)ndo->nd_opt_len - 1; n > 1; n -= 2,
-			    op += sizeof(addr))
-			{
-				r = ipv6_printaddr(tmp, l, op,
-				    ifp->name);
-				if (r != -1) {
-					l -= ((size_t)r + 1);
-					tmp += (size_t)r;
-					*tmp++ = ' ';
-				}
-			}
-			if (tmp != opt)
-				(*--tmp) = '\0';
-			else
-				*opt = '\0';
-			break;
-
-		case ND_OPT_DNSSL:
-			dnssl = (struct nd_opt_dnssl *)p;
-			lifetime = ntohl(dnssl->nd_opt_dnssl_lifetime);
-			op = p + offsetof(struct nd_opt_dnssl,
-			    nd_opt_dnssl_lifetime);
-			op += sizeof(dnssl->nd_opt_dnssl_lifetime);
-			n = (size_t)(dnssl->nd_opt_dnssl_len - 1) * 8;
-			r = decode_rfc3397(NULL, 0, op, n);
-			if (r < 1) {
-				logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG,
-				    "%s: invalid DNSSL option",
-				    ifp->name);
-				continue;
-			} else {
-				l = (size_t)r + 1;
-				tmp = malloc(l);
-				if (tmp) {
-					decode_rfc3397(tmp, l, op, n);
-					l -= 1;
-					n = (size_t)print_string(NULL, 0,
-					    STRING | ARRAY | DOMAIN,
-					    (const uint8_t *)tmp, l);
-					n++;
-					opt = malloc(n);
-					if (opt) {
-						print_string(opt, n,
-						    STRING | ARRAY | DOMAIN,
-						    (const uint8_t *)tmp, l);
-					} else
-						logger(ifp->ctx, LOG_ERR,
-						    "%s: %m", __func__);
-					free(tmp);
-				}
-			}
-			break;
+			rdnss = (struct nd_opt_rdnss *)(void *)p;
+			if (rdnss->nd_opt_rdnss_lifetime &&
+			    rdnss->nd_opt_rdnss_len > 1)
+				rap->hasdns = 1;
 
 		default:
 			continue;
 		}
+	}
 
-		if (opt == NULL) {
-			logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
-			continue;
-		}
-
-		n = ndo->nd_opt_type;
-extra_opt:
-		TAILQ_FOREACH(rao, &rap->options, next) {
-			if (rao->type == n &&
-			    strcmp(rao->option, opt) == 0)
-				break;
-		}
-		if (lifetime == 0 || *opt == '\0') {
-			if (rao) {
-				TAILQ_REMOVE(&rap->options, rao, next);
-				free(rao->option);
-				free(rao);
-			}
-			free(opt);
-			free(opt2);
-			continue;
-		}
-
-		if (rao == NULL) {
-			rao = malloc(sizeof(*rao));
-			if (rao == NULL) {
-				logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
-				continue;
-			}
-			rao->type = (uint16_t)n;
-			rao->option = opt;
-			TAILQ_INSERT_TAIL(&rap->options, rao, next);
-		} else
-			free(opt);
-		if (lifetime == ~0U)
-			timespecclear(&rao->expire);
-		else {
-			expire.tv_sec = (time_t)lifetime;
-			expire.tv_nsec = 0;
-			timespecadd(&rap->received, &expire, &rao->expire);
-		}
-		if (rao && rao->type == ND_OPT_PREFIX_INFORMATION && opt2) {
-			n = _ND_OPT_PREFIX_ADDR;
-			opt = opt2;
-			opt2 = NULL;
-			goto extra_opt;
+	for (i = 0, dho = dctx->nd_opts;
+	    i < dctx->nd_opts_len;
+	    i++, dho++)
+	{
+		if (has_option_mask(ifp->options->requiremasknd,
+		    dho->option))
+		{
+			logger(ifp->ctx, LOG_WARNING,
+			    "%s: reject RA (no option %s) from %s",
+			    ifp->name, dho->var, ctx->sfrom);
+			if (new_rap)
+				ipv6nd_removefreedrop_ra(rap, 0, 0);
+			else
+				ipv6nd_free_ra(rap);
+			return;
 		}
 	}
 
 	if (new_rap)
 		add_router(ifp->ctx->ipv6, rap);
+
 	if (!ipv6nd_ra_has_public_addr(rap) &&
 	    !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
 	    (!(rap->flags & ND_RA_FLAG_MANAGED) ||
@@ -1191,7 +1109,7 @@ extra_opt:
 	}
 	ipv6_addaddrs(&rap->addrs);
 #ifdef IPV6_MANAGETEMPADDR
-	ipv6_addtempaddrs(ifp, &rap->received);
+	ipv6_addtempaddrs(ifp, &rap->acquired);
 #endif
 
 	/* Find any freshly added routes, such as the subnet route.
@@ -1289,119 +1207,155 @@ ipv6nd_hasradhcp(const struct interface 
 	return 0;
 }
 
+static const uint8_t *
+ipv6nd_getoption(struct dhcpcd_ctx *ctx,
+    size_t *os, unsigned int *code, size_t *len,
+    const uint8_t *od, size_t ol, struct dhcp_opt **oopt)
+{
+	const struct nd_opt_hdr *o;
+	size_t i;
+	struct dhcp_opt *opt;
+
+	if (od) {
+		*os = sizeof(*o);
+		if (ol < *os) {
+			errno = EINVAL;
+			return NULL;
+		}
+		o = (const struct nd_opt_hdr *)od;
+		if (o->nd_opt_len > ol) {
+			errno = EINVAL;
+			return NULL;
+		}
+		*len = ND_OPTION_LEN(o);
+		*code = o->nd_opt_type;
+	} else
+		o = NULL;
+
+	for (i = 0, opt = ctx->nd_opts;
+	    i < ctx->nd_opts_len; i++, opt++)
+	{
+		if (opt->option == *code) {
+			*oopt = opt;
+			break;
+		}
+	}
+
+	if (o)
+		return ND_COPTION_DATA(o);
+	return NULL;
+}
+
 ssize_t
 ipv6nd_env(char **env, const char *prefix, const struct interface *ifp)
 {
-	size_t i, l, len;
-	const struct ra *rap;
-	const struct ra_opt *rao;
-	char buffer[32];
-	const char *optn;
-	char **pref, **addr, **mtu, **rdnss, **dnssl, ***var, *new;
+	size_t i, j, n, len;
+	struct ra *rap;
+	char ndprefix[32], abuf[24];
+	struct dhcp_opt *opt;
+	const struct nd_opt_hdr *o;
+	struct ipv6_addr *ia;
+	struct timespec now;
 
-	i = l = 0;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	i = n = 0;
 	TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
 		if (rap->iface != ifp)
 			continue;
 		i++;
+		if (prefix != NULL)
+			snprintf(ndprefix, sizeof(ndprefix),
+			    "%s_nd%zu", prefix, i);
+		else
+			snprintf(ndprefix, sizeof(ndprefix),
+			    "nd%zu", i);
+		if (env)
+			setvar(rap->iface->ctx, &env[n], ndprefix,
+			    "from", rap->sfrom);
+		n++;
+		if (env)
+			setvard(rap->iface->ctx, &env[n], ndprefix,
+			    "acquired", (size_t)rap->acquired.tv_sec);
+		n++;
+		if (env)
+			setvard(rap->iface->ctx, &env[n], ndprefix,
+			    "now", (size_t)now.tv_sec);
+		n++;
+
+		/* Zero our indexes */
 		if (env) {
-			snprintf(buffer, sizeof(buffer),
-			    "ra%zu_from", i);
-			setvar(ifp->ctx, &env, prefix, buffer, rap->sfrom);
-		}
-		l++;
-
-		pref = addr = mtu = rdnss = dnssl = NULL;
-		TAILQ_FOREACH(rao, &rap->options, next) {
-			if (rao->option == NULL)
-				continue;
-			var = NULL;
-			switch(rao->type) {
-			case ND_OPT_PREFIX_INFORMATION:
-				optn = "prefix";
-				var = &pref;
-				break;
-			case _ND_OPT_PREFIX_ADDR:
-				optn = "addr";
-				var = &addr;
-				break;
-			case ND_OPT_MTU:
-				optn = "mtu";
-				var = &mtu;
-				break;
-			case ND_OPT_RDNSS:
-				optn = "rdnss";
-				var = &rdnss;
-				break;
-			case ND_OPT_DNSSL:
-				optn = "dnssl";
-				var = &dnssl;
+			for (j = 0, opt = rap->iface->ctx->nd_opts;
+			    j < rap->iface->ctx->nd_opts_len;
+			    j++, opt++)
+				dhcp_zero_index(opt);
+			for (j = 0, opt = rap->iface->options->nd_override;
+			    j < rap->iface->options->nd_override_len;
+			    j++, opt++)
+				dhcp_zero_index(opt);
+		}
+
+		/* Unlike DHCP, ND6 options *may* occur more than once.
+		 * There is also no provision for option concatenation
+		 * unlike DHCP. */
+		len = rap->data_len -
+		    ((size_t)((const uint8_t *)ND_CFIRST_OPTION(rap) -
+		    rap->data));
+
+		for (o = ND_CFIRST_OPTION(rap);
+		    len >= (ssize_t)sizeof(*o);
+		    o = ND_CNEXT_OPTION(o))
+		{
+			if ((size_t)o->nd_opt_len * 8 > len) {
+				errno =	EINVAL;
 				break;
-			default:
-				continue;
 			}
-			if (*var == NULL) {
-				*var = env ? env : &new;
-				l++;
-			} else if (env) {
-				/* With single only options, last one takes
-				 * precedence */
-				if (rao->type == ND_OPT_MTU) {
-					new = strchr(**var, '=');
-					if (new == NULL) {
-						logger(ifp->ctx, LOG_ERR,
-						    "new is null");
-						continue;
-					} else
-						new++;
-					len = (size_t)(new - **var) +
-					    strlen(rao->option) + 1;
-					if (len > strlen(**var))
-						new = realloc(**var, len);
-					else
-						new = **var;
-					if (new) {
-						**var = new;
-						new = strchr(**var, '=');
-						if (new) {
-							len -=
-							    (size_t)
-							    (new - **var);
-							strlcpy(new + 1,
-							    rao->option,
-							    len - 1);
-						} else
-							logger(ifp->ctx,
-							    LOG_ERR,
-							    "new is null");
-					}
-					continue;
-				}
-				len = strlen(rao->option) + 1;
-				new = realloc(**var, strlen(**var) + 1 + len);
-				if (new) {
-					**var = new;
-					new += strlen(new);
-					*new++ = ' ';
-					strlcpy(new, rao->option, len);
-				} else
-					logger(ifp->ctx, LOG_ERR,
-					    "%s: %m", __func__);
+			len -= (size_t)(o->nd_opt_len * 8);
+			if (has_option_mask(rap->iface->options->nomasknd,
+			    o->nd_opt_type))
 				continue;
+			for (j = 0, opt = rap->iface->options->nd_override;
+			    j < rap->iface->options->nd_override_len;
+			    j++, opt++)
+				if (opt->option == o->nd_opt_type)
+					break;
+			if (j == rap->iface->options->nd_override_len) {
+				for (j = 0, opt = rap->iface->ctx->nd_opts;
+				    j < rap->iface->ctx->nd_opts_len;
+				    j++, opt++)
+					if (opt->option == o->nd_opt_type)
+						break;
+				if (j == rap->iface->ctx->nd_opts_len)
+					opt = NULL;
 			}
+			if (opt) {
+				n += dhcp_envoption(rap->iface->ctx,
+				    env == NULL ? NULL : &env[n],
+				    ndprefix, rap->iface->name,
+				    opt, ipv6nd_getoption,
+				    ND_COPTION_DATA(o), ND_OPTION_LEN(o));
+			}
+		}
+
+		/* We need to output the addresses we actually made
+		 * from the prefix information options as well. */
+		j = 0;
+		TAILQ_FOREACH(ia, &rap->addrs, next) {
+			if (!(ia->flags & IPV6_AF_AUTOCONF)
+#ifdef IPV6_AF_TEMPORARY
+			    || ia->flags & IPV6_AF_TEMPORARY
+#endif
+			    )
+				continue;
+			j++;
 			if (env) {
-				snprintf(buffer, sizeof(buffer),
-				    "ra%zu_%s", i, optn);
-				setvar(ifp->ctx, &env,
-				    prefix, buffer, rao->option);
+				snprintf(abuf, sizeof(abuf), "addr%zu", j);
+				setvar(rap->iface->ctx, &env[n], ndprefix,
+				    abuf, ia->saddr);
 			}
+			n++;
 		}
 	}
-
-	if (env)
-		setvard(ifp->ctx, &env, prefix, "ra_count", i);
-	l++;
-	return (ssize_t)l;
+	return (ssize_t)n;
 }
 
 void
@@ -1424,12 +1378,11 @@ ipv6nd_expirera(void *arg)
 {
 	struct interface *ifp;
 	struct ra *rap, *ran;
-	struct ra_opt *rao, *raon;
 	struct timespec now, lt, expire, next;
 	uint8_t expired, valid, validone;
 
 	ifp = arg;
-	get_monotonic(&now);
+	clock_gettime(CLOCK_MONOTONIC, &now);
 	expired = 0;
 	timespecclear(&next);
 
@@ -1441,7 +1394,7 @@ ipv6nd_expirera(void *arg)
 		if (rap->lifetime) {
 			lt.tv_sec = (time_t)rap->lifetime;
 			lt.tv_nsec = 0;
-			timespecadd(&rap->received, &lt, &expire);
+			timespecadd(&rap->acquired, &lt, &expire);
 			if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
 			{
 				if (!rap->expired) {
@@ -1460,43 +1413,10 @@ ipv6nd_expirera(void *arg)
 			}
 		}
 
-		/* Addresses are expired in ipv6_addaddrs
-		 * so that DHCPv6 addresses can be removed also. */
-		TAILQ_FOREACH_SAFE(rao, &rap->options, next, raon) {
-			if (rap->expired) {
-				switch(rao->type) {
-				case ND_OPT_RDNSS: /* FALLTHROUGH */
-				case ND_OPT_DNSSL:
-					/* RFC6018 end of section 5.2 states
-					 * that if tha RA has a lifetime of 0
-					 * then we should expire these
-					 * options */
-					TAILQ_REMOVE(&rap->options, rao, next);
-					expired = 1;
-					free(rao->option);
-					free(rao);
-					continue;
-				}
-			}
-			if (!timespecisset(&rao->expire))
-				continue;
-			if (timespeccmp(&now, &rao->expire, >)) {
-				/* Expired prefixes are logged above */
-				if (rao->type != ND_OPT_PREFIX_INFORMATION)
-					logger(ifp->ctx, LOG_WARNING,
-					    "%s: %s: expired option %d",
-					    ifp->name, rap->sfrom, rao->type);
-				TAILQ_REMOVE(&rap->options, rao, next);
-				expired = 1;
-				free(rao->option);
-				free(rao);
-				continue;
-			}
-			valid = 1;
-			timespecsub(&rao->expire, &now, &lt);
-			if (!timespecisset(&next) || timespeccmp(&next, &lt, >))
-				next = lt;
-		}
+		/* XXX FixMe!
+		 * We need to extract the lifetime from each option and check
+		 * if that has expired or not.
+		 * If it has, zero the option out in the returned data. */
 
 		/* No valid lifetimes are left on the RA, so we might
 		 * as well punt it. */
@@ -1646,7 +1566,7 @@ ipv6nd_handledata(void *arg)
 	len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0);
 	if (len == -1) {
 		logger(dctx, LOG_ERR, "recvmsg: %m");
-		eloop_event_delete(dctx->eloop, ctx->nd_fd, 0);
+		eloop_event_delete(dctx->eloop, ctx->nd_fd);
 		close(ctx->nd_fd);
 		ctx->nd_fd = -1;
 		return;

Index: src/external/bsd/dhcpcd/dist/ipv4.c
diff -u src/external/bsd/dhcpcd/dist/ipv4.c:1.14 src/external/bsd/dhcpcd/dist/ipv4.c:1.15
--- src/external/bsd/dhcpcd/dist/ipv4.c:1.14	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv4.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv4.c,v 1.14 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: ipv4.c,v 1.15 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -35,6 +35,7 @@
 #include <arpa/inet.h>
 #include <net/route.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -159,6 +160,15 @@ ipv4_findaddr(struct dhcpcd_ctx *ctx, co
 }
 
 int
+ipv4_ifaddrexists(const struct interface *ifp)
+{
+	const struct dhcp_state *state;
+
+	state = D_CSTATE(ifp);
+	return (state && state->addr.s_addr != INADDR_ANY);
+}
+
+int
 ipv4_addrexists(struct dhcpcd_ctx *ctx, const struct in_addr *addr)
 {
 	struct interface *ifp;
@@ -744,6 +754,7 @@ ipv4_deladdr(struct interface *ifp,
 	int r;
 	struct ipv4_state *state;
 	struct ipv4_addr *ap;
+	struct arp_state *astate;
 
 	logger(ifp->ctx, LOG_DEBUG, "%s: deleting IP address %s/%d",
 	    ifp->name, inet_ntoa(*addr), inet_ntocidr(*net));
@@ -753,14 +764,8 @@ ipv4_deladdr(struct interface *ifp,
 	    errno != ENODEV)
 		logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
 
-	dstate = D_STATE(ifp);
-	if (dstate->addr.s_addr == addr->s_addr &&
-	    dstate->net.s_addr == net->s_addr)
-	{
-		dstate->added = 0;
-		dstate->addr.s_addr = 0;
-		dstate->net.s_addr = 0;
-	}
+	if ((astate = arp_find(ifp, addr)) != NULL)
+		arp_free(astate);
 
 	state = IPV4_STATE(ifp);
 	TAILQ_FOREACH(ap, &state->addrs, next) {
@@ -772,6 +777,18 @@ ipv4_deladdr(struct interface *ifp,
 			break;
 		}
 	}
+
+	/* Have to do this last incase the function arguments
+	 * were these very pointers. */
+	dstate = D_STATE(ifp);
+	if (dstate &&
+	    dstate->addr.s_addr == addr->s_addr &&
+	    dstate->net.s_addr == net->s_addr)
+	{
+		dstate->added = 0;
+		dstate->addr.s_addr = 0;
+		dstate->net.s_addr = 0;
+	}
 	return r;
 }
 
@@ -815,6 +832,7 @@ ipv4_addaddr(struct interface *ifp, cons
 {
 	struct ipv4_state *state;
 	struct ipv4_addr *ia;
+	struct dhcp_state *dstate;
 
 	if ((state = ipv4_getstate(ifp)) == NULL) {
 		logger(ifp->ctx, LOG_ERR, "%s: ipv4_getstate: %m", __func__);
@@ -852,6 +870,17 @@ ipv4_addaddr(struct interface *ifp, cons
 	ia->addr_flags = IN_IFF_TENTATIVE;
 #endif
 	TAILQ_INSERT_TAIL(&state->addrs, ia, next);
+
+	dstate = D_STATE(ifp);
+#ifdef IN_IFF_TENTATIVE
+	dstate->added |= STATE_ADDED;
+#else
+	dstate->added = STATE_ADDED;
+#endif
+	dstate->defend = 0;
+	dstate->addr.s_addr = lease->addr.s_addr;
+	dstate->net.s_addr = lease->net.s_addr;
+
 	return 0;
 }
 
@@ -860,6 +889,8 @@ ipv4_finalisert(struct interface *ifp)
 {
 	const struct dhcp_state *state = D_CSTATE(ifp);
 
+	assert(state != NULL);
+
 	/* Find any freshly added routes, such as the subnet route.
 	 * We do this because we cannot rely on recieving the kernel
 	 * notification right now via our link socket. */
@@ -884,13 +915,48 @@ ipv4_finaliseaddr(struct interface *ifp)
 	    ipv4_iffindaddr(ifp, &lease->addr, NULL))
 		delete_address(ifp);
 
-	state->added = STATE_ADDED;
-	state->defend = 0;
-	state->addr.s_addr = lease->addr.s_addr;
-	state->net.s_addr = lease->net.s_addr;
+	state->added &= (uint8_t)~(STATE_FAKE | STATE_TENTATIVE);
 	ipv4_finalisert(ifp);
 }
 
+int
+ipv4_preferanother(struct interface *ifp)
+{
+	struct dhcp_state *state = D_STATE(ifp), *nstate;
+	struct interface *ifn;
+	int preferred;
+
+	if (state == NULL)
+		return 0;
+
+	preferred = 0;
+	if (!state->added)
+		goto out;
+
+	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
+		if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0)
+			break; /* We are already the most preferred */
+		nstate = D_STATE(ifn);
+		if (nstate && !nstate->added &&
+		    nstate->lease.addr.s_addr == state->addr.s_addr)
+		{
+			preferred = 1;
+			delete_address(ifp);
+			if (ifn->options->options & DHCPCD_ARP)
+				dhcp_bind(ifn, NULL);
+			else {
+				ipv4_addaddr(ifn, &nstate->lease);
+				nstate->added = STATE_ADDED;
+			}
+			break;
+		}
+	}
+
+out:
+	ipv4_buildroutes(ifp->ctx);
+	return preferred;
+}
+
 void
 ipv4_applyaddr(void *arg)
 {
@@ -907,38 +973,15 @@ ipv4_applyaddr(void *arg)
 	dhcp = state->new;
 	lease = &state->lease;
 
+	if_sortinterfaces(ifp->ctx);
 	if (dhcp == NULL) {
 		if ((ifo->options & (DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
 		    (DHCPCD_EXITING | DHCPCD_PERSISTENT))
 		{
-			if (state->added) {
-				struct in_addr addr;
-
-				addr = state->addr;
+			if (state->added && !ipv4_preferanother(ifp)) {
 				delete_address(ifp);
-				TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
-					if (ifn == ifp ||
-					    strcmp(ifn->name, ifp->name) == 0)
-						continue;
-					nstate = D_STATE(ifn);
-					if (nstate && !nstate->added &&
-					    nstate->addr.s_addr == addr.s_addr)
-					{
-						if (ifn->options->options &
-						    DHCPCD_ARP)
-						{
-							dhcp_bind(ifn, NULL);
-						} else {
-							ipv4_addaddr(ifn,
-							    &nstate->lease);
-							nstate->added =
-							    STATE_ADDED;
-						}
-						break;
-					}
-				}
+				ipv4_buildroutes(ifp->ctx);
 			}
-			ipv4_buildroutes(ifp->ctx);
 			script_runreason(ifp, state->reason);
 		} else
 			ipv4_buildroutes(ifp->ctx);
@@ -946,29 +989,30 @@ ipv4_applyaddr(void *arg)
 	}
 
 	/* Ensure only one interface has the address */
+	r = 0;
 	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
-		if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0)
+		if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0) {
+			r = 1; /* past ourselves */
 			continue;
+		}
 		nstate = D_STATE(ifn);
 		if (nstate && nstate->added &&
 		    nstate->addr.s_addr == lease->addr.s_addr)
 		{
-			if (ifn->metric <= ifp->metric) {
+			if (r == 0) {
 				logger(ifp->ctx, LOG_INFO,
 				    "%s: preferring %s on %s",
 				    ifp->name,
 				    inet_ntoa(lease->addr),
 				    ifn->name);
-				state->addr.s_addr = lease->addr.s_addr;
-				state->net.s_addr = lease->net.s_addr;
-				ipv4_finalisert(ifp);
+				state->added &= (uint8_t)~STATE_TENTATIVE;
+				return;
 			}
 			logger(ifp->ctx, LOG_INFO, "%s: preferring %s on %s",
 			    ifn->name,
 			    inet_ntoa(lease->addr),
 			    ifp->name);
 			ipv4_deladdr(ifn, &nstate->addr, &nstate->net);
-			nstate->added = 0;
 			break;
 		}
 	}

Index: src/external/bsd/dhcpcd/dist/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/ipv6.c:1.11 src/external/bsd/dhcpcd/dist/ipv6.c:1.12
--- src/external/bsd/dhcpcd/dist/ipv6.c:1.11	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: ipv6.c,v 1.11 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: ipv6.c,v 1.12 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -38,19 +38,6 @@
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 
-#ifndef __linux__
-#  ifndef __QNX__
-#    include <sys/endian.h>
-#  endif
-#  include <net/if.h>
-#  ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
-#    include <net/if_var.h>
-#  endif
-#  ifndef __sun
-#    include <netinet6/in6_var.h>
-#  endif
-#endif
-
 #include <errno.h>
 #include <ifaddrs.h>
 #include <inttypes.h>
@@ -688,24 +675,36 @@ ipv6_addaddr(struct ipv6_addr *ap, const
 		struct timespec n;
 
 		if (now == NULL) {
-			get_monotonic(&n);
+			clock_gettime(CLOCK_MONOTONIC, &n);
 			now = &n;
 		}
 		timespecsub(now, &ap->acquired, &n);
-		if (ap->prefix_pltime != ND6_INFINITE_LIFETIME)
+		if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) {
 			ap->prefix_pltime -= (uint32_t)n.tv_sec;
+			/* This can happen when confirming a
+			 * deprecated but still valid lease. */
+			if (ap->prefix_pltime > pltime)
+				ap->prefix_pltime = 0;
+		}
 		if (ap->prefix_vltime != ND6_INFINITE_LIFETIME)
 			ap->prefix_vltime -= (uint32_t)n.tv_sec;
-	}
 
-	if (if_addaddress6(ap) == -1) {
-		logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
 #if 0
 		logger(ap->iface->ctx, LOG_DEBUG,
+		    "%s: acquired %lld.%.9ld, now %lld.%.9ld, diff %lld.%.9ld",
+		    ap->iface->name,
+		    (long long)ap->acquired.tv_sec, ap->acquired.tv_nsec,
+		    (long long)now->tv_sec, now->tv_nsec,
+		    (long long)n.tv_sec, n.tv_nsec);
+		logger(ap->iface->ctx, LOG_DEBUG,
 		    "%s: adj pltime %"PRIu32" seconds, "
 		    "vltime %"PRIu32" seconds",
 		    ap->iface->name, ap->prefix_pltime, ap->prefix_vltime);
 #endif
+	}
+
+	if (if_addaddress6(ap) == -1) {
+		logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
 		/* Restore real pltime and vltime */
 		ap->prefix_pltime = pltime;
 		ap->prefix_vltime = vltime;
@@ -829,7 +828,7 @@ ipv6_addaddrs(struct ipv6_addrhead *addr
 			if (ap->flags & IPV6_AF_NEW)
 				i++;
 			if (!timespecisset(&now))
-				get_monotonic(&now);
+				clock_gettime(CLOCK_MONOTONIC, &now);
 			ipv6_addaddr(ap, &now);
 		}
 	}
@@ -875,7 +874,7 @@ ipv6_freedrop_addrs(struct ipv6_addrhead
 			    DHCPCD_EXITING) && apf)
 			{
 				if (!timespecisset(&now))
-					get_monotonic(&now);
+					clock_gettime(CLOCK_MONOTONIC, &now);
 				ipv6_addaddr(apf, &now);
 			}
 			if (drop == 2)
@@ -1466,7 +1465,7 @@ ipv6_tempdadcallback(void *arg)
 			    ia->iface->name);
 			return;
 		}
-		get_monotonic(&tv);
+		clock_gettime(CLOCK_MONOTONIC, &tv);
 		if ((ia1 = ipv6_createtempaddr(ia, &tv)) == NULL)
 			logger(ia->iface->ctx, LOG_ERR,
 			    "ipv6_createtempaddr: %m");
@@ -1571,9 +1570,7 @@ again:
 	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';
+		    cbp, ia->prefix_len); else ia->saddr[0] = '\0';
 
 	TAILQ_INSERT_TAIL(&state->addrs, ia, next);
 	return ia;
@@ -1692,7 +1689,7 @@ ipv6_regentempaddr(void *arg)
 
 	logger(ia->iface->ctx, LOG_DEBUG, "%s: regen temp addr %s",
 	    ia->iface->name, ia->saddr);
-	get_monotonic(&tv);
+	clock_gettime(CLOCK_MONOTONIC, &tv);
 	ia1 = ipv6_createtempaddr(ia, &tv);
 	if (ia1)
 		ipv6_addaddr(ia1, &tv);
Index: src/external/bsd/dhcpcd/dist/ipv6nd.h
diff -u src/external/bsd/dhcpcd/dist/ipv6nd.h:1.11 src/external/bsd/dhcpcd/dist/ipv6nd.h:1.12
--- src/external/bsd/dhcpcd/dist/ipv6nd.h:1.11	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/ipv6nd.h	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: ipv6nd.h,v 1.11 2015/05/02 15:18:37 roy Exp $ */
+/* $NetBSD: ipv6nd.h,v 1.12 2015/05/16 23:31:32 roy Exp $ */
 
 /*
  * dhcpcd - DHCP client daemon
@@ -36,13 +36,6 @@
 #include "dhcpcd.h"
 #include "ipv6.h"
 
-struct ra_opt {
-	TAILQ_ENTRY(ra_opt) next;
-	uint16_t type;
-	struct timespec expire;
-	char *option;
-};
-
 struct ra {
 	TAILQ_ENTRY(ra) next;
 	struct interface *iface;
@@ -50,14 +43,14 @@ struct ra {
 	char sfrom[INET6_ADDRSTRLEN];
 	unsigned char *data;
 	size_t data_len;
-	struct timespec received;
+	struct timespec acquired;
 	unsigned char flags;
 	uint32_t lifetime;
 	uint32_t reachable;
 	uint32_t retrans;
 	uint32_t mtu;
 	struct ipv6_addrhead addrs;
-	TAILQ_HEAD(, ra_opt) options;
+	uint8_t hasdns;
 	uint8_t expired;
 	uint8_t no_public_warned;
 };
@@ -73,6 +66,17 @@ struct rs_state {
 #define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND])
 #define RS_STATE_RUNNING(a) (ipv6nd_hasra((a)) && ipv6nd_dadcompleted((a)))
 
+#define ND_CFIRST_OPTION(m)						       \
+    ((const struct nd_opt_hdr *)					       \
+        ((const uint8_t *)(m)->data + sizeof(struct nd_router_advert)))
+#define ND_OPTION_LEN(o) ((size_t)((o)->nd_opt_len * 8) -		       \
+    sizeof(struct nd_opt_hdr))
+#define ND_CNEXT_OPTION(o)						       \
+    ((const struct nd_opt_hdr *)((const uint8_t *)(o) +			       \
+    (size_t)((o)->nd_opt_len * 8)))
+#define ND_COPTION_DATA(o)						       \
+    ((const uint8_t *)(o) + sizeof(struct nd_opt_hdr))
+
 #define MAX_RTR_SOLICITATION_DELAY	1	/* seconds */
 #define MAX_UNICAST_SOLICIT		3	/* 3 transmissions */
 #define RTR_SOLICITATION_INTERVAL	4	/* seconds */
@@ -93,6 +97,8 @@ struct rs_state {
 #define IPV6ND_ROUTER			(1 << 1)
 
 #ifdef INET6
+void ipv6nd_printoptions(const struct dhcpcd_ctx *,
+    const struct dhcp_opt *, size_t);
 void ipv6nd_startrs(struct interface *);
 ssize_t ipv6nd_env(char **, const char *, const struct interface *);
 struct ipv6_addr *ipv6nd_findaddr(struct dhcpcd_ctx *,
@@ -113,7 +119,6 @@ void ipv6nd_drop(struct interface *);
 void ipv6nd_neighbour(struct dhcpcd_ctx *, struct in6_addr *, int);
 #else
 #define ipv6nd_startrs(a) {}
-#define ipv6nd_findaddr(a, b, c) (0)
 #define ipv6nd_free(a) {}
 #define ipv6nd_hasra(a) (0)
 #define ipv6nd_dadcompleted(a) (0)

Index: src/external/bsd/dhcpcd/dist/script.c
diff -u src/external/bsd/dhcpcd/dist/script.c:1.19 src/external/bsd/dhcpcd/dist/script.c:1.20
--- src/external/bsd/dhcpcd/dist/script.c:1.19	Sat May  2 15:18:37 2015
+++ src/external/bsd/dhcpcd/dist/script.c	Sat May 16 23:31:32 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
- __RCSID("$NetBSD: script.c,v 1.19 2015/05/02 15:18:37 roy Exp $");
+ __RCSID("$NetBSD: script.c,v 1.20 2015/05/16 23:31:32 roy Exp $");
 
 /*
  * dhcpcd - DHCP client daemon
@@ -94,8 +94,9 @@ exec_script(const struct dhcpcd_ctx *ctx
 {
 	pid_t pid;
 	posix_spawnattr_t attr;
-	int i;
+	int r;
 #ifdef USE_SIGNALS
+	size_t i;
 	short flags;
 	sigset_t defsigs;
 #else
@@ -110,15 +111,15 @@ exec_script(const struct dhcpcd_ctx *ctx
 	flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
 	posix_spawnattr_setflags(&attr, flags);
 	sigemptyset(&defsigs);
-	for (i = 0; dhcpcd_handlesigs[i]; i++)
-		sigaddset(&defsigs, dhcpcd_handlesigs[i]);
+	for (i = 0; i < dhcpcd_signals_len; i++)
+		sigaddset(&defsigs, dhcpcd_signals[i]);
 	posix_spawnattr_setsigdefault(&attr, &defsigs);
 	posix_spawnattr_setsigmask(&attr, &ctx->sigset);
 #endif
 	errno = 0;
-	i = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
-	if (i) {
-		errno = i;
+	r = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
+	if (r) {
+		errno = r;
 		return -1;
 	}
 	return pid;
@@ -287,7 +288,7 @@ make_env(const struct interface *ifp, co
 	if (ifp->ctx->options & DHCPCD_DUMPLEASE)
 		elen = 2;
 	else
-		elen = 13;
+		elen = 12;
 
 #define EMALLOC(i, l) if ((env[(i)] = malloc((l))) == NULL) goto eexit;
 	/* Make our env + space for profile, wireless and debug */
@@ -374,12 +375,6 @@ make_env(const struct interface *ifp, co
 		env[11] = strdup("if_oneup=false");
 	if (env[11] == NULL)
 		goto eexit;
-	if (dhcpcd_ipwaited(ifp->ctx))
-		env[12] = strdup("if_ipwaited=true");
-	else
-		env[12] = strdup("if_ipwaited=false");
-	if (env[12] == NULL)
-		goto eexit;
 	if (ifo->options & DHCPCD_DEBUG) {
 		e = strlen("syslog_debug=true") + 1;
 		EMALLOC(elen, e);

Index: src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf
diff -u src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.6 src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.7
--- src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf:1.6	Fri Nov  7 20:51:03 2014
+++ src/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf	Sat May 16 23:31:32 2015
@@ -1,4 +1,4 @@
-# $NetBSD: 20-resolv.conf,v 1.6 2014/11/07 20:51:03 roy Exp $
+# $NetBSD: 20-resolv.conf,v 1.7 2015/05/16 23:31:32 roy Exp $
 
 # Generate /etc/resolv.conf
 # Support resolvconf(8) if available
@@ -70,17 +70,54 @@ build_resolv_conf()
 	rm -f "$cf"
 }
 
+# Extract any ND DNS options from the RA
+# For now, we ignore the lifetime of the DNS options unless they
+# are absent or zero.
+# In this case they are removed from consideration.
+# See draft-gont-6man-slaac-dns-config-issues-01 for issues
+# regarding DNS option lifetime in ND messages.
+eval_nd_dns()
+{
+
+	eval ltime=\$nd${i}_rdnss${j}_lifetime
+	if [ -z "$ltime" -o "$ltime" = 0 ]; then
+		rdnss=
+	else
+		eval rdnss=\$nd${i}_rdnss${j}_servers
+	fi
+	eval ltime=\$nd${i}_dnssl${j}_lifetime
+	if [ -z "$ltime" -o "$ltime" = 0 ]; then
+		dnssl=
+	else
+		eval dnssl=\$nd${i}_dnssl${j}_search
+	fi
+
+	[ -z "$rdnss" -a -z "$dnssl" ] && return 1
+
+	new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
+	new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
+	j=$(($j + 1))
+	return 0
+}
+
 add_resolv_conf()
 {
-	local x= conf="$signature$NL" i=${ra_count:-0} ra= warn=true
+	local x= conf="$signature$NL" warn=true
+	local i j ltime rdnss dnssl new_rdnss new_dnssl
 
-	while [ $i -ne 0 ]; do
-		eval ra=\$ra${i}_rdnss
-		new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$ra"
-		eval ra=\$ra${i}_dnssl
-		new_domain_search="$new_domain_search${new_domain_search:+ }$ra"
-		i=$(($i - 1))
+	# Loop to extract the ND DNS options using our indexed shell values
+	i=1
+	j=1
+	while true; do
+		while true; do
+			eval_nd_dns || break
+		done
+		i=$(($i + 1))
+		j=1
+		eval_nd_dns || break
 	done
+	new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
+	new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
 
 	# If we don't have any configuration, remove it
 	if [ -z "$new_domain_name_servers" -a \

Reply via email to