- 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
This commit is contained in:
Hiroki Sato 2013-08-05 20:13:02 +00:00
parent 456597e7bd
commit 7d26db1792
23 changed files with 287 additions and 253 deletions

View File

@ -1931,8 +1931,8 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
ltime = ND6_INFINITE_LIFETIME;
else {
if (ifa6->ia6_lifetime.ia6t_expire >
time_second)
ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_second);
time_uptime)
ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_uptime);
else
ltime = 0;
}

View File

@ -523,12 +523,12 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
/* sanity for overflow - beware unsigned */
lt = &ifr->ifr_ifru.ifru_lifetime;
if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
lt->ia6t_vltime + time_second < time_second) {
lt->ia6t_vltime + time_uptime < time_uptime) {
error = EINVAL;
goto out;
}
if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
lt->ia6t_pltime + time_second < time_second) {
lt->ia6t_pltime + time_uptime < time_uptime) {
error = EINVAL;
goto out;
}
@ -632,12 +632,12 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
/* for sanity */
if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
ia->ia6_lifetime.ia6t_expire =
time_second + ia->ia6_lifetime.ia6t_vltime;
time_uptime + ia->ia6_lifetime.ia6t_vltime;
} else
ia->ia6_lifetime.ia6t_expire = 0;
if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
ia->ia6_lifetime.ia6t_preferred =
time_second + ia->ia6_lifetime.ia6t_pltime;
time_uptime + ia->ia6_lifetime.ia6t_pltime;
} else
ia->ia6_lifetime.ia6t_preferred = 0;
break;
@ -1140,7 +1140,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
ia->ia_addr.sin6_family = AF_INET6;
ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
ia->ia6_createtime = time_second;
ia->ia6_createtime = time_uptime;
if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
/*
* XXX: some functions expect that ifa_dstaddr is not
@ -1167,7 +1167,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
}
/* update timestamp */
ia->ia6_updatetime = time_second;
ia->ia6_updatetime = time_uptime;
/* set prefix mask */
if (ifra->ifra_prefixmask.sin6_len) {
@ -1217,12 +1217,12 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
ia->ia6_lifetime = ifra->ifra_lifetime;
if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
ia->ia6_lifetime.ia6t_expire =
time_second + ia->ia6_lifetime.ia6t_vltime;
time_uptime + ia->ia6_lifetime.ia6t_vltime;
} else
ia->ia6_lifetime.ia6t_expire = 0;
if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
ia->ia6_lifetime.ia6t_preferred =
time_second + ia->ia6_lifetime.ia6t_pltime;
time_uptime + ia->ia6_lifetime.ia6t_pltime;
} else
ia->ia6_lifetime.ia6t_preferred = 0;
@ -1240,7 +1240,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
*/
if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
ia->ia6_lifetime.ia6t_pltime = 0;
ia->ia6_lifetime.ia6t_preferred = time_second;
ia->ia6_lifetime.ia6t_preferred = time_uptime;
}
/*
* Make the address tentative before joining multicast addresses,

View File

@ -361,11 +361,11 @@ extern const struct in6_addr in6addr_linklocal_allv2routers;
#define IFA6_IS_DEPRECATED(a) \
((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
(u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \
(a)->ia6_lifetime.ia6t_pltime)
#define IFA6_IS_INVALID(a) \
((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
(u_int32_t)((time_uptime - (a)->ia6_updatetime)) > \
(a)->ia6_lifetime.ia6t_vltime)
#endif /* _KERNEL */

View File

@ -137,8 +137,8 @@ ip6_forward(struct mbuf *m, int srcrt)
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
IP6STAT_INC(ip6s_cantforward);
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
V_ip6_log_time = time_second;
if (V_ip6_log_time + V_ip6_log_interval < time_uptime) {
V_ip6_log_time = time_uptime;
log(LOG_DEBUG,
"cannot forward "
"from %s to %s nxt %d received on %s\n",
@ -405,8 +405,8 @@ ip6_forward(struct mbuf *m, int srcrt)
IP6STAT_INC(ip6s_badscope);
in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
V_ip6_log_time = time_second;
if (V_ip6_log_time + V_ip6_log_interval < time_uptime) {
V_ip6_log_time = time_uptime;
log(LOG_DEBUG,
"cannot forward "
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",

View File

@ -221,7 +221,7 @@ initid(struct randomtab *p)
p->ru_g = pmod(p->ru_gen, j, p->ru_n);
p->ru_counter = 0;
p->ru_reseed = time_second + p->ru_out;
p->ru_reseed = time_uptime + p->ru_out;
p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1));
}
@ -231,7 +231,7 @@ randomid(struct randomtab *p)
int i, n;
u_int32_t tmp;
if (p->ru_counter >= p->ru_max || time_second > p->ru_reseed)
if (p->ru_counter >= p->ru_max || time_uptime > p->ru_reseed)
initid(p);
tmp = arc4random();

View File

@ -1103,8 +1103,8 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
*/
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
IP6STAT_INC(ip6s_cantforward);
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
V_ip6_log_time = time_second;
if (V_ip6_log_time + V_ip6_log_interval < time_uptime) {
V_ip6_log_time = time_uptime;
log(LOG_DEBUG,
"cannot forward "
"from %s to %s nxt %d received on %s\n",

View File

@ -428,7 +428,7 @@ nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
ln->ln_ntick = 0;
canceled = callout_stop(&ln->ln_timer_ch);
} else {
ln->la_expire = time_second + tick / hz;
ln->la_expire = time_uptime + tick / hz;
LLE_ADDREF(ln);
if (tick > INT_MAX) {
ln->ln_ntick = tick - INT_MAX;
@ -591,7 +591,7 @@ nd6_timer(void *arg)
/* expire default router list */
TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
if (dr->expire && dr->expire < time_second)
if (dr->expire && dr->expire < time_uptime)
defrtrlist_del(dr);
}
@ -675,7 +675,7 @@ nd6_timer(void *arg)
* prefix is not necessary.
*/
if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) {
/*
* address expiration and prefix expiration are
@ -1033,9 +1033,9 @@ nd6_free(struct llentry *ln, int gc)
* XXX: the check for ln_state would be redundant,
* but we intentionally keep it just in case.
*/
if (dr->expire > time_second)
if (dr->expire > time_uptime)
nd6_llinfo_settimer_locked(ln,
(dr->expire - time_second) * hz);
(dr->expire - time_uptime) * hz);
else
nd6_llinfo_settimer_locked(ln,
(long)V_nd6_gctimer * hz);

View File

@ -282,7 +282,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
dr0.rtlifetime = 0;
else
dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
dr0.expire = time_second + dr0.rtlifetime;
dr0.expire = time_uptime + dr0.rtlifetime;
dr0.ifp = ifp;
/* unspecified or not? (RFC 2461 6.3.4) */
if (advreachable) {
@ -874,7 +874,7 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
free(new, M_IP6NDP);
return(error);
}
new->ndpr_lastupdate = time_second;
new->ndpr_lastupdate = time_uptime;
if (newp != NULL)
*newp = new;
@ -998,7 +998,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
pr->ndpr_vltime = new->ndpr_vltime;
pr->ndpr_pltime = new->ndpr_pltime;
(void)in6_init_prefix_ltimes(pr); /* XXX error case? */
pr->ndpr_lastupdate = time_second;
pr->ndpr_lastupdate = time_uptime;
}
if (new->ndpr_raf_onlink &&
@ -1136,7 +1136,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
remaininglifetime = ND6_INFINITE_LIFETIME;
else if (time_second - ifa6->ia6_updatetime >
else if (time_uptime - ifa6->ia6_updatetime >
lt6_tmp.ia6t_vltime) {
/*
* The case of "invalid" address. We should usually
@ -1145,7 +1145,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
remaininglifetime = 0;
} else
remaininglifetime = lt6_tmp.ia6t_vltime -
(time_second - ifa6->ia6_updatetime);
(time_uptime - ifa6->ia6_updatetime);
/* when not updating, keep the current stored lifetime. */
lt6_tmp.ia6t_vltime = remaininglifetime;
@ -1181,18 +1181,18 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
u_int32_t maxvltime, maxpltime;
if (V_ip6_temp_valid_lifetime >
(u_int32_t)((time_second - ifa6->ia6_createtime) +
(u_int32_t)((time_uptime - ifa6->ia6_createtime) +
V_ip6_desync_factor)) {
maxvltime = V_ip6_temp_valid_lifetime -
(time_second - ifa6->ia6_createtime) -
(time_uptime - ifa6->ia6_createtime) -
V_ip6_desync_factor;
} else
maxvltime = 0;
if (V_ip6_temp_preferred_lifetime >
(u_int32_t)((time_second - ifa6->ia6_createtime) +
(u_int32_t)((time_uptime - ifa6->ia6_createtime) +
V_ip6_desync_factor)) {
maxpltime = V_ip6_temp_preferred_lifetime -
(time_second - ifa6->ia6_createtime) -
(time_uptime - ifa6->ia6_createtime) -
V_ip6_desync_factor;
} else
maxpltime = 0;
@ -1207,7 +1207,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
}
}
ifa6->ia6_lifetime = lt6_tmp;
ifa6->ia6_updatetime = time_second;
ifa6->ia6_updatetime = time_uptime;
}
IF_ADDR_RUNLOCK(ifp);
if (ia6_match == NULL && new->ndpr_vltime) {
@ -1988,7 +1988,7 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
if (ia0->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
vltime0 = IFA6_IS_INVALID(ia0) ? 0 :
(ia0->ia6_lifetime.ia6t_vltime -
(time_second - ia0->ia6_updatetime));
(time_uptime - ia0->ia6_updatetime));
if (vltime0 > V_ip6_temp_valid_lifetime)
vltime0 = V_ip6_temp_valid_lifetime;
} else
@ -1996,7 +1996,7 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
if (ia0->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
pltime0 = IFA6_IS_DEPRECATED(ia0) ? 0 :
(ia0->ia6_lifetime.ia6t_pltime -
(time_second - ia0->ia6_updatetime));
(time_uptime - ia0->ia6_updatetime));
if (pltime0 > V_ip6_temp_preferred_lifetime - V_ip6_desync_factor){
pltime0 = V_ip6_temp_preferred_lifetime -
V_ip6_desync_factor;
@ -2054,11 +2054,11 @@ in6_init_prefix_ltimes(struct nd_prefix *ndpr)
if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
ndpr->ndpr_preferred = 0;
else
ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
ndpr->ndpr_preferred = time_uptime + ndpr->ndpr_pltime;
if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
ndpr->ndpr_expire = 0;
else
ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
ndpr->ndpr_expire = time_uptime + ndpr->ndpr_vltime;
return 0;
}
@ -2070,7 +2070,7 @@ in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
lt6->ia6t_expire = 0;
else {
lt6->ia6t_expire = time_second;
lt6->ia6t_expire = time_uptime;
lt6->ia6t_expire += lt6->ia6t_vltime;
}
@ -2078,7 +2078,7 @@ in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
lt6->ia6t_preferred = 0;
else {
lt6->ia6t_preferred = time_second;
lt6->ia6t_preferred = time_uptime;
lt6->ia6t_preferred += lt6->ia6t_pltime;
}
}

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1000040 /* Master, propagated to newvers */
#define __FreeBSD_version 1000041 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

View File

@ -79,7 +79,6 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <net/if.h>
@ -105,6 +104,7 @@
#include <paths.h>
#include <err.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include "gmt2local.h"
@ -125,6 +125,7 @@ static int tflag;
static int32_t thiszone; /* time difference with gmt */
static int s = -1;
static int repeat = 0;
static struct timespec ts, ts0;
char ntop_buf[INET6_ADDRSTRLEN]; /* inet_ntop() */
char host_buf[NI_MAXHOST]; /* getnameinfo() */
@ -153,7 +154,7 @@ static void getdefif(void);
static void setdefif(char *);
#endif
static char *sec2str(time_t);
static void ts_print(const struct timeval *);
static void ts_print(const struct timespec *);
#ifdef ICMPV6CTL_ND6_DRLIST
static char *rtpref_str[] = {
@ -164,6 +165,16 @@ static char *rtpref_str[] = {
};
#endif
#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)
int mode = 0;
char *arg = NULL;
@ -172,10 +183,14 @@ main(argc, argv)
int argc;
char **argv;
{
struct timespec now;
int ch;
pid = getpid();
thiszone = gmt2local(0);
clock_gettime(CLOCK_REALTIME_FAST, &now);
clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
TS_SUB(&now, &ts, &ts0);
while ((ch = getopt(argc, argv, "acd:f:Ii:nprstA:HPR")) != -1)
switch (ch) {
case 'a':
@ -367,7 +382,8 @@ getsocket()
struct sockaddr_in6 so_mask = {sizeof(so_mask), AF_INET6 };
struct sockaddr_in6 blank_sin = {sizeof(blank_sin), AF_INET6 }, sin_m;
struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
int expire_time, flags, found_entry;
static time_t expire_time;
static int flags, found_entry;
struct {
struct rt_msghdr m_rtm;
char m_space[512];
@ -412,10 +428,10 @@ set(argc, argv)
flags = expire_time = 0;
while (argc-- > 0) {
if (strncmp(argv[0], "temp", 4) == 0) {
struct timeval time;
struct timespec now;
gettimeofday(&time, 0);
expire_time = time.tv_sec + 20 * 60;
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
expire_time = now.tv_sec + 20 * 60;
} else if (strncmp(argv[0], "proxy", 5) == 0)
flags |= RTF_ANNOUNCE;
argv++;
@ -566,7 +582,7 @@ dump(addr, cflag)
struct sockaddr_dl *sdl;
extern int h_errno;
struct in6_nbrinfo *nbi;
struct timeval time;
struct timespec now;
int addrwidth;
int llwidth;
int ifwidth;
@ -653,9 +669,9 @@ again:;
#endif
continue;
}
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
if (tflag)
ts_print(&time);
ts_print(&now);
addrwidth = strlen(host_buf);
if (addrwidth < W_ADDR)
@ -676,9 +692,9 @@ again:;
/* Print neighbor discovery specific informations */
nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
if (nbi) {
if (nbi->expire > time.tv_sec) {
if (nbi->expire > now.tv_sec) {
printf(" %-9.9s",
sec2str(nbi->expire - time.tv_sec));
sec2str(nbi->expire - now.tv_sec));
} else if (nbi->expire == 0)
printf(" %-9.9s", "permanent");
else
@ -1075,7 +1091,7 @@ rtrlist()
char *buf;
struct in6_defrouter *p, *ep;
size_t l;
struct timeval time;
struct timespec now;
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) {
err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)");
@ -1110,18 +1126,18 @@ rtrlist()
rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff;
printf(", pref=%s", rtpref_str[rtpref]);
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
if (p->expire == 0)
printf(", expire=Never\n");
else
printf(", expire=%s\n",
sec2str(p->expire - time.tv_sec));
sec2str(p->expire - now.tv_sec));
}
free(buf);
#else
struct in6_drlist dr;
int s, i;
struct timeval time;
struct timespec now;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
err(1, "socket");
@ -1150,12 +1166,12 @@ rtrlist()
printf(", flags=%s%s",
DR.flags & ND_RA_FLAG_MANAGED ? "M" : "",
DR.flags & ND_RA_FLAG_OTHER ? "O" : "");
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
if (DR.expire == 0)
printf(", expire=Never\n");
else
printf(", expire=%s\n",
sec2str(DR.expire - time.tv_sec));
sec2str(DR.expire - now.tv_sec));
}
#undef DR
close(s);
@ -1171,7 +1187,7 @@ plist()
struct in6_prefix *p, *ep, *n;
struct sockaddr_in6 *advrtr;
size_t l;
struct timeval time;
struct timespec now;
const int niflags = NI_NUMERICHOST;
int ninflags = nflag ? NI_NUMERICHOST : 0;
char namebuf[NI_MAXHOST];
@ -1202,7 +1218,7 @@ plist()
printf("%s/%d if=%s\n", namebuf, p->prefixlen,
if_indextoname(p->if_index, ifix_buf));
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
/*
* meaning of fields, especially flags, is very different
* by origin. notify the difference to the users.
@ -1228,9 +1244,9 @@ plist()
printf(", pltime=%lu", (unsigned long)p->pltime);
if (p->expire == 0)
printf(", expire=Never");
else if (p->expire >= time.tv_sec)
else if (p->expire >= now.tv_sec)
printf(", expire=%s",
sec2str(p->expire - time.tv_sec));
sec2str(p->expire - now.tv_sec));
else
printf(", expired");
printf(", ref=%d", p->refcnt);
@ -1278,9 +1294,9 @@ plist()
#else
struct in6_prlist pr;
int s, i;
struct timeval time;
struct timespec now;
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
err(1, "socket");
@ -1316,7 +1332,7 @@ plist()
printf("%s/%d if=%s\n", namebuf, PR.prefixlen,
if_indextoname(PR.if_index, ifix_buf));
gettimeofday(&time, 0);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
/*
* meaning of fields, especially flags, is very different
* by origin. notify the difference to the users.
@ -1352,9 +1368,9 @@ plist()
printf(", pltime=%lu", PR.pltime);
if (PR.expire == 0)
printf(", expire=Never");
else if (PR.expire >= time.tv_sec)
else if (PR.expire >= now.tv_sec)
printf(", expire=%s",
sec2str(PR.expire - time.tv_sec));
sec2str(PR.expire - now.tv_sec));
else
printf(", expired");
#ifdef NDPRF_ONLINK
@ -1577,15 +1593,15 @@ sec2str(total)
* from tcpdump/util.c
*/
static void
ts_print(tvp)
const struct timeval *tvp;
ts_print(tsp)
const struct timespec *tsp;
{
int s;
/* Default */
s = (tvp->tv_sec + thiszone) % 86400;
s = (tsp->tv_sec + thiszone + ts0.tv_sec) % 86400;
(void)printf("%02d:%02d:%02d.%06u ",
s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tsp->tv_nsec / 1000);
}
#undef NEXTADDR

View File

@ -55,6 +55,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <syslog.h>
#include <time.h>
#include <err.h>
#include "pathnames.h"
@ -416,6 +417,7 @@ action_show(int argc, char **argv)
char argv_dnssl[IFNAMSIZ + sizeof(":dnssl=")];
char ssbuf[SSBUFLEN];
struct timespec now, ts0, ts;
struct ctrl_msg_pl cp;
struct ifinfo *ifi;
TAILQ_HEAD(, ifinfo) ifl = TAILQ_HEAD_INITIALIZER(ifl);
@ -464,6 +466,10 @@ action_show(int argc, char **argv)
}
}
clock_gettime(CLOCK_REALTIME_FAST, &now);
clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
TS_SUB(&now, &ts, &ts0);
TAILQ_FOREACH(ifi, &ifl, ifi_next) {
struct ifinfo *ifi_s;
struct rtadvd_timer *rat;
@ -615,12 +621,20 @@ action_show(int argc, char **argv)
rat = (struct rtadvd_timer *)cp.cp_val;
}
printf("\tNext RA send: %s",
(rat == NULL) ? "never\n" :
ctime((time_t *)&rat->rat_tm.tv_sec));
printf("\tLast RA sent: %s",
(ifi_s->ifi_ra_lastsent.tv_sec == 0) ? "never\n" :
ctime((time_t *)&ifi_s->ifi_ra_lastsent.tv_sec));
printf("\tNext RA send: ");
if (rat == NULL)
printf("never\n");
else {
ts.tv_sec = rat->rat_tm.tv_sec + ts0.tv_sec;
printf("%s", ctime(&ts.tv_sec));
}
printf("\tLast RA send: ");
if (ifi_s->ifi_ra_lastsent.tv_sec == 0)
printf("never\n");
else {
ts.tv_sec = ifi_s->ifi_ra_lastsent.tv_sec + ts0.tv_sec;
printf("%s", ctime(&ts.tv_sec));
}
if (rai->rai_clockskew)
printf("\tClock skew: %" PRIu16 "sec\n",
rai->rai_clockskew);
@ -747,9 +761,9 @@ action_show_prefix(struct prefix *pfx)
{
char ntopbuf[INET6_ADDRSTRLEN];
char ssbuf[SSBUFLEN];
struct timeval now;
struct timespec now;
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
printf("\t %s/%d", inet_ntop(AF_INET6, &pfx->pfx_prefix,
ntopbuf, sizeof(ntopbuf)), pfx->pfx_prefixlen);
@ -800,7 +814,7 @@ action_show_prefix(struct prefix *pfx)
printf("<none>");
if (pfx->pfx_timer) {
struct timeval *rest;
struct timespec *rest;
rest = rtadvd_timer_rest(pfx->pfx_timer);
if (rest) { /* XXX: what if not? */

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -32,7 +32,6 @@
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/queue.h>
@ -62,10 +61,10 @@ dump_interface_status(void)
struct ifinfo *ifi;
struct rainfo *rai;
struct ra_opt *rao;
struct timeval now;
struct timespec now;
char ntopbuf[INET6_ADDRSTRLEN];
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
fprintf(fp, "Interface %s\n", ifi->ifname);
@ -87,12 +86,12 @@ dump_interface_status(void)
fprintf(fp, " probes: %d, dadcount = %d\n",
ifi->probes, ifi->dadcount);
if (ifi->timer.tv_sec == tm_max.tv_sec &&
ifi->timer.tv_usec == tm_max.tv_usec)
ifi->timer.tv_nsec == tm_max.tv_nsec)
fprintf(fp, " no timer\n");
else {
fprintf(fp, " timer: interval=%d:%d, expire=%s\n",
(int)ifi->timer.tv_sec,
(int)ifi->timer.tv_usec,
(int)ifi->timer.tv_nsec / 1000,
(ifi->expire.tv_sec < now.tv_sec) ? "expired"
: sec2str(&ifi->expire));
}
@ -137,7 +136,7 @@ rtsold_dump_file(const char *dumpfile)
}
const char *
sec2str(const struct timeval *total)
sec2str(const struct timespec *total)
{
static char result[256];
int days, hours, mins, secs;
@ -145,14 +144,14 @@ sec2str(const struct timeval *total)
char *p = result;
char *ep = &result[sizeof(result)];
int n;
struct timeval now;
struct timespec now;
time_t tsec;
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
tsec = total->tv_sec;
tsec += total->tv_usec / 1000000;
tsec += total->tv_nsec / 1000 / 1000000;
tsec -= now.tv_sec;
tsec -= now.tv_usec / 1000000;
tsec -= now.tv_nsec / 1000 / 1000000;
days = tsec / 3600 / 24;
hours = (tsec / 3600) % 24;

View File

@ -35,7 +35,6 @@
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/stat.h>
@ -58,6 +57,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <err.h>
#include <errno.h>
#include <string.h>
@ -256,8 +256,8 @@ rtsol_input(int s)
size_t len;
char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1];
char dname[NI_MAXHOST];
struct timeval now;
struct timeval lifetime;
struct timespec now;
struct timespec lifetime;
int newent_rai;
int newent_rao;
@ -376,7 +376,7 @@ rtsol_input(int s)
ifi->otherconfig = 1;
CALL_SCRIPT(OTHER, NULL);
}
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
newent_rai = 0;
rai = find_rainfo(ifi, &from);
if (rai == NULL) {
@ -472,7 +472,7 @@ rtsol_input(int s)
memset(&lifetime, 0, sizeof(lifetime));
lifetime.tv_sec =
ntohl(rdnss->nd_opt_rdnss_lifetime);
timeradd(&now, &lifetime, &rao->rao_expire);
TS_ADD(&now, &lifetime, &rao->rao_expire);
if (newent_rao)
TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
@ -531,7 +531,7 @@ rtsol_input(int s)
memset(&lifetime, 0, sizeof(lifetime));
lifetime.tv_sec =
ntohl(dnssl->nd_opt_dnssl_lifetime);
timeradd(&now, &lifetime, &rao->rao_expire);
TS_ADD(&now, &lifetime, &rao->rao_expire);
if (newent_rao)
TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
@ -574,7 +574,7 @@ ra_opt_handler(struct ifinfo *ifi)
struct ra_opt *rao;
struct rainfo *rai;
struct script_msg *smp1, *smp2, *smp3;
struct timeval now;
struct timespec now;
struct script_msg_head_t sm_rdnss_head =
TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
struct script_msg_head_t sm_dnssl_head =
@ -584,7 +584,7 @@ ra_opt_handler(struct ifinfo *ifi)
dcount = 0;
dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
/*
* All options from multiple RAs with the same or different
@ -595,7 +595,7 @@ ra_opt_handler(struct ifinfo *ifi)
TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
switch (rao->rao_type) {
case ND_OPT_RDNSS:
if (timercmp(&now, &rao->rao_expire, >)) {
if (TS_CMP(&now, &rao->rao_expire, >)) {
warnmsg(LOG_INFO, __func__,
"expired rdnss entry: %s",
(char *)rao->rao_msg);
@ -617,7 +617,7 @@ ra_opt_handler(struct ifinfo *ifi)
break;
case ND_OPT_DNSSL:
if (timercmp(&now, &rao->rao_expire, >)) {
if (TS_CMP(&now, &rao->rao_expire, >)) {
warnmsg(LOG_INFO, __func__,
"expired dnssl entry: %s",
(char *)rao->rao_msg);

View File

@ -33,7 +33,6 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/param.h>
@ -54,6 +53,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <err.h>
#include <stdarg.h>
@ -68,7 +68,7 @@
#define RTSOL_PIDFILE "/var/run/rtsold.pid";
struct ifinfo *iflist;
struct timeval tm_max = {0x7fffffff, 0x7fffffff};
struct timespec tm_max;
static int log_upto = 999;
static int fflag = 0;
@ -105,7 +105,7 @@ static int ifreconfig(char *);
#endif
static int make_packet(struct ifinfo *);
static struct timeval *rtsol_check_timer(void);
static struct timespec *rtsol_check_timer(void);
#ifndef SMALL
static void rtsold_set_dump_file(int);
@ -116,7 +116,7 @@ int
main(int argc, char **argv)
{
int s, ch, once = 0;
struct timeval *timeout;
struct timespec *timeout;
const char *opts;
#ifdef HAVE_POLL_H
struct pollfd set[2];
@ -187,6 +187,12 @@ main(int argc, char **argv)
exit(1);
}
/* Generate maximum time in timespec. */
memset(&tm_max.tv_sec, 0xff, sizeof(tm_max.tv_sec));
memset(&tm_max.tv_nsec, 0xff, sizeof(tm_max.tv_nsec));
tm_max.tv_sec &= ~(1UL << (sizeof(tm_max.tv_sec) * 8 - 1));
tm_max.tv_nsec &= ~(1UL << (sizeof(tm_max.tv_nsec) * 8 - 1));
/* set log level */
if (dflag > 1)
log_upto = LOG_DEBUG;
@ -363,7 +369,7 @@ main(int argc, char **argv)
break;
}
#ifdef HAVE_POLL_H
e = poll(set, 2, timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFTIM);
e = poll(set, 2, timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 1000 / 1000) : INFTIM);
#else
e = select(maxfd + 1, selectfdp, NULL, NULL, timeout);
#endif
@ -603,22 +609,22 @@ make_packet(struct ifinfo *ifi)
return (0);
}
static struct timeval *
static struct timespec *
rtsol_check_timer(void)
{
static struct timeval returnval;
struct timeval now, rtsol_timer;
static struct timespec returnval;
struct timespec now, rtsol_timer;
struct ifinfo *ifi;
struct rainfo *rai;
struct ra_opt *rao;
int flags;
gettimeofday(&now, NULL);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
rtsol_timer = tm_max;
TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
if (timercmp(&ifi->expire, &now, <=)) {
if (TS_CMP(&ifi->expire, &now, <=)) {
warnmsg(LOG_DEBUG, __func__, "timer expiration on %s, "
"state = %d", ifi->ifname, ifi->state);
@ -711,7 +717,7 @@ rtsol_check_timer(void)
"type=%d, msg=%s, expire=%s",
rao->rao_type, (char *)rao->rao_msg,
sec2str(&rao->rao_expire));
if (timercmp(&now, &rao->rao_expire,
if (TS_CMP(&now, &rao->rao_expire,
>=)) {
warnmsg(LOG_DEBUG, __func__,
"RA expiration timer: "
@ -728,21 +734,21 @@ rtsol_check_timer(void)
if (expire)
ra_opt_handler(ifi);
}
if (timercmp(&ifi->expire, &rtsol_timer, <))
if (TS_CMP(&ifi->expire, &rtsol_timer, <))
rtsol_timer = ifi->expire;
}
if (timercmp(&rtsol_timer, &tm_max, ==)) {
if (TS_CMP(&rtsol_timer, &tm_max, ==)) {
warnmsg(LOG_DEBUG, __func__, "there is no timer");
return (NULL);
} else if (timercmp(&rtsol_timer, &now, <))
} else if (TS_CMP(&rtsol_timer, &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
timersub(&rtsol_timer, &now, &returnval);
TS_SUB(&rtsol_timer, &now, &returnval);
now.tv_sec += returnval.tv_sec;
now.tv_usec += returnval.tv_usec;
now.tv_nsec += returnval.tv_nsec;
warnmsg(LOG_DEBUG, __func__, "New timer is %s",
sec2str(&now));
@ -755,7 +761,7 @@ rtsol_timer_update(struct ifinfo *ifi)
#define MILLION 1000000
#define DADRETRY 10 /* XXX: adhoc */
long interval;
struct timeval now;
struct timespec now;
bzero(&ifi->timer, sizeof(ifi->timer));
@ -783,7 +789,7 @@ rtsol_timer_update(struct ifinfo *ifi)
interval = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY * MILLION);
#endif
ifi->timer.tv_sec = interval / MILLION;
ifi->timer.tv_usec = interval % MILLION;
ifi->timer.tv_nsec = (interval % MILLION) * 1000;
break;
case IFS_PROBE:
if (ifi->probes < MAX_RTR_SOLICITATIONS)
@ -807,16 +813,16 @@ rtsol_timer_update(struct ifinfo *ifi)
}
/* reset the timer */
if (timercmp(&ifi->timer, &tm_max, ==)) {
if (TS_CMP(&ifi->timer, &tm_max, ==)) {
ifi->expire = tm_max;
warnmsg(LOG_DEBUG, __func__,
"stop timer for %s", ifi->ifname);
} else {
gettimeofday(&now, NULL);
timeradd(&now, &ifi->timer, &ifi->expire);
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
TS_ADD(&now, &ifi->timer, &ifi->expire);
now.tv_sec += ifi->timer.tv_sec;
now.tv_usec += ifi->timer.tv_usec;
now.tv_nsec += ifi->timer.tv_nsec;
warnmsg(LOG_DEBUG, __func__, "set timer for %s to %s",
ifi->ifname, sec2str(&now));
}

View File

@ -43,7 +43,7 @@ struct ra_opt {
TAILQ_ENTRY(ra_opt) rao_next;
u_int8_t rao_type;
struct timeval rao_expire;
struct timespec rao_expire;
size_t rao_len;
void *rao_msg;
};
@ -73,8 +73,8 @@ struct ifinfo {
int state;
int probes;
int dadcount;
struct timeval timer;
struct timeval expire;
struct timespec timer;
struct timespec expire;
int errors; /* # of errors we've got - detect wedge */
#define IFI_DNSOPT_STATE_NOINFO 0
#define IFI_DNSOPT_STATE_RECEIVED 1
@ -124,8 +124,31 @@ extern TAILQ_HEAD(ifinfo_head_t, ifinfo) ifinfo_head;
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
#endif
#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)
/* rtsold.c */
extern struct timeval tm_max;
extern struct timespec tm_max;
extern int dflag;
extern int aflag;
extern int Fflag;
@ -163,7 +186,7 @@ extern void defrouter_probe(struct ifinfo *);
/* dump.c */
extern void rtsold_dump_file(const char *);
extern const char *sec2str(const struct timeval *);
extern const char *sec2str(const struct timespec *);
/* rtsock.c */
extern int rtsock_open(void);