Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions include/net/net_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,29 @@ struct net_if_addr {
/** What is the current state of the address */
enum net_addr_state addr_state;

#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6)
#if defined(CONFIG_NET_NATIVE_IPV6)
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
/** Address creation time. This is used to determine if the maximum
* lifetime for this address is reached or not. The value is in seconds.
*/
u32_t addr_create_time;

/** Preferred lifetime for the address in seconds.
*/
u32_t addr_preferred_lifetime;

/** Address timeout value. This is only used if DAD needs to be redone
* for this address because of earlier DAD failure. This value is in
* seconds.
*/
s32_t addr_timeout;
#endif

#if defined(CONFIG_NET_IPV6_DAD)
/** How many times we have done DAD */
u8_t dad_count;
#endif
#endif /* CONFIG_NET_NATIVE_IPV6 */

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

u8_t _unused : 5;
/** Is this IP address temporary and generated for example by
* IPv6 privacy extension (RFC 4941)
*/
u8_t is_temporary : 1;
};

/**
Expand Down Expand Up @@ -464,6 +486,20 @@ struct net_if {

/** Network interface instance configuration */
struct net_if_config config;

/** Network interface specific flags */
/** Enable IPv6 privacy extension (RFC 4941), this is enabled
* by default if PE support is enabled in configuration.
*/
u8_t pe_enabled : 1;

/* If PE is enabled, then this tells whether public addresses
* are preferred over temporary ones for this interface.
*/
u8_t pe_prefer_public : 1;

u8_t _unused : 6;

} __net_if_align;

/**
Expand Down Expand Up @@ -1078,7 +1114,7 @@ static inline void net_if_ipv6_maddr_leave(struct net_if_mcast_addr *addr)
* @return Pointer to prefix, NULL if not found.
*/
struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface,
struct in6_addr *addr);
const struct in6_addr *addr);

/**
* @brief Check if this IPv6 prefix belongs to this interface
Expand Down
41 changes: 41 additions & 0 deletions include/net/net_ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,47 @@ static inline u8_t net_priority2vlan(enum net_priority priority)
*/
const char *net_family2str(sa_family_t family);

#if defined(CONFIG_NET_IPV6_PE_ENABLE)
/**
* @brief Add IPv6 prefix as a privacy extension filter.
*
* @details Note that the filters can be either black listing or white listing.
*
* @param addr IPv6 prefix
* @param is_blacklist Tells if this filter for white listing or black listing.
*
* @return 0 if ok, <0 if error
*/
int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_blacklist);

/**
* @brief Delete IPv6 prefix from privacy extension filter list.
*
* @param addr IPv6 prefix
*
* @return 0 if ok, <0 if error
*/
int net_ipv6_pe_del_filter(struct in6_addr *addr);

#else /* CONFIG_NET_IPV6_PE_ENABLE */

static inline int net_ipv6_pe_add_filter(struct in6_addr *addr,
bool is_blacklist)
{
ARG_UNUSED(addr);
ARG_UNUSED(is_blacklist);

return -ENOTSUP;
}

static inline int net_ipv6_pe_del_filter(struct in6_addr *addr)
{
ARG_UNUSED(addr);

return -ENOTSUP;
}
#endif /* CONFIG_NET_IPV6_PE_ENABLE */

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions subsys/net/ip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ zephyr_library_sources_ifdef(CONFIG_NET_IPV6 icmpv6.c nbr.c
ipv6.c ipv6_nbr.c)
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_MLD ipv6_mld.c)
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_FRAGMENT ipv6_fragment.c)
zephyr_library_sources_ifdef(CONFIG_NET_IPV6_PE_ENABLE ipv6_pe.c)
zephyr_library_sources_ifdef(CONFIG_NET_MGMT_EVENT net_mgmt.c)
zephyr_library_sources_ifdef(CONFIG_NET_ROUTE route.c)
zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS net_stats.c)
zephyr_library_sources_ifdef(CONFIG_NET_TCP connection.c tcp.c)
Expand Down
71 changes: 71 additions & 0 deletions subsys/net/ip/Kconfig.ipv6
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,77 @@ config NET_IPV6_RA_RDNSS
Support Router Advertisement Recursive DNS Server option.
See RFC 6106 for details. The value depends on your network needs.

config NET_IPV6_PE_ENABLE
bool "Enable privacy extension (RFC 4941) support"
select MBEDTLS
help
This enables IPv6 privacy extension (RFC 4941) support.
The interface identifier is randomized and SLAAC addresses
generated from it will expire. This requires that applications are
prepared to use new IPv6 addresses when old ones will expire.
Note that you should make sure that the value of config option
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT should be large enough so that
two PE generated IPv6 addresses can be added to the network interface
at the same time.

if NET_IPV6_PE_ENABLE

config NET_IPV6_PE_FILTER_PREFIX_COUNT
int "Size of the IPv6 prefix filter list"
default 0
help
Size of the white/black filter list of IPv6 prefixes. User can
set filters at runtime and it is possible to enable or disable
privacy extension support according to this filter list.
By default no filters are enabled.

config NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES
bool "Prefer public preferred address over temporary one"
help
Prefer public addresses over temporary addresses.

config NET_IPV6_PE_TEMP_VALID_LIFETIME
int "Max lifetime for temporary address (in minutes)"
default 10080
help
No temporary address should ever remain valid for longer than this
value. The value is in minutes. Default value is 1 week (7*24*60).

config NET_IPV6_PE_TEMP_PREFERRED_LIFETIME
int "Max preferred lifetime for temporary address (in minutes)"
default 1440
help
No temporary address should ever remain preferred for longer than this
value. The value is in minutes. Default value is 1 day (24*60).

config NET_IPV6_PE_REGEN_ADVANCE
int "Regenerate advance time units"
default 5
help
A temporary address is created only if the calculated Preferred
Lifetime is greater than REGEN_ADVANCE time units.
The value is in seconds.

config NET_IPV6_PE_MAX_DESYNC_FACTOR
int "Max desync factor (in minutes)"
default 10
help
This is the upper bound on DESYNC_FACTOR. The value is in minutes.
The value DESYNC_FACTOR is a random value (different for each client)
that ensures that clients don't synchronize with each other and
generate new addresses at exactly the same time.

config NET_IPV6_PE_TEMP_IDGEN_RETRIES
int "Max amount of failed DAD attempts"
default 3
help
The node MUST perform duplicate address detection (DAD) on the
generated temporary address. If after TEMP_IDGEN_RETRIES consecutive
attempts no non-unique address was generated then there will be no
attempt to generate temporary addresses for that interface.

endif

config NET_6LO
bool "Enable 6lowpan IPv6 Compression library"
default y if NET_L2_IEEE802154
Expand Down
87 changes: 87 additions & 0 deletions subsys/net/ip/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,91 @@ void net_ipv6_mld_init(void);
#define net_ipv6_nbr_init(...)
#endif

/**
* @brief Start IPv6 privacy extension procedure.
*
* @param iface Interface to use.
* @param prefix IPv6 prefix to use.
* @param vlifetime Lifetime of this IPv6 prefix (in seconds).
* @param preferred_lifetime Preferred lifetime of this IPv6 prefix (in seconds)
*/
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
void net_ipv6_pe_start(struct net_if *iface, const struct in6_addr *prefix,
u32_t vlifetime, u32_t preferred_lifetime);

#else
static inline void net_ipv6_pe_start(struct net_if *iface,
const struct in6_addr *prefix,
u32_t vlifetime,
u32_t preferred_lifetime)
{
ARG_UNUSED(iface);
ARG_UNUSED(prefix);
ARG_UNUSED(vlifetime);
ARG_UNUSED(preferred_lifetime);
}
#endif /* CONFIG_NET_IPV6_PE_ENABLE */

/**
* @brief Check if maximum number of Duplicate Address Detection (DAD) requests
* have been done.
*
* @param count Number of DAD requests done.
*
* @return Return True if DAD can continue, False if max amount of DAD
* requests have been done.
*/
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
bool net_ipv6_pe_check_dad(int count);
#else
static inline bool net_ipv6_pe_check_dad(int count)
{
ARG_UNUSED(count);

return false;
}
#endif /* CONFIG_NET_IPV6_PE_ENABLE */

/**
* @brief Initialize IPv6 privacy extension support for a network interface.
*
* @param iface Network interface
*
* @return Return 0 if ok or <0 if there is an error.
*/
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
int net_ipv6_pe_init(struct net_if *iface);
#else
static inline int net_ipv6_pe_init(struct net_if *iface)
{
iface->pe_enabled = false;
iface->pe_prefer_public = false;

return 0;
}
#endif /* CONFIG_NET_IPV6_PE_ENABLE */

typedef void (*net_ipv6_pe_filter_cb_t)(struct in6_addr *prefix,
bool is_blacklist,
void *user_data);

/**
* @brief Go through all the IPv6 privacy extension filters and call callback
* for each IPv6 prefix.
*
* @param cb User supplied callback function to call.
* @param user_data User specified data.
*
* @return Total number of filters found.
*/
#if defined(CONFIG_NET_IPV6_PE_ENABLE)
int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb, void *user_data);
#else
static inline int net_ipv6_pe_filter_foreach(net_ipv6_pe_filter_cb_t cb,
void *user_data)
{
return 0;
}
#endif

#endif /* __IPV6_H */
20 changes: 14 additions & 6 deletions subsys/net/ip/ipv6_nbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2117,15 +2117,15 @@ static inline u32_t remaining_lifetime(struct net_if_addr *ifaddr)
static inline void handle_prefix_autonomous(struct net_pkt *pkt,
struct net_icmpv6_nd_opt_prefix_info *prefix_info)
{
struct net_if *iface = net_pkt_iface(pkt);
struct in6_addr addr = { };
struct net_if_addr *ifaddr;

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

ifaddr = net_if_ipv6_addr_lookup(&addr, NULL);
Expand Down Expand Up @@ -2160,14 +2160,22 @@ static inline void handle_prefix_autonomous(struct net_pkt *pkt,
} else {
if (prefix_info->valid_lifetime ==
NET_IPV6_ND_INFINITE_LIFETIME) {
net_if_ipv6_addr_add(net_pkt_iface(pkt),
&addr, NET_ADDR_AUTOCONF, 0);
net_if_ipv6_addr_add(iface, &addr,
NET_ADDR_AUTOCONF, 0);
} else {
net_if_ipv6_addr_add(net_pkt_iface(pkt),
&addr, NET_ADDR_AUTOCONF,
net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF,
prefix_info->valid_lifetime);
}
}

/* If privacy extensions are enabled, then start the procedure for that
* too.
*/
if (IS_ENABLED(CONFIG_NET_IPV6_PE_ENABLE) && iface->pe_enabled) {
net_ipv6_pe_start(iface, &prefix_info->prefix,
prefix_info->valid_lifetime,
prefix_info->preferred_lifetime);
}
}

static inline bool handle_ra_prefix(struct net_pkt *pkt)
Expand Down
Loading