net: ipv6: Add support for stable IID addresses
This implements support for RFC 7217 which describes a method to have stable IPv6 Interface Identifiers to be used with IPv6 Stateless Address Autoconfiguration (SLAAC). The stable IIDs are used to provide enhanced privacy so that an IPv6 address configured using this method is stable within each subnet, but the corresponding Interface Identifier changes when the host moves from one network to another. This method is meant to be an alternative to generating Interface Identifiers based on hardware (MAC) addresses, such that the benefits of stable addresses can be achieved without sacrificing the security and privacy of users. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
parent
c9f3690ed4
commit
94177a200e
|
@ -331,6 +331,16 @@ struct net_if_ipv6 {
|
|||
/** Retransmit timer (RFC 4861, page 52) */
|
||||
uint32_t retrans_timer;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_IID_STABLE)
|
||||
/** IID (Interface Identifier) pointer used for link local address */
|
||||
struct net_if_addr *iid;
|
||||
|
||||
/** Incremented when network interface goes down so that we can
|
||||
* generate new stable addresses when interface comes back up.
|
||||
*/
|
||||
uint32_t network_counter;
|
||||
#endif /* CONFIG_NET_IPV6_IID_STABLE */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_PE)
|
||||
/** Privacy extension DESYNC_FACTOR value from RFC 8981 ch 3.4.
|
||||
* "DESYNC_FACTOR is a random value within the range 0 - MAX_DESYNC_FACTOR.
|
||||
|
|
|
@ -1439,7 +1439,32 @@ static inline bool net_ipv6_addr_is_v4_mapped(const struct in6_addr *addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Create IPv6 address interface identifier
|
||||
* @brief Generate IPv6 address using a prefix and interface identifier.
|
||||
* Interface identifier is either generated from EUI-64 (MAC) defined
|
||||
* in RFC 4291 or from randomized value defined in RFC 7217.
|
||||
*
|
||||
* @param iface Network interface
|
||||
* @param prefix IPv6 prefix, can be left out in which case fe80::/64 is used
|
||||
* @param network_id Network identifier (for example SSID in WLAN), this is
|
||||
* optional can be set to NULL
|
||||
* @param network_id_len Network identifier length, if set to 0 then the
|
||||
* network id is ignored.
|
||||
* @param dad_counter Duplicate Address Detection counter value, can be set to 0
|
||||
* if it is not known.
|
||||
* @param addr IPv6 address
|
||||
* @param lladdr Link local address
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_ipv6_addr_generate_iid(struct net_if *iface,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t *network_id, size_t network_id_len,
|
||||
uint8_t dad_counter,
|
||||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr);
|
||||
|
||||
/**
|
||||
* @brief Create IPv6 address interface identifier.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
* @param lladdr Link local address
|
||||
|
@ -1447,43 +1472,7 @@ static inline bool net_ipv6_addr_is_v4_mapped(const struct in6_addr *addr)
|
|||
static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr)
|
||||
{
|
||||
UNALIGNED_PUT(htonl(0xfe800000), &addr->s6_addr32[0]);
|
||||
UNALIGNED_PUT(0, &addr->s6_addr32[1]);
|
||||
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
/* The generated IPv6 shall not toggle the
|
||||
* Universal/Local bit. RFC 6282 ch 3.2.2
|
||||
*/
|
||||
if (lladdr->type == NET_LINK_IEEE802154) {
|
||||
UNALIGNED_PUT(0, &addr->s6_addr32[2]);
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
addr->s6_addr[13] = 0U;
|
||||
addr->s6_addr[14] = lladdr->addr[0];
|
||||
addr->s6_addr[15] = lladdr->addr[1];
|
||||
}
|
||||
|
||||
break;
|
||||
case 6:
|
||||
/* We do not toggle the Universal/Local bit
|
||||
* in Bluetooth. See RFC 7668 ch 3.2.2
|
||||
*/
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, 3);
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
memcpy(&addr->s6_addr[13], lladdr->addr + 3, 3);
|
||||
|
||||
if (lladdr->type == NET_LINK_ETHERNET) {
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
}
|
||||
|
||||
break;
|
||||
case 8:
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, lladdr->len);
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
}
|
||||
(void)net_ipv6_addr_generate_iid(NULL, NULL, NULL, 0, 0, addr, lladdr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,7 +54,7 @@ zephyr_library_sources_ifdef(CONFIG_NET_CONNECTION_SOCKETS connection.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_PACKET packet_socket.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_CAN canbus_socket.c)
|
||||
|
||||
if(CONFIG_NET_TCP_ISN_RFC6528 OR CONFIG_NET_IPV6_PE)
|
||||
if(CONFIG_NET_TCP_ISN_RFC6528 OR CONFIG_NET_IPV6_PE OR CONFIG_NET_IPV6_IID_STABLE)
|
||||
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -174,6 +174,46 @@ config NET_IPV6_RA_RDNSS
|
|||
Support Router Advertisement Recursive DNS Server option.
|
||||
See RFC 6106 for details. The value depends on your network needs.
|
||||
|
||||
choice NET_IPV6_IID_GENERATION
|
||||
prompt "IPv6 Interface Identifier (IID) generation"
|
||||
default NET_IPV6_IID_EUI_64
|
||||
help
|
||||
Determines how the IPv6 Interface Identifier (IID) is generated.
|
||||
By default the legacy format using EUI-64 (MAC address) specified in
|
||||
RFC 4291 chapter 2.5.1 is used.
|
||||
User can also choose to use stable IID specified in RFC 7217 in which
|
||||
case a randomized IID is generated for each network interface.
|
||||
The stable IID enhances privacy by having a different IID for each
|
||||
network interface.
|
||||
|
||||
config NET_IPV6_IID_EUI_64
|
||||
bool "Generate IID using EUI-64"
|
||||
help
|
||||
Generate IID from modified EUI-64 a.k.a MAC address. This is the
|
||||
legacy way described in RFC 4291 chapter 2.5.1
|
||||
|
||||
config NET_IPV6_IID_STABLE
|
||||
bool "Generate stable IID [EXPERIMENTAL]"
|
||||
select MBEDTLS
|
||||
select MBEDTLS_MD
|
||||
select EXPERIMENTAL
|
||||
depends on !NET_6LO
|
||||
help
|
||||
Generate a stable IID described in RFC 7217. This option specifies a
|
||||
method for generating IPv6 Interface Identifiers to be used with
|
||||
IPv6 Stateless Address Autoconfiguration (SLAAC), such that an IPv6
|
||||
address configured using this method is stable within each subnet,
|
||||
but the corresponding Interface Identifier changes when the host
|
||||
moves from one network to another. This method is meant to be an
|
||||
alternative to generating Interface Identifiers based on hardware
|
||||
addresses (e.g., IEEE LAN Media Access Control (MAC) addresses),
|
||||
such that the benefits of stable addresses can be achieved without
|
||||
sacrificing the security and privacy of users.
|
||||
Currently the stable IID generation is disabled for 6lo networks
|
||||
because of header compression.
|
||||
|
||||
endchoice
|
||||
|
||||
config NET_IPV6_PE
|
||||
bool "Privacy extension (RFC 8981) support [EXPERIMENTAL]"
|
||||
select MBEDTLS
|
||||
|
|
|
@ -18,6 +18,12 @@ LOG_MODULE_REGISTER(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
|
|||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_IID_STABLE)
|
||||
#include <zephyr/random/random.h>
|
||||
#include <mbedtls/md.h>
|
||||
#endif /* CONFIG_NET_IPV6_IID_STABLE */
|
||||
|
||||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
#include <zephyr/net/net_stats.h>
|
||||
|
@ -815,6 +821,194 @@ bad_hdr:
|
|||
return NET_DROP;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6_IID_STABLE)
|
||||
static bool check_reserved(const uint8_t *buf, size_t len)
|
||||
{
|
||||
/* Subnet-Router Anycast (RFC 4291) */
|
||||
if (memcmp(buf, (uint8_t *)&(struct in6_addr)IN6ADDR_ANY_INIT, len) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Reserved Subnet Anycast Addresses (RFC 2526)
|
||||
* FDFF:FFFF:FFFF:FF80 - FDFF:FFFF:FFFF:FFFF
|
||||
*/
|
||||
if (buf[0] == 0xFD && buf[1] == 0xFF && buf[2] == 0xFF &&
|
||||
buf[3] == 0xFF && buf[4] == 0xFF && buf[5] == 0xFF &&
|
||||
buf[6] == 0xFF && buf[7] >= 0x80) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6_IID_STABLE */
|
||||
|
||||
static int gen_stable_iid(uint8_t if_index,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t *network_id, size_t network_id_len,
|
||||
uint8_t dad_counter,
|
||||
uint8_t *stable_iid,
|
||||
size_t stable_iid_len)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6_IID_STABLE)
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
mbedtls_md_context_t ctx;
|
||||
uint8_t digest[32];
|
||||
int ret;
|
||||
static bool once;
|
||||
static uint8_t secret_key[16]; /* Min 128 bits, RFC 7217 ch 5 */
|
||||
struct {
|
||||
struct in6_addr prefix;
|
||||
uint8_t if_index;
|
||||
uint8_t network_id[16];
|
||||
uint8_t dad_counter;
|
||||
} buf = {
|
||||
.dad_counter = dad_counter,
|
||||
};
|
||||
|
||||
if (prefix == NULL) {
|
||||
NET_ERR("IPv6 prefix must be set for generating a stable IID");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&buf.prefix, prefix, sizeof(struct in6_addr));
|
||||
|
||||
buf.if_index = if_index;
|
||||
|
||||
if (network_id != NULL && network_id_len > 0) {
|
||||
memcpy(buf.network_id, network_id,
|
||||
MIN(network_id_len, sizeof(buf.network_id)));
|
||||
}
|
||||
|
||||
if (!once) {
|
||||
sys_rand_get(&secret_key, sizeof(secret_key));
|
||||
once = true;
|
||||
}
|
||||
|
||||
mbedtls_md_init(&ctx);
|
||||
mbedtls_md_setup(&ctx, md_info, true);
|
||||
ret = mbedtls_md_hmac_starts(&ctx, secret_key, sizeof(secret_key));
|
||||
if (ret != 0) {
|
||||
NET_DBG("Cannot %s hmac (%d)", "start", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = mbedtls_md_hmac_update(&ctx, (uint8_t *)&buf, sizeof(buf));
|
||||
if (ret != 0) {
|
||||
NET_DBG("Cannot %s hmac (%d)", "update", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = mbedtls_md_hmac_finish(&ctx, digest);
|
||||
if (ret != 0) {
|
||||
NET_DBG("Cannot %s hmac (%d)", "finish", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(stable_iid, digest, MIN(sizeof(digest), stable_iid_len));
|
||||
|
||||
/* Check reserved addresses, RFC 5453 ch 3 */
|
||||
if (unlikely(check_reserved(stable_iid, stable_iid_len))) {
|
||||
LOG_HEXDUMP_DBG(stable_iid, stable_iid_len,
|
||||
"Generated IID is reserved");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
mbedtls_md_free(&ctx);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int net_ipv6_addr_generate_iid(struct net_if *iface,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t *network_id,
|
||||
size_t network_id_len,
|
||||
uint8_t dad_counter,
|
||||
struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr)
|
||||
{
|
||||
struct in6_addr tmp_addr;
|
||||
uint8_t if_index;
|
||||
|
||||
if_index = (iface == NULL) ? net_if_get_by_iface(net_if_get_default())
|
||||
: net_if_get_by_iface(iface);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6_IID_STABLE)) {
|
||||
struct in6_addr tmp_prefix = { 0 };
|
||||
int ret;
|
||||
|
||||
if (prefix == NULL) {
|
||||
UNALIGNED_PUT(htonl(0xfe800000), &tmp_prefix.s6_addr32[0]);
|
||||
} else {
|
||||
UNALIGNED_PUT(prefix->s6_addr32[0], &tmp_prefix.s6_addr32[0]);
|
||||
UNALIGNED_PUT(prefix->s6_addr32[1], &tmp_prefix.s6_addr32[1]);
|
||||
}
|
||||
|
||||
ret = gen_stable_iid(if_index, &tmp_prefix, network_id, network_id_len,
|
||||
dad_counter, (uint8_t *)&tmp_addr + 8,
|
||||
sizeof(tmp_addr) / 2);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix == NULL) {
|
||||
UNALIGNED_PUT(htonl(0xfe800000), &tmp_addr.s6_addr32[0]);
|
||||
UNALIGNED_PUT(0, &tmp_addr.s6_addr32[1]);
|
||||
} else {
|
||||
UNALIGNED_PUT(prefix->s6_addr32[0], &tmp_addr.s6_addr32[0]);
|
||||
UNALIGNED_PUT(prefix->s6_addr32[1], &tmp_addr.s6_addr32[1]);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6_IID_EUI_64)) {
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
/* The generated IPv6 shall not toggle the
|
||||
* Universal/Local bit. RFC 6282 ch 3.2.2
|
||||
*/
|
||||
if (lladdr->type == NET_LINK_IEEE802154) {
|
||||
UNALIGNED_PUT(0, &tmp_addr.s6_addr32[2]);
|
||||
tmp_addr.s6_addr[11] = 0xff;
|
||||
tmp_addr.s6_addr[12] = 0xfe;
|
||||
tmp_addr.s6_addr[13] = 0U;
|
||||
tmp_addr.s6_addr[14] = lladdr->addr[0];
|
||||
tmp_addr.s6_addr[15] = lladdr->addr[1];
|
||||
}
|
||||
|
||||
break;
|
||||
case 6:
|
||||
/* We do not toggle the Universal/Local bit
|
||||
* in Bluetooth. See RFC 7668 ch 3.2.2
|
||||
*/
|
||||
memcpy(&tmp_addr.s6_addr[8], lladdr->addr, 3);
|
||||
tmp_addr.s6_addr[11] = 0xff;
|
||||
tmp_addr.s6_addr[12] = 0xfe;
|
||||
memcpy(&tmp_addr.s6_addr[13], lladdr->addr + 3, 3);
|
||||
|
||||
if (lladdr->type == NET_LINK_ETHERNET) {
|
||||
tmp_addr.s6_addr[8] ^= 0x02;
|
||||
}
|
||||
|
||||
break;
|
||||
case 8:
|
||||
memcpy(&tmp_addr.s6_addr[8], lladdr->addr, lladdr->len);
|
||||
tmp_addr.s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("%s IID for iface %d %s",
|
||||
IS_ENABLED(CONFIG_NET_IPV6_IID_STABLE) ? "Stable" : "EUI-64",
|
||||
if_index, net_sprint_ipv6_addr(&tmp_addr));
|
||||
|
||||
memcpy(addr, &tmp_addr, sizeof(*addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void net_ipv6_init(void)
|
||||
{
|
||||
net_ipv6_nbr_init();
|
||||
|
|
|
@ -2237,13 +2237,24 @@ static inline void handle_prefix_autonomous(struct net_pkt *pkt,
|
|||
struct net_if *iface = net_pkt_iface(pkt);
|
||||
struct in6_addr addr = { };
|
||||
struct net_if_addr *ifaddr;
|
||||
int ret;
|
||||
|
||||
/* 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.
|
||||
/* Create IPv6 address using the given prefix and iid.
|
||||
*/
|
||||
net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface));
|
||||
memcpy(&addr, prefix_info->prefix, sizeof(struct in6_addr) / 2);
|
||||
ret = net_ipv6_addr_generate_iid(iface,
|
||||
(struct in6_addr *)prefix_info->prefix,
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
((uint8_t *)&iface->config.ip.ipv6->network_counter),
|
||||
(NULL)),
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
(sizeof(iface->config.ip.ipv6->network_counter)),
|
||||
(0U)),
|
||||
0U,
|
||||
&addr,
|
||||
net_if_get_link_addr(iface));
|
||||
if (ret < 0) {
|
||||
NET_WARN("IPv6 IID generation issue (%d)", ret);
|
||||
}
|
||||
|
||||
ifaddr = net_if_ipv6_addr_lookup(&addr, NULL);
|
||||
if (ifaddr && ifaddr->addr_type == NET_ADDR_AUTOCONF) {
|
||||
|
|
|
@ -1342,14 +1342,32 @@ void net_if_start_dad(struct net_if *iface)
|
|||
goto out;
|
||||
}
|
||||
|
||||
net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface));
|
||||
ret = net_ipv6_addr_generate_iid(iface, NULL,
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
((uint8_t *)&ipv6->network_counter),
|
||||
(NULL)),
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
(sizeof(ipv6->network_counter)),
|
||||
(0U)),
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
(ipv6->iid ? ipv6->iid->dad_count : 0U),
|
||||
(0U)),
|
||||
&addr,
|
||||
net_if_get_link_addr(iface));
|
||||
if (ret < 0) {
|
||||
NET_WARN("IPv6 IID generation issue (%d)", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, 0);
|
||||
if (!ifaddr) {
|
||||
NET_ERR("Cannot add %s address to interface %p, DAD fails",
|
||||
net_sprint_ipv6_addr(&addr), iface);
|
||||
goto out;
|
||||
}
|
||||
|
||||
IF_ENABLED(CONFIG_NET_IPV6_IID_STABLE, (ipv6->iid = ifaddr));
|
||||
|
||||
/* Start DAD for all the addresses that were added earlier when
|
||||
* the interface was down.
|
||||
*/
|
||||
|
@ -1383,10 +1401,11 @@ void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6_IID_STABLE) || IS_ENABLED(CONFIG_NET_IPV6_PE)) {
|
||||
ifaddr->dad_count++;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6_PE)) {
|
||||
ifaddr->dad_count++;
|
||||
|
||||
timeout = COND_CODE_1(CONFIG_NET_IPV6_PE,
|
||||
(ifaddr->addr_timeout), (0));
|
||||
preferred_lifetime = COND_CODE_1(CONFIG_NET_IPV6_PE,
|
||||
|
@ -3251,16 +3270,29 @@ static void iface_ipv6_start(struct net_if *iface)
|
|||
|
||||
static void iface_ipv6_stop(struct net_if *iface)
|
||||
{
|
||||
struct in6_addr addr = { };
|
||||
struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
|
||||
|
||||
if (!net_if_flag_is_set(iface, NET_IF_IPV6) ||
|
||||
net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface));
|
||||
if (ipv6 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)net_if_ipv6_addr_rm(iface, &addr);
|
||||
IF_ENABLED(CONFIG_NET_IPV6_IID_STABLE, (ipv6->network_counter++));
|
||||
IF_ENABLED(CONFIG_NET_IPV6_IID_STABLE, (ipv6->iid = NULL));
|
||||
|
||||
/* Remove all autoconf addresses */
|
||||
ARRAY_FOR_EACH(ipv6->unicast, i) {
|
||||
if (ipv6->unicast[i].is_used &&
|
||||
ipv6->unicast[i].address.family == AF_INET6 &&
|
||||
ipv6->unicast[i].addr_type == NET_ADDR_AUTOCONF) {
|
||||
(void)net_if_ipv6_addr_rm(iface,
|
||||
&ipv6->unicast[i].address.in6_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iface_ipv6_init(int if_count)
|
||||
|
|
|
@ -98,7 +98,8 @@ static int ethernet_set_config(uint32_t mgmt_request,
|
|||
* generated from old MAC address, from network interface if
|
||||
* needed.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_NET_NATIVE_IPV6)) {
|
||||
if (IS_ENABLED(CONFIG_NET_NATIVE_IPV6) &&
|
||||
IS_ENABLED(CONFIG_NET_IPV6_IID_EUI_64)) {
|
||||
struct in6_addr iid;
|
||||
|
||||
net_ipv6_addr_create_iid(&iid,
|
||||
|
|
|
@ -449,9 +449,22 @@ static int interface_attach(struct net_if *iface, struct net_if *lower_iface)
|
|||
if (IS_ENABLED(CONFIG_NET_IPV6) && ctx->family == AF_INET6) {
|
||||
struct net_if_addr *ifaddr;
|
||||
struct in6_addr iid;
|
||||
int ret;
|
||||
|
||||
/* RFC4213 chapter 3.7 */
|
||||
net_ipv6_addr_create_iid(&iid, net_if_get_link_addr(iface));
|
||||
ret = net_ipv6_addr_generate_iid(iface, NULL,
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
((uint8_t *)&iface->config.ip.ipv6->network_counter),
|
||||
(NULL)),
|
||||
COND_CODE_1(CONFIG_NET_IPV6_IID_STABLE,
|
||||
(sizeof(iface->config.ip.ipv6->network_counter)),
|
||||
(0U)),
|
||||
0,
|
||||
&iid,
|
||||
net_if_get_link_addr(iface));
|
||||
if (ret < 0) {
|
||||
NET_WARN("IPv6 IID generation issue (%d)", ret);
|
||||
}
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface, &iid, NET_ADDR_AUTOCONF, 0);
|
||||
if (!ifaddr) {
|
||||
|
|
Loading…
Reference in New Issue