summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2015-05-06 15:21:56 +0000
committerRoy Marples <roy@marples.name>2015-05-06 15:21:56 +0000
commit474ba00c161e950a39111c7d3b37b3176d898b69 (patch)
tree5e330c923985da7f4672f1fc909aaf02747f6a4f /ipv6.c
parentbbba67d0f8a0b70dca42e43841e52f1ec0ea2d85 (diff)
downloaddhcpcd-474ba00c161e950a39111c7d3b37b3176d898b69.tar.xz
Fix IPv6 prefix underflow when confirming deprecated but valid leases.
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/ipv6.c b/ipv6.c
index 66c2fca1..759bc1e3 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -689,20 +689,32 @@ ipv6_addaddr(struct ipv6_addr *ap, const struct timespec *now)
now = &n;
}
timespecsub(now, &ap->acquired, &n);
- if (ap->prefix_pltime != ND6_INFINITE_LIFETIME)
+ if (ap->prefix_pltime != ND6_INFINITE_LIFETIME) {
ap->prefix_pltime -= (uint32_t)n.tv_sec;
+ /* This can happen when confirming a
+ * deprecated but still valid lease. */
+ if (ap->prefix_pltime > pltime)
+ ap->prefix_pltime = 0;
+ }
if (ap->prefix_vltime != ND6_INFINITE_LIFETIME)
ap->prefix_vltime -= (uint32_t)n.tv_sec;
- }
- if (if_addaddress6(ap) == -1) {
- logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
#if 0
logger(ap->iface->ctx, LOG_DEBUG,
+ "%s: acquired %lld.%.9ld, now %lld.%.9ld, diff %lld.%.9ld",
+ ap->iface->name,
+ (long long)ap->acquired.tv_sec, ap->acquired.tv_nsec,
+ (long long)now->tv_sec, now->tv_nsec,
+ (long long)n.tv_sec, n.tv_nsec);
+ logger(ap->iface->ctx, LOG_DEBUG,
"%s: adj pltime %"PRIu32" seconds, "
"vltime %"PRIu32" seconds",
ap->iface->name, ap->prefix_pltime, ap->prefix_vltime);
#endif
+ }
+
+ if (if_addaddress6(ap) == -1) {
+ logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
/* Restore real pltime and vltime */
ap->prefix_pltime = pltime;
ap->prefix_vltime = vltime;