Skip to content

Commit a7a0c3c

Browse files
committed
net: ipv6: Expire temporary addresses periodically
Have a timer which checks if there are any expired and temporary IPv6 addresses and removes them if any are found. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 1edb2d8 commit a7a0c3c

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

subsys/net/ip/ipv6_pe.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ static bool ipv6_pe_blacklist;
6060
static struct in6_addr ipv6_pe_filter[CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT];
6161
#endif
6262

63+
/* We need to periodically update the private address. */
64+
static struct k_delayed_work temp_lifetime;
65+
6366
static bool ipv6_pe_use_this_prefix(const struct in6_addr *prefix)
6467
{
6568
#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0
@@ -192,6 +195,7 @@ void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix,
192195
struct net_if_ipv6 *ipv6;
193196
struct in6_addr addr;
194197
u8_t md5[128 / 8];
198+
s32_t remaining;
195199
int i;
196200

197201
if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
@@ -281,6 +285,13 @@ void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix,
281285
iface);
282286

283287
net_if_ipv6_start_dad(iface, ifaddr);
288+
289+
remaining = k_delayed_work_remaining_get(&temp_lifetime);
290+
if (remaining == 0 || remaining > K_SECONDS(vlifetime)) {
291+
NET_DBG("Next check for temp addresses in %d seconds",
292+
vlifetime);
293+
k_delayed_work_submit(&temp_lifetime, K_SECONDS(vlifetime));
294+
}
284295
}
285296

286297
#if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT > 0
@@ -428,6 +439,61 @@ int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, void *user_data)
428439
#endif
429440
}
430441

442+
static void renewal_cb(struct net_if *iface, void *user_data)
443+
{
444+
struct net_if_ipv6 *ipv6;
445+
struct in6_addr prefix;
446+
int i;
447+
448+
if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
449+
return;
450+
}
451+
452+
if (!ipv6) {
453+
return;
454+
}
455+
456+
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
457+
s32_t diff;
458+
459+
if (!ipv6->unicast[i].is_used ||
460+
ipv6->unicast[i].address.family != AF_INET6 ||
461+
!ipv6->unicast[i].is_temporary) {
462+
continue;
463+
}
464+
465+
/* If the address is too old, then generate a new one
466+
* and remove the old address.
467+
*/
468+
diff = (s32_t)(ipv6->unicast[i].addr_create_time -
469+
((u32_t)(k_uptime_get() / 1000)));
470+
diff = abs(diff);
471+
472+
if (diff < (TEMP_PREFERRED_LIFETIME -
473+
REGEN_ADVANCE - DESYNC_FACTOR)) {
474+
continue;
475+
}
476+
477+
net_ipaddr_copy(&prefix, &ipv6->unicast[i].address.in6_addr);
478+
479+
net_if_ipv6_addr_rm(iface,
480+
&ipv6->unicast[i].address.in6_addr);
481+
482+
memset(prefix.s6_addr + 8, 0, sizeof(prefix) - 8);
483+
484+
net_ipv6_pe_start(iface, &prefix,
485+
ipv6->unicast[i].addr_timeout,
486+
ipv6->unicast[i].addr_preferred_lifetime);
487+
}
488+
}
489+
490+
static void ipv6_pe_renew(struct k_work *work)
491+
{
492+
ARG_UNUSED(work);
493+
494+
net_if_foreach(renewal_cb, NULL);
495+
}
496+
431497
int net_ipv6_pe_init(struct net_if *iface)
432498
{
433499
static bool init_done;
@@ -452,6 +518,8 @@ int net_ipv6_pe_init(struct net_if *iface)
452518
init_done = true;
453519
}
454520

521+
k_delayed_work_init(&temp_lifetime, ipv6_pe_renew);
522+
455523
return 0;
456524
}
457525

0 commit comments

Comments
 (0)