summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-12-16 20:20:01 +0000
committerRoy Marples <roy@marples.name>2014-12-16 20:20:01 +0000
commit0b3255ac875375112d273cca8223c22dfe3af12d (patch)
tree09c83f35a829d35bcba36be230b15ac3e3c449b8 /ipv6.c
parent3852009b98d8a5f3447c95e45cdcf7e995a22613 (diff)
downloaddhcpcd-0b3255ac875375112d273cca8223c22dfe3af12d.tar.xz
Store acquired time for each IPv6 address so we can correctly offset
pltime and vltime if we need to re-add them.
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/ipv6.c b/ipv6.c
index e66bddd8..6744140b 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -602,11 +602,13 @@ ipv6_deleteaddr(struct ipv6_addr *addr)
}
int
-ipv6_addaddr(struct ipv6_addr *ap)
+ipv6_addaddr(struct ipv6_addr *ap, const struct timeval *now)
{
struct interface *ifp;
struct ipv6_state *state;
struct ipv6_addr *nap;
+ struct timeval n;
+ uint32_t pltime, vltime;
/* Ensure no other interface has this address */
TAILQ_FOREACH(ifp, ap->iface->ctx->ifaces, next) {
@@ -623,6 +625,24 @@ ipv6_addaddr(struct ipv6_addr *ap)
}
}
+ /* Adjust plftime and vltime based on acquired time */
+ pltime = ap->prefix_pltime;
+ vltime = ap->prefix_vltime;
+ if (timerisset(&ap->acquired) &&
+ (ap->prefix_pltime != ND6_INFINITE_LIFETIME ||
+ ap->prefix_vltime != ND6_INFINITE_LIFETIME))
+ {
+ if (now == NULL) {
+ get_monotonic(&n);
+ now = &n;
+ }
+ timersub(now, &ap->acquired, &n);
+ if (ap->prefix_pltime != ND6_INFINITE_LIFETIME)
+ ap->prefix_pltime -= n.tv_sec;
+ if (ap->prefix_vltime != ND6_INFINITE_LIFETIME)
+ ap->prefix_vltime -= n.tv_sec;
+ }
+
syslog(ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
"%s: adding address %s", ap->iface->name, ap->saddr);
if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
@@ -630,8 +650,15 @@ ipv6_addaddr(struct ipv6_addr *ap)
ap->flags |= IPV6_AF_DADCOMPLETED;
if (if_addaddress6(ap) == -1) {
syslog(LOG_ERR, "if_addaddress6: %m");
+ /* Restore real pltime and vltime */
+ ap->prefix_pltime = pltime;
+ ap->prefix_vltime = vltime;
return -1;
}
+
+ /* Restore real pltime and vltime */
+ ap->prefix_pltime = pltime;
+ ap->prefix_vltime = vltime;
ap->flags &= ~IPV6_AF_NEW;
ap->flags |= IPV6_AF_ADDED;
if (ap->delegating_iface)
@@ -695,8 +722,10 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
{
struct ipv6_addr *ap, *apn, *apf;
ssize_t i;
+ struct timeval now;
i = 0;
+ timerclear(&now);
TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
if (ap->prefix_vltime == 0) {
if (ap->flags & IPV6_AF_ADDED) {
@@ -741,7 +770,9 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
apf->flags &= ~IPV6_AF_ADDED;
if (ap->flags & IPV6_AF_NEW)
i++;
- ipv6_addaddr(ap);
+ if (!timerisset(&now))
+ get_monotonic(&now);
+ ipv6_addaddr(ap, &now);
}
}
@@ -753,7 +784,9 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
const struct interface *ifd)
{
struct ipv6_addr *ap, *apn, *apf;
+ struct timeval now;
+ timerclear(&now);
TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
if (ifd && ap->delegating_iface != ifd)
continue;
@@ -772,7 +805,11 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
ipv6_deleteaddr(ap);
if (!(ap->iface->options->options &
DHCPCD_EXITING) && apf)
- ipv6_addaddr(apf);
+ {
+ if (!timerisset(&now))
+ get_monotonic(&now);
+ ipv6_addaddr(apf, &now);
+ }
}
free(ap);
}
@@ -1078,7 +1115,7 @@ nextslaacprivate:
inet_ntop(AF_INET6, &ap->addr, ap->saddr, sizeof(ap->saddr));
TAILQ_INSERT_TAIL(&state->addrs, ap, next);
- ipv6_addaddr(ap);
+ ipv6_addaddr(ap, NULL);
return 1;
}