diff options
author | hrs <hrs@FreeBSD.org> | 2013-08-05 20:13:02 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2013-08-05 20:13:02 +0000 |
commit | 13c1bcf2c1d5fbdca99cdddec726f822b68dddbc (patch) | |
tree | c3af796aa3d9d6e1a9fa48bdec823e34beac7892 /usr.sbin/rtadvd | |
parent | 103825c951713677489b0556d7cd86852ec2969c (diff) | |
download | FreeBSD-src-13c1bcf2c1d5fbdca99cdddec726f822b68dddbc.zip FreeBSD-src-13c1bcf2c1d5fbdca99cdddec726f822b68dddbc.tar.gz |
- Use time_uptime instead of time_second in data structures for
PF_INET6 in kernel. This fixes various malfunction when the wall time
clock is changed. Bump __FreeBSD_version to 1000041.
- Use clock_gettime(CLOCK_MONOTONIC_FAST) in userland utilities.
MFC after: 1 month
Diffstat (limited to 'usr.sbin/rtadvd')
-rw-r--r-- | usr.sbin/rtadvd/config.c | 20 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rrenum.c | 9 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.c | 41 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.h | 4 | ||||
-rw-r--r-- | usr.sbin/rtadvd/timer.c | 45 | ||||
-rw-r--r-- | usr.sbin/rtadvd/timer.h | 10 | ||||
-rw-r--r-- | usr.sbin/rtadvd/timer_subr.c | 49 | ||||
-rw-r--r-- | usr.sbin/rtadvd/timer_subr.h | 44 |
8 files changed, 99 insertions, 123 deletions
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c index d10829a..bb4aaec 100644 --- a/usr.sbin/rtadvd/config.c +++ b/usr.sbin/rtadvd/config.c @@ -34,7 +34,6 @@ #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> -#include <sys/time.h> #include <net/if.h> #include <net/if_var.h> @@ -58,6 +57,7 @@ #include <string.h> #include <search.h> #include <stdlib.h> +#include <time.h> #include <unistd.h> #include <ifaddrs.h> @@ -563,8 +563,9 @@ getconfig(struct ifinfo *ifi) makeentry(entbuf, sizeof(entbuf), i, "vltimedecr"); if (agetflag(entbuf)) { - struct timeval now; - gettimeofday(&now, 0); + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC_FAST, &now); pfx->pfx_vltimeexpire = now.tv_sec + pfx->pfx_validlifetime; } @@ -583,8 +584,9 @@ getconfig(struct ifinfo *ifi) makeentry(entbuf, sizeof(entbuf), i, "pltimedecr"); if (agetflag(entbuf)) { - struct timeval now; - gettimeofday(&now, 0); + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC_FAST, &now); pfx->pfx_pltimeexpire = now.tv_sec + pfx->pfx_preflifetime; } @@ -1164,7 +1166,7 @@ delete_prefix(struct prefix *pfx) void invalidate_prefix(struct prefix *pfx) { - struct timeval timo; + struct timespec timo; struct rainfo *rai; struct ifinfo *ifi; char ntopbuf[INET6_ADDRSTRLEN]; @@ -1191,7 +1193,7 @@ invalidate_prefix(struct prefix *pfx) delete_prefix(pfx); } timo.tv_sec = prefix_timo; - timo.tv_usec = 0; + timo.tv_nsec = 0; rtadvd_set_timer(&timo, pfx->pfx_timer); } @@ -1415,7 +1417,7 @@ make_packet(struct rainfo *rai) TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { uint32_t vltime, pltime; - struct timeval now; + struct timespec now; ndopt_pi = (struct nd_opt_prefix_info *)buf; ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; @@ -1432,7 +1434,7 @@ make_packet(struct rainfo *rai) vltime = 0; else { if (pfx->pfx_vltimeexpire || pfx->pfx_pltimeexpire) - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); if (pfx->pfx_vltimeexpire == 0) vltime = pfx->pfx_validlifetime; else diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c index a8fbbf2..0c97d98 100644 --- a/usr.sbin/rtadvd/rrenum.c +++ b/usr.sbin/rtadvd/rrenum.c @@ -49,6 +49,7 @@ #include <netdb.h> #include <string.h> #include <stdlib.h> +#include <time.h> #include <syslog.h> #include "rtadvd.h" #include "rrenum.h" @@ -215,7 +216,7 @@ do_use_prefix(int len, struct rr_pco_match *rpm, rai = ifi->ifi_rainfo; TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { - struct timeval now; + struct timespec now; if (prefix_match(&pfx->pfx_prefix, pfx->pfx_prefixlen, &rpm->rpm_prefix, @@ -226,14 +227,16 @@ do_use_prefix(int len, struct rr_pco_match *rpm, pfx->pfx_preflifetime = ntohl(rpu->rpu_pltime); if (irr->irr_rrf_decrvalid) { - gettimeofday(&now, 0); + clock_gettime(CLOCK_MONOTONIC_FAST, + &now); pfx->pfx_vltimeexpire = now.tv_sec + pfx->pfx_validlifetime; } else pfx->pfx_vltimeexpire = 0; if (irr->irr_rrf_decrprefd) { - gettimeofday(&now, 0); + clock_gettime(CLOCK_MONOTONIC_FAST, + &now); pfx->pfx_pltimeexpire = now.tv_sec + pfx->pfx_preflifetime; diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c index c3420ef..ba71954 100644 --- a/usr.sbin/rtadvd/rtadvd.c +++ b/usr.sbin/rtadvd/rtadvd.c @@ -35,7 +35,6 @@ #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/uio.h> -#include <sys/time.h> #include <sys/queue.h> #include <sys/stat.h> #include <sys/sysctl.h> @@ -179,7 +178,7 @@ int main(int argc, char *argv[]) { struct pollfd set[PFD_MAX]; - struct timeval *timeout; + struct timespec *timeout; int i, ch; int fflag = 0, logopt; int error; @@ -331,7 +330,7 @@ main(int argc, char *argv[]) "<%s> set timer to %ld:%ld. waiting for " "inputs or timeout", __func__, (long int)timeout->tv_sec, - (long int)timeout->tv_usec); + (long int)timeout->tv_nsec / 1000); } else { syslog(LOG_DEBUG, "<%s> there's no timer. waiting for inputs", @@ -339,7 +338,7 @@ main(int argc, char *argv[]) } if ((i = poll(set, sizeof(set)/sizeof(set[0]), timeout ? (timeout->tv_sec * 1000 + - timeout->tv_usec / 1000) : INFTIM)) < 0) { + timeout->tv_nsec / 1000 / 1000) : INFTIM)) < 0) { /* EINTR would occur if a signal was delivered */ if (errno != EINTR) @@ -432,7 +431,7 @@ rtadvd_shutdown(void) if (ifi->ifi_ra_timer == NULL) continue; if (ifi->ifi_ra_lastsent.tv_sec == 0 && - ifi->ifi_ra_lastsent.tv_usec == 0 && + ifi->ifi_ra_lastsent.tv_nsec == 0 && ifi->ifi_ra_timer != NULL) { /* * When RA configured but never sent, @@ -1006,7 +1005,7 @@ static void set_short_delay(struct ifinfo *ifi) { long delay; /* must not be greater than 1000000 */ - struct timeval interval, now, min_delay, tm_tmp, *rest; + struct timespec interval, now, min_delay, tm_tmp, *rest; if (ifi->ifi_ra_timer == NULL) return; @@ -1023,9 +1022,9 @@ set_short_delay(struct ifinfo *ifi) delay = random() % MAX_RA_DELAY_TIME; #endif interval.tv_sec = 0; - interval.tv_usec = delay; + interval.tv_nsec = delay * 1000; rest = rtadvd_timer_rest(ifi->ifi_ra_timer); - if (TIMEVAL_LT(rest, &interval)) { + if (TS_CMP(rest, &interval, <)) { syslog(LOG_DEBUG, "<%s> random delay is larger than " "the rest of the current timer", __func__); interval = *rest; @@ -1038,13 +1037,13 @@ set_short_delay(struct ifinfo *ifi) * MIN_DELAY_BETWEEN_RAS plus the random value after the * previous advertisement was sent. */ - gettimeofday(&now, NULL); - TIMEVAL_SUB(&now, &ifi->ifi_ra_lastsent, &tm_tmp); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); + TS_SUB(&now, &ifi->ifi_ra_lastsent, &tm_tmp); min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; - min_delay.tv_usec = 0; - if (TIMEVAL_LT(&tm_tmp, &min_delay)) { - TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); - TIMEVAL_ADD(&min_delay, &interval, &interval); + min_delay.tv_nsec = 0; + if (TS_CMP(&tm_tmp, &min_delay, <)) { + TS_SUB(&min_delay, &tm_tmp, &min_delay); + TS_ADD(&min_delay, &interval, &interval); } rtadvd_set_timer(&interval, ifi->ifi_ra_timer); } @@ -1242,7 +1241,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, int inconsistent = 0; char ntopbuf[INET6_ADDRSTRLEN]; char prefixbuf[INET6_ADDRSTRLEN]; - struct timeval now; + struct timespec now; #if 0 /* impossible */ if (pinfo->nd_opt_pi_type != ND_OPT_PREFIX_INFORMATION) @@ -1285,7 +1284,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, * XXX: can we really expect that all routers on the link * have synchronized clocks? */ - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); preferred_time += now.tv_sec; if (!pfx->pfx_timer && rai->rai_clockskew && @@ -1318,7 +1317,7 @@ prefix_check(struct nd_opt_prefix_info *pinfo, valid_time = ntohl(pinfo->nd_opt_pi_valid_time); if (pfx->pfx_vltimeexpire) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); valid_time += now.tv_sec; if (!pfx->pfx_timer && rai->rai_clockskew && @@ -1784,7 +1783,7 @@ ra_output(struct ifinfo *ifi) } /* update timestamp */ - gettimeofday(&ifi->ifi_ra_lastsent, NULL); + clock_gettime(CLOCK_MONOTONIC_FAST, &ifi->ifi_ra_lastsent); /* update counter */ ifi->ifi_rs_waitcount = 0; @@ -1866,7 +1865,7 @@ ra_timeout(void *arg) /* update RA timer */ void -ra_timer_update(void *arg, struct timeval *tm) +ra_timer_update(void *arg, struct timespec *tm) { uint16_t interval; struct rainfo *rai; @@ -1916,12 +1915,12 @@ ra_timer_update(void *arg, struct timeval *tm) } tm->tv_sec = interval; - tm->tv_usec = 0; + tm->tv_nsec = 0; syslog(LOG_DEBUG, "<%s> RA timer on %s is set to %ld:%ld", __func__, ifi->ifi_ifname, - (long int)tm->tv_sec, (long int)tm->tv_usec); + (long int)tm->tv_sec, (long int)tm->tv_nsec / 1000); return; } diff --git a/usr.sbin/rtadvd/rtadvd.h b/usr.sbin/rtadvd/rtadvd.h index ac8ce99..e7ed87f 100644 --- a/usr.sbin/rtadvd/rtadvd.h +++ b/usr.sbin/rtadvd/rtadvd.h @@ -270,7 +270,7 @@ struct ifinfo { uint32_t ifi_burstinterval; struct rtadvd_timer *ifi_ra_timer; /* timestamp when the latest RA was sent */ - struct timeval ifi_ra_lastsent; + struct timespec ifi_ra_lastsent; uint16_t ifi_rs_waitcount; /* statistics */ @@ -286,7 +286,7 @@ extern TAILQ_HEAD(ifilist_head_t, ifinfo) ifilist; extern char *mcastif; struct rtadvd_timer *ra_timeout(void *); -void ra_timer_update(void *, struct timeval *); +void ra_timer_update(void *, struct timespec *); void ra_output(struct ifinfo *); int prefix_match(struct in6_addr *, int, diff --git a/usr.sbin/rtadvd/timer.c b/usr.sbin/rtadvd/timer.c index 2ea77b5..faa541d 100644 --- a/usr.sbin/rtadvd/timer.c +++ b/usr.sbin/rtadvd/timer.c @@ -31,7 +31,6 @@ * SUCH DAMAGE. */ -#include <sys/time.h> #include <sys/queue.h> #include <sys/socket.h> @@ -44,6 +43,7 @@ #include <stdlib.h> #include <string.h> #include <search.h> +#include <time.h> #include <netdb.h> #include "rtadvd.h" @@ -52,12 +52,17 @@ struct rtadvd_timer_head_t ra_timer = TAILQ_HEAD_INITIALIZER(ra_timer); -static struct timeval tm_limit = {0x7fffffff, 0x7fffffff}; -static struct timeval tm_max; +static struct timespec tm_limit; +static struct timespec tm_max; void rtadvd_timer_init(void) { + /* Generate maximum time in timespec. */ + memset(&tm_limit.tv_sec, 0xff, sizeof(tm_limit.tv_sec)); + memset(&tm_limit.tv_nsec, 0xff, sizeof(tm_limit.tv_nsec)); + tm_limit.tv_sec &= ~(1UL << (sizeof(tm_limit.tv_sec) * 8 - 1)); + tm_limit.tv_nsec &= ~(1UL << (sizeof(tm_limit.tv_nsec) * 8 - 1)); tm_max = tm_limit; TAILQ_INIT(&ra_timer); @@ -102,7 +107,7 @@ rtadvd_update_timeout_handler(void) struct rtadvd_timer * rtadvd_add_timer(struct rtadvd_timer *(*timeout)(void *), - void (*update)(void *, struct timeval *), + void (*update)(void *, struct timespec *), void *timeodata, void *updatedata) { struct rtadvd_timer *rat; @@ -149,48 +154,48 @@ rtadvd_remove_timer(struct rtadvd_timer *rat) * call the expire function for the timer and update the timer. * Return the next interval for select() call. */ -struct timeval * +struct timespec * rtadvd_check_timer(void) { - static struct timeval returnval; - struct timeval now; + static struct timespec returnval; + struct timespec now; struct rtadvd_timer *rat; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); tm_max = tm_limit; TAILQ_FOREACH(rat, &ra_timer, rat_next) { - if (TIMEVAL_LEQ(&rat->rat_tm, &now)) { + if (TS_CMP(&rat->rat_tm, &now, <=)) { if (((*rat->rat_expire)(rat->rat_expire_data) == NULL)) continue; /* the timer was removed */ if (rat->rat_update) (*rat->rat_update)(rat->rat_update_data, &rat->rat_tm); - TIMEVAL_ADD(&rat->rat_tm, &now, &rat->rat_tm); + TS_ADD(&rat->rat_tm, &now, &rat->rat_tm); } - if (TIMEVAL_LT(&rat->rat_tm, &tm_max)) + if (TS_CMP(&rat->rat_tm, &tm_max, <)) tm_max = rat->rat_tm; } - if (TIMEVAL_EQUAL(&tm_max, &tm_limit)) { + if (TS_CMP(&tm_max, &tm_limit, ==)) { /* no need to timeout */ return (NULL); - } else if (TIMEVAL_LT(&tm_max, &now)) { + } else if (TS_CMP(&tm_max, &now, <)) { /* this may occur when the interval is too small */ - returnval.tv_sec = returnval.tv_usec = 0; + returnval.tv_sec = returnval.tv_nsec = 0; } else - TIMEVAL_SUB(&tm_max, &now, &returnval); + TS_SUB(&tm_max, &now, &returnval); return (&returnval); } void -rtadvd_set_timer(struct timeval *tm, struct rtadvd_timer *rat) +rtadvd_set_timer(struct timespec *tm, struct rtadvd_timer *rat) { - struct timeval now; + struct timespec now; /* reset the timer */ - gettimeofday(&now, NULL); - TIMEVAL_ADD(&now, tm, &rat->rat_tm); + clock_gettime(CLOCK_MONOTONIC_FAST, &now); + TS_ADD(&now, tm, &rat->rat_tm); /* update the next expiration time */ - if (TIMEVAL_LT(&rat->rat_tm, &tm_max)) + if (TS_CMP(&rat->rat_tm, &tm_max, <)) tm_max = rat->rat_tm; return; diff --git a/usr.sbin/rtadvd/timer.h b/usr.sbin/rtadvd/timer.h index f70e0d1..4498aaf 100644 --- a/usr.sbin/rtadvd/timer.h +++ b/usr.sbin/rtadvd/timer.h @@ -35,18 +35,18 @@ struct rtadvd_timer { TAILQ_ENTRY(rtadvd_timer) rat_next; struct rainfo *rat_rai; - struct timeval rat_tm; + struct timespec rat_tm; struct rtadvd_timer *(*rat_expire)(void *); void *rat_expire_data; - void (*rat_update)(void *, struct timeval *); + void (*rat_update)(void *, struct timespec *); void *rat_update_data; }; void rtadvd_timer_init(void); void rtadvd_update_timeout_handler(void); struct rtadvd_timer *rtadvd_add_timer(struct rtadvd_timer *(*)(void *), - void (*)(void *, struct timeval *), void *, void *); -void rtadvd_set_timer(struct timeval *, + void (*)(void *, struct timespec *), void *, void *); +void rtadvd_set_timer(struct timespec *, struct rtadvd_timer *); void rtadvd_remove_timer(struct rtadvd_timer *); -struct timeval *rtadvd_check_timer(void); +struct timespec *rtadvd_check_timer(void); diff --git a/usr.sbin/rtadvd/timer_subr.c b/usr.sbin/rtadvd/timer_subr.c index 2bebdd3..0ddf0a4 100644 --- a/usr.sbin/rtadvd/timer_subr.c +++ b/usr.sbin/rtadvd/timer_subr.c @@ -30,69 +30,34 @@ * SUCH DAMAGE. */ -#include <sys/time.h> #include <sys/queue.h> #include <sys/socket.h> #include <syslog.h> #include <stdio.h> #include <inttypes.h> +#include <time.h> #include "timer.h" #include "timer_subr.h" -struct timeval * +struct timespec * rtadvd_timer_rest(struct rtadvd_timer *rat) { - static struct timeval returnval, now; + static struct timespec returnval, now; - gettimeofday(&now, NULL); - if (TIMEVAL_LEQ(&rat->rat_tm, &now)) { + clock_gettime(CLOCK_MONOTONIC_FAST, &now); + if (TS_CMP(&rat->rat_tm, &now, <=)) { syslog(LOG_DEBUG, "<%s> a timer must be expired, but not yet", __func__); - returnval.tv_sec = returnval.tv_usec = 0; + returnval.tv_sec = returnval.tv_nsec = 0; } else - TIMEVAL_SUB(&rat->rat_tm, &now, &returnval); + TS_SUB(&rat->rat_tm, &now, &returnval); return (&returnval); } -/* result = a + b */ -void -TIMEVAL_ADD(struct timeval *a, struct timeval *b, struct timeval *result) -{ - long l; - - if ((l = a->tv_usec + b->tv_usec) < MILLION) { - result->tv_usec = l; - result->tv_sec = a->tv_sec + b->tv_sec; - } - else { - result->tv_usec = l - MILLION; - result->tv_sec = a->tv_sec + b->tv_sec + 1; - } -} - -/* - * result = a - b - * XXX: this function assumes that a >= b. - */ -void -TIMEVAL_SUB(struct timeval *a, struct timeval *b, struct timeval *result) -{ - long l; - - if ((l = a->tv_usec - b->tv_usec) >= 0) { - result->tv_usec = l; - result->tv_sec = a->tv_sec - b->tv_sec; - } - else { - result->tv_usec = MILLION + l; - result->tv_sec = a->tv_sec - b->tv_sec - 1; - } -} - char * sec2str(uint32_t s, char *buf) { diff --git a/usr.sbin/rtadvd/timer_subr.h b/usr.sbin/rtadvd/timer_subr.h index 9ceddad..32e1bb1 100644 --- a/usr.sbin/rtadvd/timer_subr.h +++ b/usr.sbin/rtadvd/timer_subr.h @@ -31,27 +31,29 @@ */ #define SSBUFLEN 1024 -#define MILLION 1000000 -/* a < b */ -#define TIMEVAL_LT(a, b) \ - (((a)->tv_sec < (b)->tv_sec) || \ - (((a)->tv_sec == (b)->tv_sec) && \ - ((a)->tv_usec < (b)->tv_usec))) +#define TS_CMP(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#define TS_ADD(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 (0) +#define TS_SUB(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 (0) -/* a <= b */ -#define TIMEVAL_LEQ(a, b) \ - (((a)->tv_sec < (b)->tv_sec) || \ - (((a)->tv_sec == (b)->tv_sec) && \ - ((a)->tv_usec <= (b)->tv_usec))) - -#define TIMEVAL_EQUAL(a,b) \ - (((a)->tv_sec == (b)->tv_sec) && \ - ((a)->tv_usec == (b)->tv_usec)) - -struct timeval *rtadvd_timer_rest(struct rtadvd_timer *); -void TIMEVAL_ADD(struct timeval *, struct timeval *, - struct timeval *); -void TIMEVAL_SUB(struct timeval *, struct timeval *, - struct timeval *); +struct timespec *rtadvd_timer_rest(struct rtadvd_timer *); char *sec2str(uint32_t, char *buf); |