Skip to content

Commit 2e96305

Browse files
committed
net: ipv6: Select proper IPv6 source address for privacy extension
If IPv6 privacy extension is enabled, then we need to select proper public or temporary IPv6 source address when sending the packet. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent a7a0c3c commit 2e96305

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

include/net/net_if.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ static inline void net_if_ipv6_maddr_leave(struct net_if_mcast_addr *addr)
11141114
* @return Pointer to prefix, NULL if not found.
11151115
*/
11161116
struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface,
1117-
struct in6_addr *addr);
1117+
const struct in6_addr *addr);
11181118

11191119
/**
11201120
* @brief Check if this IPv6 prefix belongs to this interface

subsys/net/ip/net_if.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,7 @@ bool net_if_ipv6_prefix_rm(struct net_if *iface, struct in6_addr *addr,
20062006
}
20072007

20082008
struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface,
2009-
struct in6_addr *addr)
2009+
const struct in6_addr *addr)
20102010
{
20112011
struct net_if_ipv6_prefix *prefix = NULL;
20122012
struct net_if_ipv6 *ipv6;
@@ -2269,25 +2269,53 @@ static inline bool is_proper_ipv6_address(struct net_if_addr *addr)
22692269
return false;
22702270
}
22712271

2272+
static bool use_public_address(bool prefer_public, bool is_temporary)
2273+
{
2274+
if (IS_ENABLED(CONFIG_NET_IPV6_PE_ENABLE)) {
2275+
if (!prefer_public && is_temporary) {
2276+
return false;
2277+
}
2278+
}
2279+
2280+
return true;
2281+
}
2282+
22722283
static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface,
22732284
const struct in6_addr *dst,
2285+
u8_t prefix_len,
22742286
u8_t *best_so_far)
22752287
{
22762288
struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
2289+
struct net_if_addr *public_addr = NULL;
22772290
struct in6_addr *src = NULL;
2278-
u8_t len;
2291+
u8_t public_addr_len = 0;
2292+
struct in6_addr *temp_addr;
2293+
u8_t len, temp_addr_len;
2294+
bool ret;
22792295
int i;
22802296

22812297
if (!ipv6) {
22822298
return NULL;
22832299
}
22842300

2301+
if (IS_ENABLED(CONFIG_NET_IPV6_PE_ENABLE)) {
2302+
temp_addr = NULL;
2303+
temp_addr_len = 0;
2304+
} else {
2305+
ARG_UNUSED(temp_addr);
2306+
ARG_UNUSED(temp_addr_len);
2307+
}
2308+
22852309
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
22862310
if (!is_proper_ipv6_address(&ipv6->unicast[i])) {
22872311
continue;
22882312
}
22892313

22902314
len = get_diff_ipv6(dst, &ipv6->unicast[i].address.in6_addr);
2315+
if (len >= prefix_len) {
2316+
len = prefix_len;
2317+
}
2318+
22912319
if (len >= *best_so_far) {
22922320
/* Mesh local address can only be selected for the same
22932321
* subnet.
@@ -2296,11 +2324,39 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface,
22962324
continue;
22972325
}
22982326

2327+
ret = use_public_address(iface->pe_prefer_public,
2328+
ipv6->unicast[i].is_temporary);
2329+
if (!ret) {
2330+
temp_addr = &ipv6->unicast[i].address.in6_addr;
2331+
temp_addr_len = len;
2332+
continue;
2333+
}
2334+
2335+
if (!ipv6->unicast[i].is_temporary) {
2336+
public_addr = &ipv6->unicast[i];
2337+
public_addr_len = len;
2338+
}
2339+
22992340
*best_so_far = len;
23002341
src = &ipv6->unicast[i].address.in6_addr;
23012342
}
23022343
}
23032344

2345+
if (IS_ENABLED(CONFIG_NET_IPV6_PE_ENABLE) &&
2346+
!iface->pe_prefer_public && temp_addr) {
2347+
if (temp_addr_len >= *best_so_far) {
2348+
*best_so_far = temp_addr_len;
2349+
src = temp_addr;
2350+
}
2351+
} else {
2352+
/* By default prefer always public address if found */
2353+
if (public_addr &&
2354+
!net_ipv6_addr_cmp(&public_addr->address.in6_addr, src)) {
2355+
src = &public_addr->address.in6_addr;
2356+
*best_so_far = public_addr_len;
2357+
}
2358+
}
2359+
23042360
return src;
23052361
}
23062362

@@ -2312,13 +2368,21 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
23122368
struct net_if *iface;
23132369

23142370
if (!net_ipv6_is_ll_addr(dst) && !net_ipv6_is_addr_mcast(dst)) {
2371+
struct net_if_ipv6_prefix *prefix;
2372+
u8_t prefix_len = 128;
2373+
2374+
prefix = net_if_ipv6_prefix_get(dst_iface, dst);
2375+
if (prefix) {
2376+
prefix_len = prefix->len;
2377+
}
23152378

23162379
for (iface = __net_if_start;
23172380
!dst_iface && iface != __net_if_end;
23182381
iface++) {
23192382
struct in6_addr *addr;
23202383

23212384
addr = net_if_ipv6_get_best_match(iface, dst,
2385+
prefix_len,
23222386
&best_match);
23232387
if (addr) {
23242388
src = addr;
@@ -2328,6 +2392,7 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
23282392
/* If caller has supplied interface, then use that */
23292393
if (dst_iface) {
23302394
src = net_if_ipv6_get_best_match(dst_iface, dst,
2395+
prefix_len,
23312396
&best_match);
23322397
}
23332398

0 commit comments

Comments
 (0)