diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2020-10-30 18:30:27 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2020-10-30 18:30:27 +0000 |
commit | 3c72d2135bc46cd3d3febc70c17d73d79f1d74c1 (patch) | |
tree | 7b8b53638276e845b0b0fe1df15665f0ade51c53 /sbin/slaacd/engine.c | |
parent | 54cea00ef1f5c3ee3466d17554827c6a426e9bc7 (diff) |
Track creation time of address proposals to be able to establish total
lifetime. Use this information to renew pltime / vltime of privacy
addresses for up to 1 day / 2 days as RFC 4941.
This is important when announced pltime / vltime is lower than 1 day /
2 days, privacy addresses would have expired too fast.
Spotted after a remark by Fernando Gont on misc@
Diffstat (limited to 'sbin/slaacd/engine.c')
-rw-r--r-- | sbin/slaacd/engine.c | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c index 8193e3966fc..52380f64439 100644 --- a/sbin/slaacd/engine.c +++ b/sbin/slaacd/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.56 2020/10/30 18:29:13 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.57 2020/10/30 18:30:26 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser <florian@openbsd.org> @@ -81,6 +81,8 @@ #include "slaacd.h" #include "engine.h" +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) + #define MAX_RTR_SOLICITATION_DELAY 1 #define MAX_RTR_SOLICITATION_DELAY_USEC MAX_RTR_SOLICITATION_DELAY * 1000000 #define RTR_SOLICITATION_INTERVAL 4 @@ -90,6 +92,7 @@ #define PRIV_MAX_DESYNC_FACTOR 600 /* 10 minutes */ #define PRIV_VALID_LIFETIME 172800 /* 2 days */ #define PRIV_PREFERRED_LIFETIME 86400 /* 1 day */ +#define PRIV_REGEN_ADVANCE 5 /* 5 seconds */ enum if_state { IF_DOWN, @@ -183,6 +186,7 @@ struct address_proposal { enum proposal_state state; time_t next_timeout; int timeout_count; + struct timespec created; struct timespec when; struct timespec uptime; uint32_t if_index; @@ -801,6 +805,7 @@ engine_dispatch_main(int fd, short event, void *bula) timeout_from_lifetime(addr_proposal); + /* leave created 0, we don't know when it was created */ if (clock_gettime(CLOCK_REALTIME, &addr_proposal->when)) fatal("clock_gettime"); if (clock_gettime(CLOCK_MONOTONIC, @@ -1822,7 +1827,7 @@ update_iface_ra_prefix(struct slaacd_iface *iface, struct radv *ra, struct radv_prefix *prefix) { struct address_proposal *addr_proposal; - uint32_t remaining_lifetime; + uint32_t remaining_lifetime, pltime, vltime; int found, found_privacy, duplicate_found; found = found_privacy = duplicate_found = 0; @@ -1847,38 +1852,46 @@ update_iface_ra_prefix(struct slaacd_iface *iface, struct radv *ra, continue; } - if (addr_proposal->privacy) { - /* create new privacy address if old expires */ - if (addr_proposal->state != PROPOSAL_NEARLY_EXPIRED) - found_privacy = 1; + remaining_lifetime = real_lifetime(&addr_proposal->uptime, + addr_proposal->vltime); - if (!iface->autoconfprivacy) - log_debug("%s XXX remove privacy address", - __func__); + /* RFC 4862 5.5.3 two hours rule */ +#define TWO_HOURS 2 * 3600 + if (prefix->vltime > TWO_HOURS || + prefix->vltime >= remaining_lifetime) + vltime = prefix->vltime; + else + vltime = TWO_HOURS; - log_debug("%s, privacy addr state: %s", __func__, - proposal_state_name[addr_proposal->state]); + if (addr_proposal->privacy) { + struct timespec now; + int64_t ltime; - /* privacy addresses just expire */ - continue; - } + if (clock_gettime(CLOCK_MONOTONIC, &now)) + fatal("clock_gettime"); - found = 1; + ltime = MINIMUM(addr_proposal->created.tv_sec + + PRIV_PREFERRED_LIFETIME - desync_factor, + now.tv_sec + prefix->pltime) - now.tv_sec; + pltime = ltime > 0 ? ltime : 0; - remaining_lifetime = real_lifetime(&addr_proposal->uptime, - addr_proposal->vltime); + ltime = MINIMUM(addr_proposal->created.tv_sec + + PRIV_VALID_LIFETIME, now.tv_sec + vltime) - + now.tv_sec; + vltime = ltime > 0 ? ltime : 0; + + if (pltime > PRIV_REGEN_ADVANCE) + found_privacy = 1; + } else { + pltime = prefix->pltime; + found = 1; + } addr_proposal->when = ra->when; addr_proposal->uptime = ra->uptime; - /* RFC 4862 5.5.3 two hours rule */ -#define TWO_HOURS 2 * 3600 - if (prefix->vltime > TWO_HOURS || - prefix->vltime > remaining_lifetime) - addr_proposal->vltime = prefix->vltime; - else - addr_proposal->vltime = TWO_HOURS; - addr_proposal->pltime = prefix->pltime; + addr_proposal->vltime = vltime; + addr_proposal->pltime = pltime; if (ra->mtu == iface->cur_mtu) addr_proposal->mtu = 0; @@ -2032,6 +2045,8 @@ gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct addr_proposal->next_timeout = 1; addr_proposal->timeout_count = 0; addr_proposal->state = PROPOSAL_NOT_CONFIGURED; + if (clock_gettime(CLOCK_MONOTONIC, &addr_proposal->created)) + fatal("clock_gettime"); addr_proposal->when = ra->when; addr_proposal->uptime = ra->uptime; addr_proposal->if_index = iface->if_index; @@ -2045,16 +2060,10 @@ gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct addr_proposal->prefix_len = prefix->prefix_len; if (privacy) { - if (prefix->vltime > PRIV_VALID_LIFETIME) - addr_proposal->vltime = PRIV_VALID_LIFETIME; - else - addr_proposal->vltime = prefix->vltime; - - if (prefix->pltime > PRIV_PREFERRED_LIFETIME) - addr_proposal->pltime = PRIV_PREFERRED_LIFETIME - - desync_factor; - else - addr_proposal->pltime = prefix->pltime; + addr_proposal->vltime = MINIMUM(prefix->vltime, + PRIV_VALID_LIFETIME); + addr_proposal->pltime = MINIMUM(prefix->pltime, + PRIV_PREFERRED_LIFETIME - desync_factor); } else { addr_proposal->vltime = prefix->vltime; addr_proposal->pltime = prefix->pltime; |