changeset 2976:fe20a975aa48 draft

Replace timeval with timespec.
author Roy Marples <roy@marples.name>
date Tue, 03 Mar 2015 17:27:25 +0000
parents 4f153a979fd2
children a7c2131d0b48
files arp.c common.c common.h dhcp.c dhcp.h dhcp6.c dhcp6.h dhcpcd.c eloop.c eloop.h if-bsd.c ipv6.c ipv6.h ipv6nd.c ipv6nd.h
diffstat 15 files changed, 181 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/arp.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/arp.c	Tue Mar 03 17:27:25 2015 +0000
@@ -253,24 +253,24 @@
 {
 	struct arp_state *astate = arg;
 	struct interface *ifp = astate->iface;
-	struct timeval tv;
+	struct timespec tv;
 
 	if (++astate->probes < PROBE_NUM) {
 		tv.tv_sec = PROBE_MIN;
-		tv.tv_usec = (suseconds_t)arc4random_uniform(
-		    (PROBE_MAX - PROBE_MIN) * 1000000);
-		timernorm(&tv);
+		tv.tv_nsec = (suseconds_t)arc4random_uniform(
+		    (PROBE_MAX - PROBE_MIN) * NSEC_PER_SEC);
+		timespecnorm(&tv);
 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe1, astate);
 	} else {
 		tv.tv_sec = ANNOUNCE_WAIT;
-		tv.tv_usec = 0;
+		tv.tv_nsec = 0;
 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
 	}
 	syslog(LOG_DEBUG,
 	    "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
 	    ifp->name, inet_ntoa(astate->addr),
 	    astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
-	    timeval_to_double(&tv));
+	    timespec_to_double(&tv));
 	if (arp_send(ifp, ARPOP_REQUEST, 0, astate->addr.s_addr) == -1)
 		syslog(LOG_ERR, "send_arp: %m");
 }
--- a/common.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/common.c	Tue Mar 03 17:27:25 2015 +0000
@@ -89,18 +89,13 @@
  */
 #define NO_MONOTONIC "host does not support a monotonic clock - timing can skew"
 int
-get_monotonic(struct timeval *tp)
+get_monotonic(struct timespec *ts)
 {
-#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
-	struct timespec ts;
 
-	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
-		tp->tv_sec = ts.tv_sec;
-		tp->tv_usec = (suseconds_t)(ts.tv_nsec / 1000);
+#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
+	return clock_gettime(CLOCK_MONOTONIC, ts);
 		return 0;
-	}
 #elif defined(__APPLE__)
-#define NSEC_PER_SEC 1000000000
 	/* 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 };
@@ -118,13 +113,12 @@
 		nano = mach_absolute_time();
 		if ((info.denom != 1 || info.numer != 1) && factor != 0.0)
 			nano *= factor;
-		tp->tv_sec = nano / NSEC_PER_SEC;
-		rem = nano % NSEC_PER_SEC;
-		if (rem < 0) {
-			tp->tv_sec--;
-			rem += NSEC_PER_SEC;
+		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;
 		}
-		tp->tv_usec = rem / 1000;
 		return 0;
 	}
 #endif
@@ -136,7 +130,15 @@
 		posix_clock_set = 1;
 	}
 #endif
-	return gettimeofday(tp, NULL);
+	{
+		struct timeval tv;
+		if (gettimeofday(&tv, NULL) == 0) {
+			TIMEVAL_TO_TIMESPEC(&tv, ts);
+			return 0;
+		}
+	}
+
+	return -1;
 }
 
 ssize_t
@@ -172,7 +174,7 @@
 time_t
 uptime(void)
 {
-	struct timeval tv;
+	struct timespec tv;
 
 	if (get_monotonic(&tv) == -1)
 		return -1;
--- a/common.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/common.h	Tue Mar 03 17:27:25 2015 +0000
@@ -48,28 +48,34 @@
 #define STRINGIFY(a)		#a
 #define TOSTRING(a)		STRINGIFY(a)
 
-#define USECINSEC		1000000
-#define timeval_to_double(tv)						\
-	((double)(tv)->tv_sec + (double)((tv)->tv_usec) * 1.0e-6)
-#define timernorm(tv) do {						\
-	while ((tv)->tv_usec >=  USECINSEC) {				\
-		(tv)->tv_sec++;						\
-		(tv)->tv_usec -= USECINSEC;				\
-	}								\
+#define USEC_PER_SEC		1000000L
+#define USEC_PER_NSEC		1000L
+#define NSEC_PER_SEC		1000000000L
+#define MSEC_PER_SEC		1000L
+#define MSEC_PER_NSEC		1000000L
+
+#define timespec_to_double(tv)						     \
+	((double)(tv)->tv_sec + (double)((tv)->tv_nsec) / 1000000000.0)
+#define timespecnorm(tv) do {						     \
+	while ((tv)->tv_nsec >=  NSEC_PER_SEC) {			     \
+		(tv)->tv_sec++;						     \
+		(tv)->tv_nsec -= NSEC_PER_SEC;				     \
+	}								     \
 } while (0 /* CONSTCOND */);
-#define tv_to_ms(ms, tv) do {						\
-	ms = (tv)->tv_sec * 1000;					\
-	ms += (tv)->tv_usec / 1000;					\
+#define ts_to_ms(ms, tv) do {						     \
+	ms = (tv)->tv_sec * MSEC_PER_SEC;				     \
+	ms += (tv)->tv_nsec / MSEC_PER_NSEC;				     \
 } while (0 /* CONSTCOND */);
-#define ms_to_tv(tv, ms) do {						      \
-	(tv)->tv_sec = ms / 1000;					      \
-	(tv)->tv_usec = (suseconds_t)(ms - ((tv)->tv_sec * 1000)) * 1000;     \
+#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;						     \
 } while (0 /* CONSTCOND */);
 
 #ifndef TIMEVAL_TO_TIMESPEC
 #define	TIMEVAL_TO_TIMESPEC(tv, ts) do {				\
 	(ts)->tv_sec = (tv)->tv_sec;					\
-	(ts)->tv_nsec = (tv)->tv_usec * 1000;				\
+	(ts)->tv_nsec = (tv)->tv_usec * USEC_PER_NSEC;			\
 } while (0 /* CONSTCOND */)
 #endif
 
@@ -110,7 +116,7 @@
 void get_line_free(void);
 const char *get_hostname(char *, size_t, int);
 extern int clock_monotonic;
-int get_monotonic(struct timeval *);
+int get_monotonic(struct timespec *);
 ssize_t setvar(char ***, const char *, const char *, const char *);
 ssize_t setvard(char ***, const char *, const char *, size_t);
 time_t uptime(void);
--- a/dhcp.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/dhcp.c	Tue Mar 03 17:27:25 2015 +0000
@@ -1569,7 +1569,7 @@
 	ssize_t r;
 	struct in_addr from, to;
 	in_addr_t a = INADDR_ANY;
-	struct timeval tv;
+	struct timespec tv;
 	int s;
 
 	if (!callback)
@@ -1584,13 +1584,13 @@
 				state->interval = 64;
 		}
 		tv.tv_sec = state->interval + DHCP_RAND_MIN;
-		tv.tv_usec = (suseconds_t)arc4random_uniform(
-		    (DHCP_RAND_MAX - DHCP_RAND_MIN) * 1000000);
-		timernorm(&tv);
+		tv.tv_nsec = (suseconds_t)arc4random_uniform(
+		    (DHCP_RAND_MAX - DHCP_RAND_MIN) * NSEC_PER_SEC);
+		timespecnorm(&tv);
 		syslog(LOG_DEBUG,
 		    "%s: sending %s (xid 0x%x), next in %0.1f seconds",
 		    iface->name, get_dhcp_op(type), state->xid,
-		    timeval_to_double(&tv));
+		    timespec_to_double(&tv));
 	}
 
 	if (dhcp_open(iface) == -1)
@@ -1829,7 +1829,6 @@
 	struct dhcp_state *state = D_STATE(ifp);
 	struct if_options *ifo = ifp->options;
 	struct dhcp_lease *lease = &state->lease;
-	struct timeval tv;
 	uint8_t ipv4ll = 0;
 
 	if (state->state == DHS_BOUND)
@@ -1862,9 +1861,7 @@
 		lease->leasetime = ~0U;
 		state->reason = "INFORM";
 	} else {
-		if (gettimeofday(&tv, NULL) == 0)
-			lease->leasedfrom = tv.tv_sec;
-		else if (lease->frominfo)
+		if (lease->frominfo)
 			state->reason = "TIMEOUT";
 		if (lease->leasetime == ~0U) {
 			lease->renewaltime =
@@ -3071,7 +3068,6 @@
 	struct if_options *ifo = ifp->options;
 	struct dhcp_state *state;
 	struct stat st;
-	struct timeval now;
 	uint32_t l;
 	int nolease;
 
@@ -3167,10 +3163,12 @@
 		} else if (state->lease.leasetime != ~0U &&
 		    stat(state->leasefile, &st) == 0)
 		{
+			time_t now;
+
 			/* Offset lease times and check expiry */
-			gettimeofday(&now, NULL);
-			if ((time_t)state->lease.leasetime <
-			    now.tv_sec - st.st_mtime)
+			now = time(NULL);
+			if (now == -1 ||
+			    (time_t)state->lease.leasetime < now - st.st_mtime)
 			{
 				syslog(LOG_DEBUG,
 				    "%s: discarding expired lease",
@@ -3195,7 +3193,7 @@
 					dhcp_drop(ifp, "EXPIRE");
 #endif
 			} else {
-				l = (uint32_t)(now.tv_sec - st.st_mtime);
+				l = (uint32_t)(now - st.st_mtime);
 				state->lease.leasetime -= l;
 				state->lease.renewaltime -= l;
 				state->lease.rebindtime -= l;
@@ -3223,19 +3221,19 @@
 void
 dhcp_start(struct interface *ifp)
 {
-	struct timeval tv;
+	struct timespec tv;
 
 	if (!(ifp->options->options & DHCPCD_IPV4))
 		return;
 
 	/* No point in delaying a static configuration */
 	tv.tv_sec = DHCP_MIN_DELAY;
-	tv.tv_usec = (suseconds_t)arc4random_uniform(
-	    (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
-	timernorm(&tv);
+	tv.tv_nsec = (suseconds_t)arc4random_uniform(
+	    (DHCP_MAX_DELAY - DHCP_MIN_DELAY) * NSEC_PER_SEC);
+	timespecnorm(&tv);
 	syslog(LOG_DEBUG,
 	    "%s: delaying IPv4 for %0.1f seconds",
-	    ifp->name, timeval_to_double(&tv));
+	    ifp->name, timespec_to_double(&tv));
 
 	eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
 }
--- a/dhcp.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/dhcp.h	Tue Mar 03 17:27:25 2015 +0000
@@ -181,7 +181,6 @@
 	uint32_t renewaltime;
 	uint32_t rebindtime;
 	struct in_addr server;
-	time_t leasedfrom;
 	uint8_t frominfo;
 	uint32_t cookie;
 };
--- a/dhcp6.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/dhcp6.c	Tue Mar 03 17:27:25 2015 +0000
@@ -990,7 +990,7 @@
 	struct sockaddr_in6 dst;
 	struct cmsghdr *cm;
 	struct in6_pktinfo pi;
-	struct timeval RTprev;
+	struct timespec RTprev;
 	double rnd;
 	time_t ms;
 	uint8_t neg;
@@ -1037,49 +1037,49 @@
 				state->RT.tv_sec = 1;
 			else
 				state->RT.tv_sec = 0;
-			state->RT.tv_usec = (suseconds_t)arc4random_uniform(
-			    state->IMD * 1000000);
-			timernorm(&state->RT);
+			state->RT.tv_nsec = (suseconds_t)arc4random_uniform(
+			    state->IMD * NSEC_PER_SEC);
+			timespecnorm(&state->RT);
 			broad_uni = "delaying";
 			goto logsend;
 		}
 		if (state->RTC == 0) {
 			RTprev.tv_sec = state->IRT;
-			RTprev.tv_usec = 0;
+			RTprev.tv_nsec = 0;
 			state->RT.tv_sec = RTprev.tv_sec;
-			state->RT.tv_usec = 0;
+			state->RT.tv_nsec = 0;
 		} else {
 			RTprev = state->RT;
-			timeradd(&state->RT, &state->RT, &state->RT);
+			timespecadd(&state->RT, &state->RT, &state->RT);
 		}
 
 		rnd = DHCP6_RAND_MIN;
 		rnd += (suseconds_t)arc4random_uniform(
 		    DHCP6_RAND_MAX - DHCP6_RAND_MIN);
-		rnd /= 1000;
+		rnd /= MSEC_PER_SEC;
 		neg = (rnd < 0.0);
 		if (neg)
 			rnd = -rnd;
-		tv_to_ms(ms, &RTprev);
+		ts_to_ms(ms, &RTprev);
 		ms *= rnd;
-		ms_to_tv(&RTprev, ms);
+		ms_to_ts(&RTprev, ms);
 		if (neg)
-			timersub(&state->RT, &RTprev, &state->RT);
+			timespecsub(&state->RT, &RTprev, &state->RT);
 		else
-			timeradd(&state->RT, &RTprev, &state->RT);
+			timespecadd(&state->RT, &RTprev, &state->RT);
 
 		if (state->RT.tv_sec > state->MRT) {
 			RTprev.tv_sec = state->MRT;
-			RTprev.tv_usec = 0;
+			RTprev.tv_nsec = 0;
 			state->RT.tv_sec = state->MRT;
-			state->RT.tv_usec = 0;
-			tv_to_ms(ms, &RTprev);
+			state->RT.tv_nsec = 0;
+			ts_to_ms(ms, &RTprev);
 			ms *= rnd;
-			ms_to_tv(&RTprev, ms);
+			ms_to_ts(&RTprev, ms);
 			if (neg)
-				timersub(&state->RT, &RTprev, &state->RT);
+				timespecsub(&state->RT, &RTprev, &state->RT);
 			else
-				timeradd(&state->RT, &RTprev, &state->RT);
+				timespecadd(&state->RT, &RTprev, &state->RT);
 		}
 
 logsend:
@@ -1092,7 +1092,7 @@
 		    state->send->xid[0],
 		    state->send->xid[1],
 		    state->send->xid[2],
-		    timeval_to_double(&state->RT));
+		    timespec_to_double(&state->RT));
 
 		/* Wait the initial delay */
 		if (state->IMD) {
@@ -1695,7 +1695,7 @@
 
 static int
 dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
-    const uint8_t *d, size_t l, const struct timeval *acquired)
+    const uint8_t *d, size_t l, const struct timespec *acquired)
 {
 	struct dhcp6_state *state;
 	const struct dhcp6_option *o;
@@ -1776,7 +1776,7 @@
 
 static int
 dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
-    const uint8_t *d, size_t l, const struct timeval *acquired)
+    const uint8_t *d, size_t l, const struct timespec *acquired)
 {
 	struct dhcp6_state *state;
 	const struct dhcp6_option *o, *ex;
@@ -1902,7 +1902,7 @@
 
 static int
 dhcp6_findia(struct interface *ifp, const struct dhcp6_message *m, size_t l,
-    const char *sfrom, const struct timeval *acquired)
+    const char *sfrom, const struct timespec *acquired)
 {
 	struct dhcp6_state *state;
 	const struct if_options *ifo;
@@ -2051,11 +2051,11 @@
 static int
 dhcp6_validatelease(struct interface *ifp,
     const struct dhcp6_message *m, size_t len,
-    const char *sfrom, const struct timeval *acquired)
+    const char *sfrom, const struct timespec *acquired)
 {
 	struct dhcp6_state *state;
 	int nia;
-	struct timeval aq;
+	struct timespec aq;
 
 	if (len <= sizeof(*m)) {
 		syslog(LOG_ERR, "%s: DHCPv6 lease truncated", ifp->name);
@@ -2109,9 +2109,9 @@
 	struct stat st;
 	int fd;
 	ssize_t bytes;
-	struct timeval now;
 	const struct dhcp6_option *o;
-	struct timeval acquired;
+	struct timespec acquired;
+	time_t now;
 
 	state = D6_STATE(ifp);
 	if (stat(state->leasefile, &st) == -1) {
@@ -2145,9 +2145,13 @@
 		goto ex;
 	}
 
-	gettimeofday(&now, NULL);
+	if ((now = time(NULL)) == -1) {
+		syslog(LOG_ERR, "%s: time: %m", __func__);
+		goto ex;
+	}
+
 	get_monotonic(&acquired);
-	acquired.tv_sec -= now.tv_sec - st.st_mtime;
+	acquired.tv_sec -= now - st.st_mtime;
 
 	/* Check to see if the lease is still valid */
 	fd = dhcp6_validatelease(ifp, state->new, state->new_len, NULL,
@@ -2158,7 +2162,7 @@
 	if (!(ifp->ctx->options & DHCPCD_DUMPLEASE) &&
 	    state->expire != ND6_INFINITE_LIFETIME)
 	{
-		if ((time_t)state->expire < now.tv_sec - st.st_mtime) {
+		if ((time_t)state->expire < now - st.st_mtime) {
 			syslog(LOG_DEBUG,"%s: discarding expired lease",
 			    ifp->name);
 			goto ex;
--- a/dhcp6.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/dhcp6.h	Tue Mar 03 17:27:25 2015 +0000
@@ -172,7 +172,7 @@
 	time_t start_uptime;
 
 	/* Message retransmission timings */
-	struct timeval RT;
+	struct timespec RT;
 	unsigned int IMD;
 	unsigned int RTC;
 	time_t IRT;
--- a/dhcpcd.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/dhcpcd.c	Tue Mar 03 17:27:25 2015 +0000
@@ -550,10 +550,10 @@
 
 	carrier = if_carrier(ifp); /* will set ifp->flags */
 	if (carrier == LINK_UP && !(ifp->flags & IFF_UP)) {
-		struct timeval tv;
+		struct timespec tv;
 
 		tv.tv_sec = 0;
-		tv.tv_usec = IF_POLL_UP * 1000;
+		tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC;
 		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp);
 		return;
 	}
@@ -681,7 +681,7 @@
 	size_t i;
 	char buf[DUID_LEN * 3];
 	int carrier;
-	struct timeval tv;
+	struct timespec tv;
 
 	if (ifo->options & DHCPCD_LINK) {
 		switch (ifp->carrier) {
@@ -695,7 +695,7 @@
 			 * Loop until both IFF_UP and IFF_RUNNING are set */
 			if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) {
 				tv.tv_sec = 0;
-				tv.tv_usec = IF_POLL_UP * 1000;
+				tv.tv_nsec = IF_POLL_UP * MSEC_PER_NSEC;
 				eloop_timeout_add_tv(ifp->ctx->eloop,
 				    &tv, dhcpcd_startinterface, ifp);
 			} else
@@ -1508,7 +1508,7 @@
 	 * eloop removals as well, so init here. */
 	ctx.eloop = eloop_init();
 	if (ctx.eloop == NULL) {
-		syslog(LOG_ERR, "%s: %m", __func__);
+		syslog(LOG_ERR, "%s: eloop_init: %m", __func__);
 		goto exit_failure;
 	}
 
--- a/eloop.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/eloop.c	Tue Mar 03 17:27:25 2015 +0000
@@ -153,16 +153,15 @@
 
 int
 eloop_q_timeout_add_tv(struct eloop_ctx *ctx, int queue,
-    const struct timeval *when, void (*callback)(void *), void *arg)
+    const struct timespec *when, void (*callback)(void *), void *arg)
 {
-	struct timeval now;
-	struct timeval w;
+	struct timespec now, w;
 	struct eloop_timeout *t, *tt = NULL;
 
 	get_monotonic(&now);
-	timeradd(&now, when, &w);
+	timespecadd(&now, when, &w);
 	/* Check for time_t overflow. */
-	if (timercmp(&w, &now, <)) {
+	if (timespeccmp(&w, &now, <)) {
 		errno = ERANGE;
 		return -1;
 	}
@@ -188,8 +187,7 @@
 		}
 	}
 
-	t->when.tv_sec = w.tv_sec;
-	t->when.tv_usec = w.tv_usec;
+	t->when = w;
 	t->callback = callback;
 	t->arg = arg;
 	t->queue = queue;
@@ -197,7 +195,7 @@
 	/* The timeout list should be in chronological order,
 	 * soonest first. */
 	TAILQ_FOREACH(tt, &ctx->timeouts, next) {
-		if (timercmp(&t->when, &tt->when, <)) {
+		if (timespeccmp(&t->when, &tt->when, <)) {
 			TAILQ_INSERT_BEFORE(tt, t, next);
 			return 0;
 		}
@@ -210,10 +208,10 @@
 eloop_q_timeout_add_sec(struct eloop_ctx *ctx, int queue, time_t when,
     void (*callback)(void *), void *arg)
 {
-	struct timeval tv;
+	struct timespec tv;
 
 	tv.tv_sec = when;
-	tv.tv_usec = 0;
+	tv.tv_nsec = 0;
 	return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg);
 }
 
@@ -261,6 +259,11 @@
 eloop_init(void)
 {
 	struct eloop_ctx *ctx;
+	struct timespec now;
+
+	/* Check we have a working monotonic clock. */
+	if (get_monotonic(&now) == -1)
+		return NULL;
 
 	ctx = calloc(1, sizeof(*ctx));
 	if (ctx) {
@@ -306,12 +309,10 @@
 eloop_start(struct dhcpcd_ctx *dctx)
 {
 	struct eloop_ctx *ctx;
-	struct timeval now;
 	int n;
 	struct eloop_event *e;
 	struct eloop_timeout *t;
-	struct timeval tv;
-	struct timespec ts, *tsp;
+	struct timespec now, ts, *tsp;
 	void (*t0)(void *);
 #ifndef USE_SIGNALS
 	int timeout;
@@ -331,14 +332,13 @@
 		}
 		if ((t = TAILQ_FIRST(&ctx->timeouts))) {
 			get_monotonic(&now);
-			if (timercmp(&now, &t->when, >)) {
+			if (timespeccmp(&now, &t->when, >)) {
 				TAILQ_REMOVE(&ctx->timeouts, t, next);
 				t->callback(t->arg);
 				TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next);
 				continue;
 			}
-			timersub(&t->when, &now, &tv);
-			TIMEVAL_TO_TIMESPEC(&tv, &ts);
+			timespecsub(&t->when, &now, &ts);
 			tsp = &ts;
 		} else
 			/* No timeouts, so wait forever */
--- a/eloop.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/eloop.h	Tue Mar 03 17:27:25 2015 +0000
@@ -50,7 +50,7 @@
 
 struct eloop_timeout {
 	TAILQ_ENTRY(eloop_timeout) next;
-	struct timeval when;
+	struct timespec when;
 	void (*callback)(void *);
 	void *arg;
 	int queue;
@@ -88,7 +88,7 @@
 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,
-    const struct timeval *, void (*)(void *), void *);
+    const struct timespec *, void (*)(void *), void *);
 int eloop_timeout_add_now(struct eloop_ctx *, void (*)(void *), void *);
 void eloop_q_timeout_delete(struct eloop_ctx *, int, void (*)(void *), void *);
 struct eloop_ctx * eloop_init(void);
--- a/if-bsd.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/if-bsd.c	Tue Mar 03 17:27:25 2015 +0000
@@ -600,6 +600,9 @@
 #ifdef RTF_CLONING
 			rtm.hdr.rtm_flags |= RTF_CLONING;
 #endif
+#ifdef RTP_CONNECTED
+			rtm.hdr.rtm_priority = RTP_CONNECTED;
+#endif
 		}
 	}
 	if (rt->dest.s_addr == rt->gate.s_addr &&
@@ -953,6 +956,9 @@
 #ifdef RTF_CLONING
 		rtm.hdr.rtm_flags |= RTF_CLONING;
 #endif
+#ifdef RTP_CONNECTED
+		rtm.hdr.rtm_priority = RTP_CONNECTED;
+#endif
 	} else
 		rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
 
--- a/ipv6.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/ipv6.c	Tue Mar 03 17:27:25 2015 +0000
@@ -594,9 +594,9 @@
 		    ap->iface->ctx->ifaces, ap->iface->name,
 		    &ap->addr, ap->prefix_len, ifa_flags);
 	} else {
-		struct timeval tv;
+		struct timespec tv;
 
-		ms_to_tv(&tv, RETRANS_TIMER / 2);
+		ms_to_ts(&tv, RETRANS_TIMER / 2);
 		eloop_timeout_add_tv(ap->iface->ctx->eloop, &tv,
 		    ipv6_checkaddrflags, ap);
 	}
@@ -627,7 +627,7 @@
 }
 
 int
-ipv6_addaddr(struct ipv6_addr *ap, const struct timeval *now)
+ipv6_addaddr(struct ipv6_addr *ap, const struct timespec *now)
 {
 	struct interface *ifp;
 	struct ipv6_state *state;
@@ -676,17 +676,17 @@
 	/* Adjust plftime and vltime based on acquired time */
 	pltime = ap->prefix_pltime;
 	vltime = ap->prefix_vltime;
-	if (timerisset(&ap->acquired) &&
+	if (timespecisset(&ap->acquired) &&
 	    (ap->prefix_pltime != ND6_INFINITE_LIFETIME ||
 	    ap->prefix_vltime != ND6_INFINITE_LIFETIME))
 	{
-		struct timeval n;
+		struct timespec n;
 
 		if (now == NULL) {
 			get_monotonic(&n);
 			now = &n;
 		}
-		timersub(now, &ap->acquired, &n);
+		timespecsub(now, &ap->acquired, &n);
 		if (ap->prefix_pltime != ND6_INFINITE_LIFETIME)
 			ap->prefix_pltime -= (uint32_t)n.tv_sec;
 		if (ap->prefix_vltime != ND6_INFINITE_LIFETIME)
@@ -732,9 +732,9 @@
 	eloop_timeout_delete(ap->iface->ctx->eloop,
 		ipv6_checkaddrflags, ap);
 	if (!(ap->flags & IPV6_AF_DADCOMPLETED)) {
-		struct timeval tv;
+		struct timespec tv;
 
-		ms_to_tv(&tv, RETRANS_TIMER / 2);
+		ms_to_ts(&tv, RETRANS_TIMER / 2);
 		eloop_timeout_add_tv(ap->iface->ctx->eloop,
 		    &tv, ipv6_checkaddrflags, ap);
 	}
@@ -766,10 +766,10 @@
 {
 	struct ipv6_addr *ap, *apn, *apf;
 	ssize_t i;
-	struct timeval now;
+	struct timespec now;
 
 	i = 0;
-	timerclear(&now);
+	timespecclear(&now);
 	TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
 		if (ap->prefix_vltime == 0) {
 			if (ap->flags & IPV6_AF_ADDED) {
@@ -814,7 +814,7 @@
 				apf->flags &= ~IPV6_AF_ADDED;
 			if (ap->flags & IPV6_AF_NEW)
 				i++;
-			if (!timerisset(&now))
+			if (!timespecisset(&now))
 				get_monotonic(&now);
 			ipv6_addaddr(ap, &now);
 		}
@@ -836,9 +836,9 @@
     const struct interface *ifd)
 {
 	struct ipv6_addr *ap, *apn, *apf;
-	struct timeval now;
+	struct timespec now;
 
-	timerclear(&now);
+	timespecclear(&now);
 	TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
 		if (ifd && ap->delegating_iface != ifd)
 			continue;
@@ -860,7 +860,7 @@
 			if (!(ap->iface->options->options &
 			    DHCPCD_EXITING) && apf)
 			{
-				if (!timerisset(&now))
+				if (!timespecisset(&now))
 					get_monotonic(&now);
 				ipv6_addaddr(apf, &now);
 			}
@@ -997,9 +997,9 @@
 			if (IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
 #ifdef IPV6_POLLADDRFLAG
 				if (ap->addr_flags & IN6_IFF_TENTATIVE) {
-					struct timeval tv;
+					struct timespec tv;
 
-					ms_to_tv(&tv, RETRANS_TIMER / 2);
+					ms_to_ts(&tv, RETRANS_TIMER / 2);
 					eloop_timeout_add_tv(
 					    ap->iface->ctx->eloop,
 					    &tv, ipv6_checkaddrflags, ap);
@@ -1437,7 +1437,7 @@
 
 	if (ia->flags & IPV6_AF_DUPLICATED) {
 		struct ipv6_addr *ia1;
-		struct timeval tv;
+		struct timespec tv;
 
 		if (++ia->dadcounter == TEMP_IDGEN_RETRIES) {
 			syslog(LOG_ERR,
@@ -1457,7 +1457,7 @@
 }
 
 struct ipv6_addr *
-ipv6_createtempaddr(struct ipv6_addr *ia0, const struct timeval *now)
+ipv6_createtempaddr(struct ipv6_addr *ia0, const struct timespec *now)
 {
 	struct ipv6_state *state;
 	const struct ipv6_state *cstate;
@@ -1649,7 +1649,7 @@
 }
 
 void
-ipv6_addtempaddrs(struct interface *ifp, const struct timeval *now)
+ipv6_addtempaddrs(struct interface *ifp, const struct timespec *now)
 {
 	struct ipv6_state *state;
 	struct ipv6_addr *ia;
@@ -1666,7 +1666,7 @@
 ipv6_regentempaddr(void *arg)
 {
 	struct ipv6_addr *ia = arg, *ia1;
-	struct timeval tv;
+	struct timespec tv;
 
 	syslog(LOG_DEBUG, "%s: regen temp addr %s",
 	    ia->iface->name, ia->saddr);
--- a/ipv6.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/ipv6.h	Tue Mar 03 17:27:25 2015 +0000
@@ -104,8 +104,8 @@
 	uint8_t prefix_len;
 	uint32_t prefix_vltime;
 	uint32_t prefix_pltime;
-	struct timeval created;
-	struct timeval acquired;
+	struct timespec created;
+	struct timespec acquired;
 	struct in6_addr addr;
 	int addr_flags;
 	short flags;
@@ -238,7 +238,7 @@
 int ipv6_userprefix( const struct in6_addr *, short prefix_len,
     uint64_t user_number, struct in6_addr *result, short result_len);
 void ipv6_checkaddrflags(void *);
-int ipv6_addaddr(struct ipv6_addr *, const struct timeval *);
+int ipv6_addaddr(struct ipv6_addr *, const struct timespec *);
 ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs);
 void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
     const struct interface *);
@@ -261,9 +261,9 @@
 void ipv6_gentempifid(struct interface *);
 void ipv6_settempstale(struct interface *);
 struct ipv6_addr *ipv6_createtempaddr(struct ipv6_addr *,
-    const struct timeval *);
+    const struct timespec *);
 struct ipv6_addr *ipv6_settemptime(struct ipv6_addr *, int);
-void ipv6_addtempaddrs(struct interface *, const struct timeval *);
+void ipv6_addtempaddrs(struct interface *, const struct timespec *);
 #else
 #define ipv6_gentempifid(a) {}
 #define ipv6_settempstale(a) {}
--- a/ipv6nd.c	Mon Mar 02 20:37:28 2015 +0000
+++ b/ipv6nd.c	Tue Mar 03 17:27:25 2015 +0000
@@ -519,7 +519,7 @@
 		TAILQ_FOREACH(rao, &rap->options, next) {
 			if (rao->type == ND_OPT_RDNSS &&
 			    rao->option &&
-			    timerisset(&rao->expire))
+			    timespecisset(&rao->expire))
 			{
 				hasdns = 1;
 				break;
@@ -578,7 +578,7 @@
 	struct interface *ifp;
 	struct ra *rap;
 	int wascompleted, found;
-	struct timeval tv;
+	struct timespec tv;
 	char buf[INET6_ADDRSTRLEN];
 	const char *p;
 	int dadcounter;
@@ -630,9 +630,9 @@
 			else
 				ap->saddr[0] = '\0';
 			tv.tv_sec = 0;
-			tv.tv_usec = (suseconds_t)arc4random_uniform(
-			    IDGEN_DELAY * USECINSEC);
-			timernorm(&tv);
+			tv.tv_nsec = (suseconds_t)
+			    arc4random_uniform(IDGEN_DELAY * NSEC_PER_SEC);
+			timespecnorm(&tv);
 			eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
 			    ipv6nd_addaddr, ap);
 			return;
@@ -690,7 +690,7 @@
 	struct ra_opt *rao;
 	struct ipv6_addr *ap;
 	char *opt, *opt2, *tmp;
-	struct timeval expire;
+	struct timespec expire;
 	uint8_t new_rap, new_data;
 #ifdef IPV6_MANAGETEMPADDR
 	uint8_t new_ap;
@@ -1094,11 +1094,11 @@
 		} else
 			free(opt);
 		if (lifetime == ~0U)
-			timerclear(&rao->expire);
+			timespecclear(&rao->expire);
 		else {
 			expire.tv_sec = (time_t)lifetime;
-			expire.tv_usec = 0;
-			timeradd(&rap->received, &expire, &rao->expire);
+			expire.tv_nsec = 0;
+			timespecadd(&rap->received, &expire, &rao->expire);
 		}
 		if (rao && rao->type == ND_OPT_PREFIX_INFORMATION && opt2) {
 			n = _ND_OPT_PREFIX_ADDR;
@@ -1316,13 +1316,13 @@
 	struct interface *ifp;
 	struct ra *rap, *ran;
 	struct ra_opt *rao, *raon;
-	struct timeval now, lt, expire, next;
+	struct timespec now, lt, expire, next;
 	int expired, valid;
 
 	ifp = arg;
 	get_monotonic(&now);
 	expired = 0;
-	timerclear(&next);
+	timespecclear(&next);
 
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) {
 		if (rap->iface != ifp)
@@ -1330,9 +1330,10 @@
 		valid = 0;
 		if (rap->lifetime) {
 			lt.tv_sec = (time_t)rap->lifetime;
-			lt.tv_usec = 0;
-			timeradd(&rap->received, &lt, &expire);
-			if (rap->lifetime == 0 || timercmp(&now, &expire, >)) {
+			lt.tv_nsec = 0;
+			timespecadd(&rap->received, &lt, &expire);
+			if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
+			{
 				if (!rap->expired) {
 					syslog(LOG_WARNING,
 					    "%s: %s: router expired",
@@ -1341,9 +1342,9 @@
 				}
 			} else {
 				valid = 1;
-				timersub(&expire, &now, &lt);
-				if (!timerisset(&next) ||
-				    timercmp(&next, &lt, >))
+				timespecsub(&expire, &now, &lt);
+				if (!timespecisset(&next) ||
+				    timespeccmp(&next, &lt, >))
 					next = lt;
 			}
 		}
@@ -1366,9 +1367,9 @@
 					continue;
 				}
 			}
-			if (!timerisset(&rao->expire))
+			if (!timespecisset(&rao->expire))
 				continue;
-			if (timercmp(&now, &rao->expire, >)) {
+			if (timespeccmp(&now, &rao->expire, >)) {
 				/* Expired prefixes are logged above */
 				if (rao->type != ND_OPT_PREFIX_INFORMATION)
 					syslog(LOG_WARNING,
@@ -1381,8 +1382,8 @@
 				continue;
 			}
 			valid = 1;
-			timersub(&rao->expire, &now, &lt);
-			if (!timerisset(&next) || timercmp(&next, &lt, >))
+			timespecsub(&rao->expire, &now, &lt);
+			if (!timespecisset(&next) || timespeccmp(&next, &lt, >))
 				next = lt;
 		}
 
@@ -1392,7 +1393,7 @@
 			ipv6nd_free_ra(rap);
 	}
 
-	if (timerisset(&next))
+	if (timespecisset(&next))
 		eloop_timeout_add_tv(ifp->ctx->eloop,
 		    &next, ipv6nd_expirera, ifp);
 	if (expired) {
@@ -1624,16 +1625,16 @@
 void
 ipv6nd_startrs(struct interface *ifp)
 {
-	struct timeval tv;
+	struct timespec tv;
 
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	tv.tv_sec = 0;
-	tv.tv_usec = (suseconds_t)arc4random_uniform(
-	    MAX_RTR_SOLICITATION_DELAY * 1000000);
-	timernorm(&tv);
+	tv.tv_nsec = (suseconds_t)arc4random_uniform(
+	    MAX_RTR_SOLICITATION_DELAY * NSEC_PER_SEC);
+	timespecnorm(&tv);
 	syslog(LOG_DEBUG,
 	    "%s: delaying IPv6 router solicitation for %0.1f seconds",
-	    ifp->name, timeval_to_double(&tv));
+	    ifp->name, timespec_to_double(&tv));
 	eloop_timeout_add_tv(ifp->ctx->eloop, &tv, ipv6nd_startrs1, ifp);
 	return;
 }
--- a/ipv6nd.h	Mon Mar 02 20:37:28 2015 +0000
+++ b/ipv6nd.h	Tue Mar 03 17:27:25 2015 +0000
@@ -37,7 +37,7 @@
 struct ra_opt {
 	TAILQ_ENTRY(ra_opt) next;
 	uint16_t type;
-	struct timeval expire;
+	struct timespec expire;
 	char *option;
 };
 
@@ -48,7 +48,7 @@
 	char sfrom[INET6_ADDRSTRLEN];
 	unsigned char *data;
 	size_t data_len;
-	struct timeval received;
+	struct timespec received;
 	unsigned char flags;
 	uint32_t lifetime;
 	uint32_t reachable;