summaryrefslogtreecommitdiffstats
path: root/src/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-01-01 11:18:49 +0000
committerRoy Marples <roy@marples.name>2020-01-01 11:18:49 +0000
commit16c11c9dd1e561b9fb6eeb2d454c5707a442ab0c (patch)
tree8f445d3873c92532aa467f98d4db5aecc6744925 /src/ipv6.c
parent1be93cd89121a59b71aa4f64550a0af181cdd740 (diff)
downloaddhcpcd-16c11c9dd1e561b9fb6eeb2d454c5707a442ab0c.tar.xz
eloop: Allow for for timeouts greater than time_t and time wrapping
On some systems time_t is int32_t. However, on wire timeouts are generally uint32_t. As such, we need to avoid using timespec internally except to record when the timeout was created. Instead, record the timeout as unsigned int seconds and long nanoseconds. On long running systems using time_t as int32_t, monotonic time would wrap after approximately 68 years. It's highly unlikely dhcpcd would be running for so long, but just incase it does, the code should now cope.
Diffstat (limited to 'src/ipv6.c')
-rw-r--r--src/ipv6.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/src/ipv6.c b/src/ipv6.c
index 08a4ebf3..7b2e8e67 100644
--- a/src/ipv6.c
+++ b/src/ipv6.c
@@ -729,7 +729,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
ia->prefix_vltime &&
ip6_use_tempaddr(ifp->name))
eloop_timeout_add_sec(ifp->ctx->eloop,
- (time_t)ia->prefix_pltime - REGEN_ADVANCE,
+ ia->prefix_pltime - REGEN_ADVANCE,
ipv6_regentempaddr, ia);
#endif
@@ -1879,7 +1879,7 @@ static void
ipv6_regen_desync(struct interface *ifp, int force)
{
struct ipv6_state *state;
- time_t max;
+ unsigned int max, pref;
state = IPV6_STATE(ifp);
@@ -1887,15 +1887,14 @@ ipv6_regen_desync(struct interface *ifp, int force)
* greater than TEMP_VALID_LIFETIME - REGEN_ADVANCE.
* I believe this is an error and it should be never be greateter than
* TEMP_PREFERRED_LIFETIME - REGEN_ADVANCE. */
- max = ip6_temp_preferred_lifetime(ifp->name) - REGEN_ADVANCE;
+ pref = (unsigned int)ip6_temp_preferred_lifetime(ifp->name);
+ max = pref - REGEN_ADVANCE;
if (state->desync_factor && !force && state->desync_factor < max)
return;
if (state->desync_factor == 0)
state->desync_factor =
- (time_t)arc4random_uniform(MIN(MAX_DESYNC_FACTOR,
- (uint32_t)max));
- max = ip6_temp_preferred_lifetime(ifp->name) -
- state->desync_factor - REGEN_ADVANCE;
+ arc4random_uniform(MIN(MAX_DESYNC_FACTOR, max));
+ max = pref - state->desync_factor - REGEN_ADVANCE;
eloop_timeout_add_sec(ifp->ctx->eloop, max, ipv6_regentempifid, ifp);
}
@@ -2050,8 +2049,8 @@ again:
ipv6_regen_desync(ia->iface, 0);
/* RFC4941 Section 3.3.4 */
- i = (uint32_t)(ip6_temp_preferred_lifetime(ia0->iface->name) -
- state->desync_factor);
+ i = (uint32_t)ip6_temp_preferred_lifetime(ia0->iface->name) -
+ state->desync_factor;
ia->prefix_pltime = MIN(ia0->prefix_pltime, i);
i = (uint32_t)ip6_temp_valid_lifetime(ia0->iface->name);
ia->prefix_vltime = MIN(ia0->prefix_vltime, i);
@@ -2080,7 +2079,7 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
ap->prefix_pltime &&
IN6_ARE_ADDR_EQUAL(&ia->prefix, &ap->prefix))
{
- time_t max, ext;
+ unsigned int max, ext;
if (flags == 0) {
if (ap->prefix_pltime -
@@ -2109,10 +2108,11 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
/* RFC4941 Section 3.3.2
* Extend temporary times, but ensure that they
* never last beyond the system limit. */
- ext = ia->acquired.tv_sec + (time_t)ia->prefix_pltime;
- max = ap->created.tv_sec +
+ ext = (unsigned int)ia->acquired.tv_sec
+ + ia->prefix_pltime;
+ max = (unsigned int)(ap->created.tv_sec +
ip6_temp_preferred_lifetime(ap->iface->name) -
- state->desync_factor;
+ state->desync_factor);
if (ext < max)
ap->prefix_pltime = ia->prefix_pltime;
else
@@ -2120,9 +2120,10 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
(uint32_t)(max - ia->acquired.tv_sec);
valid:
- ext = ia->acquired.tv_sec + (time_t)ia->prefix_vltime;
- max = ap->created.tv_sec +
- ip6_temp_valid_lifetime(ap->iface->name);
+ ext = (unsigned int)ia->acquired.tv_sec +
+ ia->prefix_vltime;
+ max = (unsigned int)(ap->created.tv_sec +
+ ip6_temp_valid_lifetime(ap->iface->name));
if (ext < max)
ap->prefix_vltime = ia->prefix_vltime;
else