Skip to content

Commit 1edb2d8

Browse files
committed
net: ipv6: Initial support for privacy extension
This creates support for IPv6 privacy extensions which is described in RFC 4941. This will also add API that can be used to add IPv6 prefixes to a white or black list privacy extension filter. Fixes #9349 Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 49a4144 commit 1edb2d8

File tree

9 files changed

+745
-10
lines changed

9 files changed

+745
-10
lines changed

include/net/net_if.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,29 @@ struct net_if_addr {
6565
/** What is the current state of the address */
6666
enum net_addr_state addr_state;
6767

68-
#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6)
68+
#if defined(CONFIG_NET_NATIVE_IPV6)
69+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
70+
/** Address creation time. This is used to determine if the maximum
71+
* lifetime for this address is reached or not. The value is in seconds.
72+
*/
73+
u32_t addr_create_time;
74+
75+
/** Preferred lifetime for the address in seconds.
76+
*/
77+
u32_t addr_preferred_lifetime;
78+
79+
/** Address timeout value. This is only used if DAD needs to be redone
80+
* for this address because of earlier DAD failure. This value is in
81+
* seconds.
82+
*/
83+
s32_t addr_timeout;
84+
#endif
85+
86+
#if defined(CONFIG_NET_IPV6_DAD)
6987
/** How many times we have done DAD */
7088
u8_t dad_count;
7189
#endif
90+
#endif /* CONFIG_NET_NATIVE_IPV6 */
7291

7392
/** Is the IP address valid forever */
7493
u8_t is_infinite : 1;
@@ -79,7 +98,10 @@ struct net_if_addr {
7998
/** Is this IP address usage limited to the subnet (mesh) or not */
8099
u8_t is_mesh_local : 1;
81100

82-
u8_t _unused : 5;
101+
/** Is this IP address temporary and generated for example by
102+
* IPv6 privacy extension (RFC 4941)
103+
*/
104+
u8_t is_temporary : 1;
83105
};
84106

85107
/**
@@ -464,6 +486,20 @@ struct net_if {
464486

465487
/** Network interface instance configuration */
466488
struct net_if_config config;
489+
490+
/** Network interface specific flags */
491+
/** Enable IPv6 privacy extension (RFC 4941), this is enabled
492+
* by default if PE support is enabled in configuration.
493+
*/
494+
u8_t pe_enabled : 1;
495+
496+
/* If PE is enabled, then this tells whether public addresses
497+
* are preferred over temporary ones for this interface.
498+
*/
499+
u8_t pe_prefer_public : 1;
500+
501+
u8_t _unused : 6;
502+
467503
} __net_if_align;
468504

469505
/**

include/net/net_ip.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,47 @@ static inline u8_t net_priority2vlan(enum net_priority priority)
14061406
*/
14071407
const char *net_family2str(sa_family_t family);
14081408

1409+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
1410+
/**
1411+
* @brief Add IPv6 prefix as a privacy extension filter.
1412+
*
1413+
* @details Note that the filters can be either black listing or white listing.
1414+
*
1415+
* @param addr IPv6 prefix
1416+
* @param is_blacklist Tells if this filter for white listing or black listing.
1417+
*
1418+
* @return 0 if ok, <0 if error
1419+
*/
1420+
int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_blacklist);
1421+
1422+
/**
1423+
* @brief Delete IPv6 prefix from privacy extension filter list.
1424+
*
1425+
* @param addr IPv6 prefix
1426+
*
1427+
* @return 0 if ok, <0 if error
1428+
*/
1429+
int net_ipv6_pe_del_filter(struct in6_addr *addr);
1430+
1431+
#else /* CONFIG_NET_IPV6_PE_ENABLE */
1432+
1433+
static inline int net_ipv6_pe_add_filter(struct in6_addr *addr,
1434+
bool is_blacklist)
1435+
{
1436+
ARG_UNUSED(addr);
1437+
ARG_UNUSED(is_blacklist);
1438+
1439+
return -ENOTSUP;
1440+
}
1441+
1442+
static inline int net_ipv6_pe_del_filter(struct in6_addr *addr)
1443+
{
1444+
ARG_UNUSED(addr);
1445+
1446+
return -ENOTSUP;
1447+
}
1448+
#endif /* CONFIG_NET_IPV6_PE_ENABLE */
1449+
14091450
#ifdef __cplusplus
14101451
}
14111452
#endif

subsys/net/ip/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ zephyr_library_sources_ifdef(CONFIG_NET_IPV6 icmpv6.c nbr.c
3030
ipv6.c ipv6_nbr.c)
3131
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_MLD ipv6_mld.c)
3232
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_FRAGMENT ipv6_fragment.c)
33+
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_PE_ENABLE ipv6_pe.c)
34+
zephyr_library_sources_ifdef(CONFIG_NET_MGMT_EVENT net_mgmt.c)
3335
zephyr_library_sources_ifdef(CONFIG_NET_ROUTE route.c)
3436
zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS net_stats.c)
3537
zephyr_library_sources_ifdef(CONFIG_NET_TCP connection.c tcp.c)

subsys/net/ip/Kconfig.ipv6

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,77 @@ config NET_IPV6_RA_RDNSS
119119
Support Router Advertisement Recursive DNS Server option.
120120
See RFC 6106 for details. The value depends on your network needs.
121121

122+
config NET_IPV6_PE_ENABLE
123+
bool "Enable privacy extension (RFC 4941) support"
124+
select MBEDTLS
125+
help
126+
This enables IPv6 privacy extension (RFC 4941) support.
127+
The interface identifier is randomized and SLAAC addresses
128+
generated from it will expire. This requires that applications are
129+
prepared to use new IPv6 addresses when old ones will expire.
130+
Note that you should make sure that the value of config option
131+
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT should be large enough so that
132+
two PE generated IPv6 addresses can be added to the network interface
133+
at the same time.
134+
135+
if NET_IPV6_PE_ENABLE
136+
137+
config NET_IPV6_PE_FILTER_PREFIX_COUNT
138+
int "Size of the IPv6 prefix filter list"
139+
default 0
140+
help
141+
Size of the white/black filter list of IPv6 prefixes. User can
142+
set filters at runtime and it is possible to enable or disable
143+
privacy extension support according to this filter list.
144+
By default no filters are enabled.
145+
146+
config NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES
147+
bool "Prefer public preferred address over temporary one"
148+
help
149+
Prefer public addresses over temporary addresses.
150+
151+
config NET_IPV6_PE_TEMP_VALID_LIFETIME
152+
int "Max lifetime for temporary address (in minutes)"
153+
default 10080
154+
help
155+
No temporary address should ever remain valid for longer than this
156+
value. The value is in minutes. Default value is 1 week (7*24*60).
157+
158+
config NET_IPV6_PE_TEMP_PREFERRED_LIFETIME
159+
int "Max preferred lifetime for temporary address (in minutes)"
160+
default 1440
161+
help
162+
No temporary address should ever remain preferred for longer than this
163+
value. The value is in minutes. Default value is 1 day (24*60).
164+
165+
config NET_IPV6_PE_REGEN_ADVANCE
166+
int "Regenerate advance time units"
167+
default 5
168+
help
169+
A temporary address is created only if the calculated Preferred
170+
Lifetime is greater than REGEN_ADVANCE time units.
171+
The value is in seconds.
172+
173+
config NET_IPV6_PE_MAX_DESYNC_FACTOR
174+
int "Max desync factor (in minutes)"
175+
default 10
176+
help
177+
This is the upper bound on DESYNC_FACTOR. The value is in minutes.
178+
The value DESYNC_FACTOR is a random value (different for each client)
179+
that ensures that clients don't synchronize with each other and
180+
generate new addresses at exactly the same time.
181+
182+
config NET_IPV6_PE_TEMP_IDGEN_RETRIES
183+
int "Max amount of failed DAD attempts"
184+
default 3
185+
help
186+
The node MUST perform duplicate address detection (DAD) on the
187+
generated temporary address. If after TEMP_IDGEN_RETRIES consecutive
188+
attempts no non-unique address was generated then there will be no
189+
attempt to generate temporary addresses for that interface.
190+
191+
endif
192+
122193
config NET_6LO
123194
bool "Enable 6lowpan IPv6 Compression library"
124195
default y if NET_L2_IEEE802154

subsys/net/ip/ipv6.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,4 +483,91 @@ void net_ipv6_mld_init(void);
483483
#define net_ipv6_nbr_init(...)
484484
#endif
485485

486+
/**
487+
* @brief Start IPv6 privacy extension procedure.
488+
*
489+
* @param iface Interface to use.
490+
* @param prefix IPv6 prefix to use.
491+
* @param vlifetime Lifetime of this IPv6 prefix (in seconds).
492+
* @param preferred_lifetime Preferred lifetime of this IPv6 prefix (in seconds)
493+
*/
494+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
495+
void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix,
496+
u32_t vlifetime, u32_t preferred_lifetime);
497+
498+
#else
499+
static inline void net_ipv6_pe_start(struct net_if *iface,
500+
const struct in6_addr *prefix,
501+
u32_t vlifetime,
502+
u32_t preferred_lifetime)
503+
{
504+
ARG_UNUSED(iface);
505+
ARG_UNUSED(prefix);
506+
ARG_UNUSED(vlifetime);
507+
ARG_UNUSED(preferred_lifetime);
508+
}
509+
#endif /* CONFIG_NET_IPV6_PE_ENABLE */
510+
511+
/**
512+
* @brief Check if maximum number of Duplicate Address Detection (DAD) requests
513+
* have been done.
514+
*
515+
* @param count Number of DAD requests done.
516+
*
517+
* @return Return True if DAD can continue, False if max amount of DAD
518+
* requests have been done.
519+
*/
520+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
521+
bool net_ipv6_pe_check_dad(int count);
522+
#else
523+
static inline bool net_ipv6_pe_check_dad(int count)
524+
{
525+
ARG_UNUSED(count);
526+
527+
return false;
528+
}
529+
#endif /* CONFIG_NET_IPV6_PE_ENABLE */
530+
531+
/**
532+
* @brief Initialize IPv6 privacy extension support for a network interface.
533+
*
534+
* @param iface Network interface
535+
*
536+
* @return Return 0 if ok or <0 if there is an error.
537+
*/
538+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
539+
int net_ipv6_pe_init(struct net_if *iface);
540+
#else
541+
static inline int net_ipv6_pe_init(struct net_if *iface)
542+
{
543+
iface->pe_enabled = false;
544+
iface->pe_prefer_public = false;
545+
546+
return 0;
547+
}
548+
#endif /* CONFIG_NET_IPV6_PE_ENABLE */
549+
550+
typedef void (*net_ipv6_pe_filter_cb_t)(struct in6_addr *prefix,
551+
bool is_blacklist,
552+
void *user_data);
553+
554+
/**
555+
* @brief Go through all the IPv6 privacy extension filters and call callback
556+
* for each IPv6 prefix.
557+
*
558+
* @param cb User supplied callback function to call.
559+
* @param user_data User specified data.
560+
*
561+
* @return Total number of filters found.
562+
*/
563+
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
564+
int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, void *user_data);
565+
#else
566+
static inline int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb,
567+
void *user_data)
568+
{
569+
return 0;
570+
}
571+
#endif
572+
486573
#endif /* __IPV6_H */

subsys/net/ip/ipv6_nbr.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,15 +2117,15 @@ static inline u32_t remaining_lifetime(struct net_if_addr *ifaddr)
21172117
static inline void handle_prefix_autonomous(struct net_pkt *pkt,
21182118
struct net_icmpv6_nd_opt_prefix_info *prefix_info)
21192119
{
2120+
struct net_if *iface = net_pkt_iface(pkt);
21202121
struct in6_addr addr = { };
21212122
struct net_if_addr *ifaddr;
21222123

21232124
/* Create IPv6 address using the given prefix and iid. We first
21242125
* setup link local address, and then copy prefix over first 8
21252126
* bytes of that address.
21262127
*/
2127-
net_ipv6_addr_create_iid(&addr,
2128-
net_if_get_link_addr(net_pkt_iface(pkt)));
2128+
net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface));
21292129
memcpy(&addr, &prefix_info->prefix, sizeof(struct in6_addr) / 2);
21302130

21312131
ifaddr = net_if_ipv6_addr_lookup(&addr, NULL);
@@ -2160,14 +2160,22 @@ static inline void handle_prefix_autonomous(struct net_pkt *pkt,
21602160
} else {
21612161
if (prefix_info->valid_lifetime ==
21622162
NET_IPV6_ND_INFINITE_LIFETIME) {
2163-
net_if_ipv6_addr_add(net_pkt_iface(pkt),
2164-
&addr, NET_ADDR_AUTOCONF, 0);
2163+
net_if_ipv6_addr_add(iface, &addr,
2164+
NET_ADDR_AUTOCONF, 0);
21652165
} else {
2166-
net_if_ipv6_addr_add(net_pkt_iface(pkt),
2167-
&addr, NET_ADDR_AUTOCONF,
2166+
net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF,
21682167
prefix_info->valid_lifetime);
21692168
}
21702169
}
2170+
2171+
/* If privacy extensions are enabled, then start the procedure for that
2172+
* too.
2173+
*/
2174+
if (IS_ENABLED(CONFIG_NET_IPV6_PE_ENABLE) && iface->pe_enabled) {
2175+
net_ipv6_pe_start(iface, &prefix_info->prefix,
2176+
prefix_info->valid_lifetime,
2177+
prefix_info->preferred_lifetime);
2178+
}
21712179
}
21722180

21732181
static inline bool handle_ra_prefix(struct net_pkt *pkt)

0 commit comments

Comments
 (0)