From 110fa3cd8cceeb62e4edd8d523d7820538efcbeb Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:21:54 +0100 Subject: [PATCH 01/36] config: Define feature flag --- sys/include/net/gnrc/ipv6/nib/conf.h | 7 +++++++ sys/net/gnrc/network_layer/ipv6/nib/Kconfig | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/sys/include/net/gnrc/ipv6/nib/conf.h b/sys/include/net/gnrc/ipv6/nib/conf.h index fddbc03e8005..4ed7f54f272a 100644 --- a/sys/include/net/gnrc/ipv6/nib/conf.h +++ b/sys/include/net/gnrc/ipv6/nib/conf.h @@ -186,6 +186,13 @@ extern "C" { #define CONFIG_GNRC_IPV6_NIB_SLAAC 1 #endif +/** + * @brief Use stable privacy addresses (rfc7217) + */ +#ifndef CONFIG_GNRC_IPV6_STABLE_PRIVACY +#define CONFIG_GNRC_IPV6_STABLE_PRIVACY 0 +#endif + /** * @brief handle Redirect Messages */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/Kconfig b/sys/net/gnrc/network_layer/ipv6/nib/Kconfig index bf87ffdcd224..449765f6c7db 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/Kconfig +++ b/sys/net/gnrc/network_layer/ipv6/nib/Kconfig @@ -38,6 +38,14 @@ config GNRC_IPV6_NIB_SLAAC default n if USEMODULE_GNRC_IPV6_NIB_6LR || USEMODULE_GNRC_IPV6_NIB_6LN default y +config GNRC_IPV6_STABLE_PRIVACY + bool "Use stable privacy addresses (rfc7217)" + depends on GNRC_IPV6_NIB_SLAAC + help + Generate semantically opaque interface identifiers + (i.e. L2ADDR is not embedded) + for SLAAC IPv6 addresses + config GNRC_IPV6_NIB_QUEUE_PKT bool "Use packet queue with address resolution" default n if USEMODULE_GNRC_IPV6_NIB_6LN || GNRC_IPV6_NIB_6LN From 60933a51f8a13dc5d73b41805539efa5f1055826 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 02/36] =?UTF-8?q?=F0=9F=8D=92SLAAC=20only=20for=20/64=20pr?= =?UTF-8?q?efixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 2 ++ sys/net/gnrc/network_layer/ipv6/nib/nib.c | 4 +++- tests/net/gnrc_ipv6_nib/main.c | 2 +- tests/net/gnrc_ipv6_nib_6ln/main.c | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 1736f69cc7d2..cae9343c58cf 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -32,6 +32,8 @@ extern "C" { #endif +#define SLAAC_PREFIX_LENGTH (64U) + #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) /** * @brief Auto-configures an address from a given prefix diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index ac7e3fcfa2e6..4d3c8a5e962e 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -1657,7 +1657,9 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6, DEBUG(" - Preferred lifetime: %" PRIu32 "\n", byteorder_ntohl(pio->pref_ltime)); - if (pio->flags & NDP_OPT_PI_FLAGS_A) { + if (pio->flags & NDP_OPT_PI_FLAGS_A + && pio->prefix_len == SLAAC_PREFIX_LENGTH + ) { _auto_configure_addr(netif, &pio->prefix, pio->prefix_len); } if ((pio->flags & (NDP_OPT_PI_FLAGS_A | NDP_OPT_PI_FLAGS_L)) diff --git a/tests/net/gnrc_ipv6_nib/main.c b/tests/net/gnrc_ipv6_nib/main.c index 3233aa96c564..d18097ce7973 100644 --- a/tests/net/gnrc_ipv6_nib/main.c +++ b/tests/net/gnrc_ipv6_nib/main.c @@ -39,7 +39,7 @@ #define _RTR_LTIME (6612U) #define _REACH_TIME (1210388825UL) #define _RETRANS_TIMER (3691140UL) -#define _LOC_GB_PFX_LEN (45U) +#define _LOC_GB_PFX_LEN (64U) #define _REM_GB_PFX_LEN (37U) #define _PIO_PFX_LTIME (0x8476fedf) diff --git a/tests/net/gnrc_ipv6_nib_6ln/main.c b/tests/net/gnrc_ipv6_nib_6ln/main.c index 96aa995e055a..339339ac4d2e 100644 --- a/tests/net/gnrc_ipv6_nib_6ln/main.c +++ b/tests/net/gnrc_ipv6_nib_6ln/main.c @@ -43,7 +43,7 @@ #define _RTR_LTIME (6612U) #define _REACH_TIME (1210388825UL) #define _RETRANS_TIMER (3691140UL) -#define _LOC_GB_PFX_LEN (45U) +#define _LOC_GB_PFX_LEN (64U) #define _REM_GB_PFX_LEN (37U) #define _PIO_PFX_LTIME (0x8476fedf) #define _CTX_LTIME (29169U) From fd01be3ed19a00a4ea483e1f7d881e277a906765 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 03/36] =?UTF-8?q?=F0=9F=8D=92Documentation=20for=20constan?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index cae9343c58cf..de33ab9cd824 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -32,6 +32,15 @@ extern "C" { #endif +/** + * > An IPv6 address prefix used for stateless autoconfiguration [ACONF] + * of an Ethernet interface must have a length of 64 bits. + * - https://datatracker.ietf.org/doc/html/rfc2464 + * + * > An IPv6 address prefix used for stateless autoconfiguration [RFC4862] + * of an IEEE 802.15.4 interface MUST have a length of 64 bits. + * - https://datatracker.ietf.org/doc/html/rfc4944 + */ #define SLAAC_PREFIX_LENGTH (64U) #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) From 6774248dfc82920fdc24ac8e92ed42d2d9628ab2 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 04/36] =?UTF-8?q?=F0=9F=8D=92Documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index de33ab9cd824..6b1880eb47d4 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -40,9 +40,23 @@ extern "C" { * > An IPv6 address prefix used for stateless autoconfiguration [RFC4862] * of an IEEE 802.15.4 interface MUST have a length of 64 bits. * - https://datatracker.ietf.org/doc/html/rfc4944 + * + * Also see + * @ref INTERFACE_IDENTIFIER_LENGTH + * in combination with "sum" "does not equal 128 bits" + * from https://datatracker.ietf.org/doc/html/rfc4862#section-5.5.3 d) */ #define SLAAC_PREFIX_LENGTH (64U) +/* + * "the address architecture [RFC4291] also defines the length of the interface identifiers" + * - https://datatracker.ietf.org/doc/html/rfc4862#section-2 + * + * "Interface IDs are required to be 64 bits long" + * - https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.1 + */ +#define INTERFACE_IDENTIFIER_LENGTH (64U) + #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) /** * @brief Auto-configures an address from a given prefix From 828ac9d9e3a84aac40ac11eebc57caec01c0b943 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 05/36] =?UTF-8?q?=F0=9F=8D=92creation:=20Check=20IANA=20II?= =?UTF-8?q?D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 7 +++++++ sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index a76cb03778ec..f458823c60a2 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -96,6 +96,13 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, } #endif /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ +bool _iid_is_iana_reserved(const eui64_t *iid) +{ + return (iid->uint64.u64 == htonll(0)) + || (iid->uint32[0].u32 == htonl(0x02005eff) && iid->uint8[4] == 0xfe) + || (iid->uint32[0].u32 == htonl(0xfdffffff) && iid->uint16[2].u16 == htons(0xffff) && iid->uint8[6] == 0xff && (iid->uint8[7] & 0x80)); +} + #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif) { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 6b1880eb47d4..acc6d1146985 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -71,6 +71,18 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, #define _auto_configure_addr(netif, pfx, pfx_len) \ (void)netif; (void)pfx; (void)pfx_len; #endif /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ + +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) +/** + * @brief Check if an interface identifier of an IPv6 address + * is reserved by IANA, i.e. it shouldn't be used + * This is should be checked when the interface identifier is randomly generated. + * @see [RFC5453], https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xhtml + * @param[in] iid The interface identifier to check for + * @return whether the IID is IANA reserved + */ +bool _iid_is_iana_reserved(const eui64_t *iid); + #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) /** * @brief Removes a tentative address from the interface and tries to From 6b5424a8a0dec20190581b903a2fb9cc3601989c Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 06/36] Wrap IANA IID check in IS_ACTIVE --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 2 ++ sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 1 + 2 files changed, 3 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index f458823c60a2..a6bacbccaf31 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -96,12 +96,14 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, } #endif /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) bool _iid_is_iana_reserved(const eui64_t *iid) { return (iid->uint64.u64 == htonll(0)) || (iid->uint32[0].u32 == htonl(0x02005eff) && iid->uint8[4] == 0xfe) || (iid->uint32[0].u32 == htonl(0xfdffffff) && iid->uint16[2].u16 == htons(0xffff) && iid->uint8[6] == 0xff && (iid->uint8[7] & 0x80)); } +#endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index acc6d1146985..3ca9cb7ef693 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -82,6 +82,7 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, * @return whether the IID is IANA reserved */ bool _iid_is_iana_reserved(const eui64_t *iid); +#endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) /** From 227181aa4f18080f8796b432bec7dd084b1bb34f Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 07/36] =?UTF-8?q?=F0=9F=8D=92gnrc=5Fnetif=5Fipv6=5Faddr=5F?= =?UTF-8?q?pfx=5Fidx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/include/net/gnrc/netif/internal.h | 22 ++++++++++++++ sys/net/gnrc/netif/gnrc_netif.c | 44 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/sys/include/net/gnrc/netif/internal.h b/sys/include/net/gnrc/netif/internal.h index 5e0de86c2b60..ebbd92e0ba47 100644 --- a/sys/include/net/gnrc/netif/internal.h +++ b/sys/include/net/gnrc/netif/internal.h @@ -130,6 +130,28 @@ void gnrc_netif_ipv6_addr_remove_internal(gnrc_netif_t *netif, int gnrc_netif_ipv6_addr_idx(gnrc_netif_t *netif, const ipv6_addr_t *addr); +/** + * @brief Returns the index of the first pfx + * in gnrc_netif_t::ipv6_addrs of @p netif + * where the first @p pfx_len bits match with @p pfx + * + * @pre `(netif != NULL) && (pfx != NULL)` + * + * Can be used to check if an address is assigned to an interface. + * + * @param[in] netif the network interface + * @param[in] pfx the address to check + * @param[in] pfx_len the amount of bits to compare + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return index of the first matching address + * in gnrc_netif_t::ipv6_addrs of @p netif + * @return -1, if no matching address found for @p netif + */ +int gnrc_netif_ipv6_addr_pfx_idx(gnrc_netif_t *netif, + const ipv6_addr_t *pfx, uint8_t pfx_len); + /** * @brief Gets state from address flags * diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 8ececfad0356..4d62aea6d62f 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -502,6 +502,9 @@ void gnrc_netif_release(gnrc_netif_t *netif) #if IS_USED(MODULE_GNRC_NETIF_IPV6) static int _addr_idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr); +static int _addr_pfx_idx(const gnrc_netif_t *netif, + const ipv6_addr_t *pfx, + uint8_t pfx_len); static int _group_idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr); static char addr_str[IPV6_ADDR_MAX_STR_LEN]; @@ -730,6 +733,23 @@ int gnrc_netif_ipv6_addr_idx(gnrc_netif_t *netif, return idx; } +int gnrc_netif_ipv6_addr_pfx_idx(gnrc_netif_t *netif, + const ipv6_addr_t *pfx, uint8_t pfx_len) +{ + int idx; + + assert((netif != NULL) && (pfx != NULL)); + DEBUG("gnrc_netif: get index of first address matching %s/%u" + " from interface %" PRIkernel_pid "\n", + ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), + pfx_len, + netif->pid); + gnrc_netif_acquire(netif); + idx = _addr_pfx_idx(netif, pfx, pfx_len); + gnrc_netif_release(netif); + return idx; +} + int gnrc_netif_ipv6_addr_match(gnrc_netif_t *netif, const ipv6_addr_t *addr) { @@ -947,11 +967,35 @@ static int _idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr, bool mcast) return -1; } +static int _pfx_idx(const gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, bool mcast) +{ + //same as function @ref _idx above, but with generalized condition + if (!ipv6_addr_is_unspecified(pfx)) { + const ipv6_addr_t *iplist = (mcast) ? netif->ipv6.groups : + netif->ipv6.addrs; + unsigned ipmax = (mcast) ? GNRC_NETIF_IPV6_GROUPS_NUMOF : + CONFIG_GNRC_NETIF_IPV6_ADDRS_NUMOF; + for (unsigned i = 0; i < ipmax; i++) { + if (ipv6_addr_match_prefix(&iplist[i], pfx) >= pfx_len) { + return i; + } + } + } + return -1; +} + static inline int _addr_idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr) { return _idx(netif, addr, false); } +static inline int _addr_pfx_idx(const gnrc_netif_t *netif, + const ipv6_addr_t *pfx, + uint8_t pfx_len) +{ + return _pfx_idx(netif, pfx, pfx_len, false); +} + static inline int _group_idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr) { return _idx(netif, addr, true); From 3c9e0d08d3f5608b66fe2e5af347645e0e980a4c Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 08/36] =?UTF-8?q?=F0=9F=8D=92Supress=20SLAAC=20trigger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to check for matching address rather than prefix because for a 6LN, the SLAAC prefix is never stored in the prefix list, since everything is considered off-link. --- sys/net/gnrc/network_layer/ipv6/nib/nib.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 4d3c8a5e962e..3b9a3c6d05e3 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -1659,6 +1659,14 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6, if (pio->flags & NDP_OPT_PI_FLAGS_A && pio->prefix_len == SLAAC_PREFIX_LENGTH +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + && (gnrc_netif_ipv6_addr_pfx_idx(netif, &pio->prefix, pio->prefix_len) < 0) + /* if the prefix is already known, + * do not cause generation of a potentially different + * stable privacy address (keyword DAD_Counter). + * refer to https://datatracker.ietf.org/doc/html/rfc4862#section-5.5.3 d) + * */ +#endif ) { _auto_configure_addr(netif, &pio->prefix, pio->prefix_len); } From 356b3d95a7537b1122fa9cf18db0d443b7ec904d Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 09/36] =?UTF-8?q?=F0=9F=8D=92retries:=20New=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys/include/net/gnrc/netif/internal.h | 15 +++++++++++++++ sys/include/net/gnrc/netif/ipv6.h | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/sys/include/net/gnrc/netif/internal.h b/sys/include/net/gnrc/netif/internal.h index ebbd92e0ba47..38c19ba19281 100644 --- a/sys/include/net/gnrc/netif/internal.h +++ b/sys/include/net/gnrc/netif/internal.h @@ -182,6 +182,21 @@ static inline uint8_t gnrc_netif_ipv6_addr_dad_trans(const gnrc_netif_t *netif, return netif->ipv6.addrs_flags[idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } +/** + * @brief Gets number of address generation retries already performed for an address + * + * @param[in] netif the network interface + * @param[in] idx index of the address (and its flags) + * + * @return the number of address generation retries already + * performed + */ +static inline uint8_t gnrc_netif_ipv6_addr_gen_retries(const gnrc_netif_t *netif, + int idx) +{ + return (netif->ipv6.addrs_flags[idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES) >> GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS; +} + /** * @brief Returns the index of an address in gnrc_netif_t::ipv6_addrs of @p * netif that matches @p addr best diff --git a/sys/include/net/gnrc/netif/ipv6.h b/sys/include/net/gnrc/netif/ipv6.h index d58c708017d8..f09243b2820e 100644 --- a/sys/include/net/gnrc/netif/ipv6.h +++ b/sys/include/net/gnrc/netif/ipv6.h @@ -68,6 +68,17 @@ extern "C" { * @brief Address is an anycast address */ #define GNRC_NETIF_IPV6_ADDRS_FLAGS_ANYCAST (0x20U) + +/** + * @brief Number of address generation retries + * For addresses generated as per RFC7217, this stores the DAD_Counter value + * and the upper limit is defined by @ref STABLE_PRIVACY_IDGEN_RETRIES + */ +#define GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES (0xC0U) +/** + * @brief Shift position of address generation retries + */ +#define GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS (6) /** @} */ /** From f9343402e6b2ae0f149cb189d94e225d56403ea0 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:12:38 +0100 Subject: [PATCH 10/36] Wrap retries flag in IS_ACTIVE --- sys/include/net/gnrc/netif/internal.h | 2 ++ sys/include/net/gnrc/netif/ipv6.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sys/include/net/gnrc/netif/internal.h b/sys/include/net/gnrc/netif/internal.h index 38c19ba19281..d9d11cae4e40 100644 --- a/sys/include/net/gnrc/netif/internal.h +++ b/sys/include/net/gnrc/netif/internal.h @@ -182,6 +182,7 @@ static inline uint8_t gnrc_netif_ipv6_addr_dad_trans(const gnrc_netif_t *netif, return netif->ipv6.addrs_flags[idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) /** * @brief Gets number of address generation retries already performed for an address * @@ -196,6 +197,7 @@ static inline uint8_t gnrc_netif_ipv6_addr_gen_retries(const gnrc_netif_t *netif { return (netif->ipv6.addrs_flags[idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES) >> GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS; } +#endif /** * @brief Returns the index of an address in gnrc_netif_t::ipv6_addrs of @p diff --git a/sys/include/net/gnrc/netif/ipv6.h b/sys/include/net/gnrc/netif/ipv6.h index f09243b2820e..fd756ac7c3fa 100644 --- a/sys/include/net/gnrc/netif/ipv6.h +++ b/sys/include/net/gnrc/netif/ipv6.h @@ -69,6 +69,7 @@ extern "C" { */ #define GNRC_NETIF_IPV6_ADDRS_FLAGS_ANYCAST (0x20U) +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) /** * @brief Number of address generation retries * For addresses generated as per RFC7217, this stores the DAD_Counter value @@ -79,6 +80,7 @@ extern "C" { * @brief Shift position of address generation retries */ #define GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS (6) +#endif /** @} */ /** From 1836de505ad8a083ebec9bcb82fad59166478866 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:03:00 +0100 Subject: [PATCH 11/36] config: RFC params --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 3ca9cb7ef693..a305e76fd855 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -57,6 +57,27 @@ extern "C" { */ #define INTERFACE_IDENTIFIER_LENGTH (64U) +/** + * @name Stable privacy host constants + * @see [RFC 7217, section 7](https://tools.ietf.org/html/rfc7217#section-7) + * @{ + */ +/** + * @brief Limit for stable privacy (IDGEN) addr. generation retries for subsequent DAD failures + * + * @note Must not be greater than 3 for @ref net_gnrc since + * @ref GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES restricts it to + * that number. + */ +#ifndef STABLE_PRIVACY_IDGEN_RETRIES +#define STABLE_PRIVACY_IDGEN_RETRIES (3U) /*default value*/ +#endif + +#ifndef STABLE_PRIVACY_IDGEN_DELAY_MS +#define STABLE_PRIVACY_IDGEN_DELAY_MS 1000 /*default value*/ +#endif +/** @} */ + #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) /** * @brief Auto-configures an address from a given prefix From fa015a2e40aa00d7dffcb4cb8b87fd9f8c3f0433 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:05:54 +0100 Subject: [PATCH 12/36] includes --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index a6bacbccaf31..c3c53f3e0c22 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -15,6 +15,12 @@ #include #include +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) +#include "_nib-slaac.h" +#include +#include "ztimer.h" +#include "random.h" +#endif #include "log.h" #include "luid.h" From 6340dcd888105e2db5998b7c35a7a52f3ebb0e2c Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:16:53 +0100 Subject: [PATCH 13/36] IDGEN --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 57 +++++++++++++++++++ .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 15 +++++ 2 files changed, 72 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index c3c53f3e0c22..cb6b4888f57d 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -109,6 +109,63 @@ bool _iid_is_iana_reserved(const eui64_t *iid) || (iid->uint32[0].u32 == htonl(0x02005eff) && iid->uint8[4] == 0xfe) || (iid->uint32[0].u32 == htonl(0xfdffffff) && iid->uint16[2].u16 == htons(0xffff) && iid->uint8[6] == 0xff && (iid->uint8[7] & 0x80)); } + +uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + const uint8_t dad_ctr) +{ +#ifndef STABLE_PRIVACY_SECRET_KEY +#error "Stable privacy requires a secret_key, this should have been configured by sys/net/gnrc/Makefile.dep" +#endif + const uint8_t secret_key[16] = { STABLE_PRIVACY_SECRET_KEY }; + //SHOULD be of at least 128 bits - https://datatracker.ietf.org/doc/html/rfc7217 + + uint8_t digest[SHA256_DIGEST_LENGTH]; + + { + sha256_context_t c; + sha256_init(&c); + sha256_update(&c, pfx, sizeof(*pfx)); + +#if GNRC_NETIF_L2ADDR_MAXLEN > 0 + if (netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR) { + sha256_update(&c, &netif->l2addr, netif->l2addr_len); + } else +#endif + sha256_update(&c, &netif->pid, sizeof(netif->pid)); + + sha256_update(&c, &dad_ctr, sizeof(dad_ctr)); + sha256_update(&c, secret_key, sizeof(secret_key)); + sha256_final(&c, digest); + } + + assert(iid->uint64.u64 == 0); + assert(sizeof(digest) >= sizeof(*iid)); //as bits: 256 >= 64 //digest is large enough + + //copy digest into IID + //RFC 7217 says "starting from the least significant bit", + //i.e. in reverse order + for (uint8_t i = 0; i < sizeof(*iid); i++) { //for each of the 8 bytes + for (int j = 0; j < 8; j++) { //for each of the 8 bits _within byte_ + if ((digest[(sizeof(digest)-1)-i])&(1<uint8[i] |= 1 << ((8-1)-j); //set 1 //precondition: *iid = 0 + } + } + } + + /* "The resulting Interface Identifier SHOULD be compared against + * the reserved IPv6 Interface Identifiers" + * - https://datatracker.ietf.org/doc/html/rfc7217#section-5 */ + if (_iid_is_iana_reserved(iid)) { + if (!stable_privacy_should_retry_idgen(&dad_ctr, + "IANA reserved IID generated")) { + return -1; + } + iid->uint64.u64 = 0; /* @pre for method call */ + return _ipv6_get_rfc7217_iid(iid, netif, pfx, dad_ctr); + } + + return dad_ctr; +} #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index a305e76fd855..44a4fd998e8f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -103,6 +103,21 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, * @return whether the IID is IANA reserved */ bool _iid_is_iana_reserved(const eui64_t *iid); + +/** + * @brief + * @pre @p iid is all 0 bits (iid->uint64.u64 == 0) + * @param[out] iid + * @param[in] netif The network interface to use as source for IID generation. + * ("Net_iface" in rfc7217) + * @param[in] pfx The prefix for which the IID is to be generated. + * ("Prefix" in rfc7217) + * @param[in] dad_ctr ("DAD_Counter" in rfc7217) + * @return new value of DAD_Counter, to be stored associated with the address + * @return -1 if failed, because retry limit reached + */ +uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t dad_ctr); #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) From 20375dda294f9ec315bb5465d41447a08f542d9c Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:18:26 +0100 Subject: [PATCH 14/36] Generate secret_key at compilation Requires Python >=3.6, which is already EOL, so not noteworthy https://github.com/RIOT-OS/RIOT/pull/20370#discussion_r1498370589 --- sys/net/gnrc/Makefile.dep | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sys/net/gnrc/Makefile.dep b/sys/net/gnrc/Makefile.dep index 3dab93eade61..81f96b38c2d6 100644 --- a/sys/net/gnrc/Makefile.dep +++ b/sys/net/gnrc/Makefile.dep @@ -431,6 +431,21 @@ ifneq (,$(filter gnrc_ipv6_nib,$(USEMODULE))) USEMODULE += random endif +#This checks if the option is being set via Kconfig or CFLAGS +ifneq (,$(or $(CONFIG_GNRC_IPV6_STABLE_PRIVACY),$(filter -DCONFIG_GNRC_IPV6_STABLE_PRIVACY=1,$(CFLAGS)))) + # Set another macro that is needed for this option. + + ##prepare value + stable_privacy_secret_key != python3 -c "import secrets; print(','.join([f'0x{byte:02x}' for byte in secrets.token_bytes(16)]))" + + ##set macro + CFLAGS += -DSTABLE_PRIVACY_SECRET_KEY=$(stable_privacy_secret_key) + + # dependencies + USEMODULE += hashes ##include "hashes/sha256.h" + USEMODULE += ztimer_msec +endif + ifneq (,$(filter gnrc_udp,$(USEMODULE))) DEFAULT_MODULE += auto_init_gnrc_udp USEMODULE += gnrc_nettype_udp From 0a31c7386c6748dc77d7eb79e718102d9076f71f Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:17:31 +0100 Subject: [PATCH 15/36] Retry condition check --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 12 ++++++++++++ sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index cb6b4888f57d..535f24383e02 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -110,6 +110,18 @@ bool _iid_is_iana_reserved(const eui64_t *iid) || (iid->uint32[0].u32 == htonl(0xfdffffff) && iid->uint16[2].u16 == htons(0xffff) && iid->uint8[6] == 0xff && (iid->uint8[7] & 0x80)); } +inline bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason) { + printf("%s", reason); + if (*dad_ctr < STABLE_PRIVACY_IDGEN_RETRIES) { //within retry limit + *dad_ctr += 1; + printf(", retrying IDGEN. (%u/%u)\n", *dad_ctr, STABLE_PRIVACY_IDGEN_RETRIES); + return true; + } + //retried often enough + printf(", not retrying: IDGEN_RETRIES limit reached\n"); + return false; +} + uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, const uint8_t dad_ctr) { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 44a4fd998e8f..652c293eeab1 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -104,6 +104,12 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, */ bool _iid_is_iana_reserved(const eui64_t *iid); +/** + * @param[in,out] dad_ctr + * @param[in] reason + */ +bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); + /** * @brief * @pre @p iid is all 0 bits (iid->uint64.u64 == 0) From ec7caef882cf7770680ec9ac1dda57d37f93278d Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:18:05 +0100 Subject: [PATCH 16/36] Overload method --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 12 ++++++++++++ sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 535f24383e02..ac07ff3ca42c 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -36,8 +36,20 @@ #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) static char addr_str[IPV6_ADDR_MAX_STR_LEN]; +#if !IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len) +#else +inline void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len) +{ + _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, 0); +} + +void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, + const ipv6_addr_t *pfx, uint8_t pfx_len, + uint8_t dad_ctr) +#endif { ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; int idx; diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 652c293eeab1..5ecd2b03f5c1 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -88,6 +88,14 @@ extern "C" { */ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len); +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) +/** + * @param dad_ctr rfc7217 DAD_Counter + */ +void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len, uint8_t dad_ctr); +#endif + #else /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ #define _auto_configure_addr(netif, pfx, pfx_len) \ (void)netif; (void)pfx; (void)pfx_len; From 758b838a271a4999800d47b5feab3424071fb112 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:20:02 +0100 Subject: [PATCH 17/36] Use IDGEN --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index ac07ff3ca42c..2b3f47f26705 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -74,10 +74,15 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) bool new_address = false; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + dad_ctr = _ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, dad_ctr); + flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); +#else if (gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]) < 0) { DEBUG("nib: Can't get IID on interface %u\n", netif->pid); return; } +#endif ipv6_addr_init_prefix(&addr, pfx, pfx_len); if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) { if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len, @@ -89,6 +94,17 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) new_address = true; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ + } else { +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + /*"the same network prefix" - https://datatracker.ietf.org/doc/html/rfc7217#section-5*/ + /*"unacceptable identifier" -> retry IDGEN (dad_ctr+1)*/ + if (!stable_privacy_should_retry_idgen(&dad_ctr, "Generated address already exists")) { + return; + } + + _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, dad_ctr); + return; +#endif } #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) From 30914b7ae70764508611e47f8a96b195627fea88 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:20:43 +0100 Subject: [PATCH 18/36] Handle DAD --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 2b3f47f26705..fc9f1dbb8e45 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -270,8 +270,33 @@ void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) DEBUG("nib: other node has TENTATIVE address %s assigned " "=> removing that address\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + int idx = gnrc_netif_ipv6_addr_idx(netif, addr); + assert(idx >= 0); + uint8_t dad_counter = gnrc_netif_ipv6_addr_gen_retries(netif, idx); +#endif gnrc_netif_ipv6_addr_remove_internal(netif, addr); +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + if (stable_privacy_should_retry_idgen(&dad_counter, "Duplicate address detected")) { + + //> Hosts SHOULD introduce a random delay between 0 and IDGEN_DELAY seconds + //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 + uint32_t random_delay_ms = random_uint32_range(0, STABLE_PRIVACY_IDGEN_DELAY_MS); + ztimer_sleep(ZTIMER_MSEC, random_delay_ms); + + _auto_configure_addr_with_dad_ctr(netif, addr, SLAAC_PREFIX_LENGTH, dad_counter); + } else { + //"hosts MUST NOT automatically fall back to employing other algorithms for generating Interface Identifiers" + //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 + + //> If the address is a link-local address + //> [...] + //> not formed from an interface identifier based on the hardware address + //> IP operation on the interface MAY be continued + //- https://datatracker.ietf.org/doc/html/rfc4862#section-5.4.5 + } +#else if (!ipv6_addr_is_link_local(addr) || !_try_addr_reconfiguration(netif)) { /* Cannot use target address as personal address and can @@ -287,6 +312,7 @@ void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) "but DHCPv6 is not provided", netif->pid); } } +#endif } static int _get_netif_state(gnrc_netif_t **netif, const ipv6_addr_t *addr) From cb846fdc7f8c982617b98cedc3944742957a0bd9 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:21:00 +0100 Subject: [PATCH 19/36] Fix `unused-function` --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index fc9f1dbb8e45..ef234b5fdf00 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -209,6 +209,7 @@ uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) +#if !IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif) { uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN]; @@ -264,6 +265,7 @@ static bool _try_addr_reconfiguration(gnrc_netif_t *netif) } return hwaddr_reconf; } +#endif void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) { From ff813069ccf4d41e8d4b55dee0b64608a99dee20 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:02:42 +0100 Subject: [PATCH 20/36] IDGEN error handling and logging --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 21 +++++++++++-------- .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 9 ++++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index ef234b5fdf00..0872f19ed66c 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -75,7 +75,9 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, bool new_address = false; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - dad_ctr = _ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, dad_ctr); + if (_ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, &dad_ctr) < 0) { + return; + } flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); #else if (gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]) < 0) { @@ -139,19 +141,20 @@ bool _iid_is_iana_reserved(const eui64_t *iid) } inline bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason) { - printf("%s", reason); if (*dad_ctr < STABLE_PRIVACY_IDGEN_RETRIES) { //within retry limit + LOG_DEBUG("nib: %s", reason); *dad_ctr += 1; - printf(", retrying IDGEN. (%u/%u)\n", *dad_ctr, STABLE_PRIVACY_IDGEN_RETRIES); + LOG_DEBUG(", retrying IDGEN. (%u/%u)\n", *dad_ctr, STABLE_PRIVACY_IDGEN_RETRIES); return true; } //retried often enough - printf(", not retrying: IDGEN_RETRIES limit reached\n"); + LOG_WARNING("nib: %s", reason); + LOG_WARNING(", not retrying: IDGEN_RETRIES limit reached\n"); return false; } -uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, - const uint8_t dad_ctr) +int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr) { #ifndef STABLE_PRIVACY_SECRET_KEY #error "Stable privacy requires a secret_key, this should have been configured by sys/net/gnrc/Makefile.dep" @@ -173,7 +176,7 @@ uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv #endif sha256_update(&c, &netif->pid, sizeof(netif->pid)); - sha256_update(&c, &dad_ctr, sizeof(dad_ctr)); + sha256_update(&c, dad_ctr, sizeof(*dad_ctr)); sha256_update(&c, secret_key, sizeof(secret_key)); sha256_final(&c, digest); } @@ -196,7 +199,7 @@ uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv * the reserved IPv6 Interface Identifiers" * - https://datatracker.ietf.org/doc/html/rfc7217#section-5 */ if (_iid_is_iana_reserved(iid)) { - if (!stable_privacy_should_retry_idgen(&dad_ctr, + if (!stable_privacy_should_retry_idgen(dad_ctr, "IANA reserved IID generated")) { return -1; } @@ -204,7 +207,7 @@ uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv return _ipv6_get_rfc7217_iid(iid, netif, pfx, dad_ctr); } - return dad_ctr; + return 0; } #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 5ecd2b03f5c1..67b1b533d855 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -126,12 +126,13 @@ bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); * ("Net_iface" in rfc7217) * @param[in] pfx The prefix for which the IID is to be generated. * ("Prefix" in rfc7217) - * @param[in] dad_ctr ("DAD_Counter" in rfc7217) - * @return new value of DAD_Counter, to be stored associated with the address + * @param[in,out] dad_ctr ("DAD_Counter" in rfc7217) + * Value may increase and is to be stored associated with the address by caller + * @return 0 on success * @return -1 if failed, because retry limit reached */ -uint8_t _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t dad_ctr); +int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr); #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) From e9a5b1cb3e49c19939b98d74f198409a91b4f058 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:44:32 +0100 Subject: [PATCH 21/36] Allow rfc7217 IDGEN without L2 addr Move pre-condition check to the corresponding method requiring this condition --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 0872f19ed66c..4db7f49f571f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -64,10 +64,6 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, return; } #endif - if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) { - DEBUG("nib: interface %i has no link-layer addresses\n", netif->pid); - return; - } DEBUG("nib: add address based on %s/%u automatically to interface %u\n", ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), pfx_len, netif->pid); @@ -80,6 +76,10 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, } flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); #else + if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) { + DEBUG("nib: interface %i has no link-layer addresses\n", netif->pid); + return; + } if (gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]) < 0) { DEBUG("nib: Can't get IID on interface %u\n", netif->pid); return; From 8bc9b10d3aab9d5ab0d147422696e8df7abda128 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:42:42 +0100 Subject: [PATCH 22/36] Perform DAD for RPL PIO --- sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c index 8dff23925d18..de3ee7437a8c 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c @@ -50,6 +50,7 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#include "../../network_layer/ipv6/nib/_nib-slaac.h" static char addr_str[IPV6_ADDR_MAX_STR_LEN]; @@ -585,10 +586,8 @@ static bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt && !(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) { break; } - ipv6_addr_set_aiid(&pi->prefix, iid.uint8); - /* TODO: find a way to do this with DAD (i.e. state != VALID) */ - gnrc_netif_ipv6_addr_add_internal(netif, &pi->prefix, pi->prefix_len, - GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID); + _auto_configure_addr(netif, &pi->prefix, pi->prefix_len); + /* set lifetimes */ gnrc_ipv6_nib_pl_set(netif->pid, &pi->prefix, pi->prefix_len, _sec_to_ms(byteorder_ntohl(pi->valid_lifetime)), From f96b61063b00766124d5b2c73c9cd323dc7aebaf Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 8 Feb 2024 15:02:33 +0100 Subject: [PATCH 23/36] RFC7217 for NETOPT_IPV6_IID --- sys/include/net/netopt.h | 19 ++++++++++ sys/net/gnrc/netif/gnrc_netif.c | 38 +++++++++++++++++-- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 7 +++- tests/net/gnrc_netif/main.c | 8 ++-- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 213418a7c33f..32d8cbf620be 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -27,6 +27,8 @@ #include #include +#include +#include "eui64.h" #ifdef __cplusplus extern "C" { @@ -911,6 +913,23 @@ typedef enum { /* add other states if needed */ } netopt_state_t; +/** + * @brief Option parameter to be used with @ref NETOPT_IPV6_IID + */ +enum { + NETOPT_IPV6_IID_HWADDR = 0, + NETOPT_IPV6_IID_RFC7217, +}; + +/** + * @brief Data for @ref NETOPT_IPV6_IID when using RFC7217 + */ +typedef struct { + eui64_t *iid; + const ipv6_addr_t *pfx; + uint8_t *dad_ctr; +} netopt_ipv6_rfc7217_iid_data; + /** * @brief Option parameter to be used with @ref NETOPT_RF_TESTMODE */ diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 4d62aea6d62f..754907307be8 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -49,6 +49,7 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#include "../network_layer/ipv6/nib/_nib-slaac.h" static void _update_l2addr_from_dev(gnrc_netif_t *netif); static void _check_netdev_capabilities(netdev_t *dev); @@ -269,8 +270,23 @@ int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt) } break; case NETOPT_IPV6_IID: - assert(opt->data_len >= sizeof(eui64_t)); - res = gnrc_netif_ipv6_get_iid(netif, opt->data); + switch ((int16_t)opt->context) { + case NETOPT_IPV6_IID_HWADDR: + assert(opt->data_len >= sizeof(eui64_t)); + res = gnrc_netif_ipv6_get_iid(netif, opt->data); + break; +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + case NETOPT_IPV6_IID_RFC7217: + assert(opt->data_len == sizeof(netopt_ipv6_rfc7217_iid_data)); + netopt_ipv6_rfc7217_iid_data *data = + (netopt_ipv6_rfc7217_iid_data *) opt->data; + res = _ipv6_get_rfc7217_iid( + data->iid, netif, data->pfx, data->dad_ctr); + break; +#endif + default: + break; + } break; case NETOPT_MAX_PDU_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { @@ -1328,8 +1344,22 @@ int gnrc_netif_ipv6_add_prefix(gnrc_netif_t *netif, assert(netif != NULL); DEBUG("gnrc_netif: (re-)configure prefix %s/%d\n", ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), pfx_len); - if (gnrc_netapi_get(netif->pid, NETOPT_IPV6_IID, 0, &iid, - sizeof(eui64_t)) >= 0) { +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + uint8_t dad_ctr; + netopt_ipv6_rfc7217_iid_data data; + data.iid = &iid; + data.pfx = pfx; + data.dad_ctr = &dad_ctr; + /* no need to store dad_ctr with address (via flags) + * as it can't fail DAD, since already valid */ +#endif + if (gnrc_netapi_get(netif->pid, NETOPT_IPV6_IID, +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + NETOPT_IPV6_IID_RFC7217, &data, sizeof(data) +#else + NETOPT_IPV6_IID_HWADDR, &iid, sizeof(eui64_t) +#endif + ) >= 0) { ipv6_addr_set_aiid(&addr, iid.uint8); } else { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 4db7f49f571f..d71808ef1626 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -181,7 +181,10 @@ int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_ad sha256_final(&c, digest); } - assert(iid->uint64.u64 == 0); + iid->uint64.u64 = 0; + //uninitialized if called via gnrc_netapi_get (NETOPT_IPV6_IID_RFC7217) + //needs to be all zeros as precondition for the following copy operation + assert(sizeof(digest) >= sizeof(*iid)); //as bits: 256 >= 64 //digest is large enough //copy digest into IID @@ -190,7 +193,7 @@ int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_ad for (uint8_t i = 0; i < sizeof(*iid); i++) { //for each of the 8 bytes for (int j = 0; j < 8; j++) { //for each of the 8 bits _within byte_ if ((digest[(sizeof(digest)-1)-i])&(1<uint8[i] |= 1 << ((8-1)-j); //set 1 //precondition: *iid = 0 + iid->uint8[i] |= 1 << ((8-1)-j); //set 1 //precondition: iid->uint8[i] = 0 } } } diff --git a/tests/net/gnrc_netif/main.c b/tests/net/gnrc_netif/main.c index caf86553e173..76fc290548a8 100644 --- a/tests/net/gnrc_netif/main.c +++ b/tests/net/gnrc_netif/main.c @@ -805,12 +805,12 @@ static void test_netapi_get__IPV6_IID(void) TEST_ASSERT_EQUAL_INT(sizeof(eui64_t), gnrc_netapi_get(ethernet_netif.pid, NETOPT_IPV6_IID, - 0, &value, sizeof(value))); + NETOPT_IPV6_IID_HWADDR, &value, sizeof(value))); TEST_ASSERT_EQUAL_INT(0, memcmp(&value, ðernet_ipv6_ll.u64[1], sizeof(value))); TEST_ASSERT_EQUAL_INT(sizeof(eui64_t), gnrc_netapi_get(ieee802154_netif.pid, NETOPT_IPV6_IID, - 0, &value, sizeof(value))); + NETOPT_IPV6_IID_HWADDR, &value, sizeof(value))); TEST_ASSERT_EQUAL_INT(0, memcmp(&value, &ieee802154_ipv6_ll_long.u64[1], sizeof(value))); TEST_ASSERT_EQUAL_INT(sizeof(ieee802154_l2addr_len), @@ -820,7 +820,7 @@ static void test_netapi_get__IPV6_IID(void) sizeof(ieee802154_l2addr_len))); TEST_ASSERT_EQUAL_INT(sizeof(eui64_t), gnrc_netapi_get(ieee802154_netif.pid, NETOPT_IPV6_IID, - 0, &value, + NETOPT_IPV6_IID_HWADDR, &value, sizeof(value))); TEST_ASSERT_EQUAL_INT(0, memcmp(&value, &ieee802154_eui64_short, sizeof(value))); @@ -833,7 +833,7 @@ static void test_netapi_get__IPV6_IID(void) sizeof(ieee802154_l2addr_len))); TEST_ASSERT_EQUAL_INT(-ENOTSUP, gnrc_netapi_get(netifs[0].pid, NETOPT_IPV6_IID, - 0, &value, sizeof(value))); + NETOPT_IPV6_IID_HWADDR, &value, sizeof(value))); } static void test_netapi_get__MAX_PACKET_SIZE(void) From f54416526f6018abaa2b2a2fa8b6f5b5f83500ec Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 01:22:10 +0100 Subject: [PATCH 24/36] Rename method --- sys/net/gnrc/netif/gnrc_netif.c | 2 +- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 10 +++++----- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 754907307be8..08912d4f892b 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -280,7 +280,7 @@ int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt) assert(opt->data_len == sizeof(netopt_ipv6_rfc7217_iid_data)); netopt_ipv6_rfc7217_iid_data *data = (netopt_ipv6_rfc7217_iid_data *) opt->data; - res = _ipv6_get_rfc7217_iid( + res = ipv6_get_rfc7217_iid( data->iid, netif, data->pfx, data->dad_ctr); break; #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index d71808ef1626..99cb0c33542f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -71,7 +71,7 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, bool new_address = false; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - if (_ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, &dad_ctr) < 0) { + if (ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, &dad_ctr) < 0) { return; } flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); @@ -153,8 +153,8 @@ inline bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reas return false; } -int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t *dad_ctr) +int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr) { #ifndef STABLE_PRIVACY_SECRET_KEY #error "Stable privacy requires a secret_key, this should have been configured by sys/net/gnrc/Makefile.dep" @@ -207,7 +207,7 @@ int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_ad return -1; } iid->uint64.u64 = 0; /* @pre for method call */ - return _ipv6_get_rfc7217_iid(iid, netif, pfx, dad_ctr); + return ipv6_get_rfc7217_iid(iid, netif, pfx, dad_ctr); } return 0; @@ -286,7 +286,7 @@ void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) gnrc_netif_ipv6_addr_remove_internal(netif, addr); #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - if (stable_privacy_should_retry_idgen(&dad_counter, "Duplicate address detected")) { + if (_stable_privacy_should_retry_idgen(&dad_counter, "Duplicate address detected")) { //> Hosts SHOULD introduce a random delay between 0 and IDGEN_DELAY seconds //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 67b1b533d855..362b849422ec 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -131,8 +131,8 @@ bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); * @return 0 on success * @return -1 if failed, because retry limit reached */ -int _ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t *dad_ctr); +int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr); #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN) From 4635a2eae7c9288ee3ee4236ddd1cea985788147 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 01:23:23 +0100 Subject: [PATCH 25/36] Rename method --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 8 ++++---- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 99cb0c33542f..31f048e4873f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -100,7 +100,7 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) /*"the same network prefix" - https://datatracker.ietf.org/doc/html/rfc7217#section-5*/ /*"unacceptable identifier" -> retry IDGEN (dad_ctr+1)*/ - if (!stable_privacy_should_retry_idgen(&dad_ctr, "Generated address already exists")) { + if (!_stable_privacy_should_retry_idgen(&dad_ctr, "Generated address already exists")) { return; } @@ -140,7 +140,7 @@ bool _iid_is_iana_reserved(const eui64_t *iid) || (iid->uint32[0].u32 == htonl(0xfdffffff) && iid->uint16[2].u16 == htons(0xffff) && iid->uint8[6] == 0xff && (iid->uint8[7] & 0x80)); } -inline bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason) { +inline bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason) { if (*dad_ctr < STABLE_PRIVACY_IDGEN_RETRIES) { //within retry limit LOG_DEBUG("nib: %s", reason); *dad_ctr += 1; @@ -202,8 +202,8 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_add * the reserved IPv6 Interface Identifiers" * - https://datatracker.ietf.org/doc/html/rfc7217#section-5 */ if (_iid_is_iana_reserved(iid)) { - if (!stable_privacy_should_retry_idgen(dad_ctr, - "IANA reserved IID generated")) { + if (!_stable_privacy_should_retry_idgen(dad_ctr, + "IANA reserved IID generated")) { return -1; } iid->uint64.u64 = 0; /* @pre for method call */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 362b849422ec..2044d121f3f9 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -116,7 +116,7 @@ bool _iid_is_iana_reserved(const eui64_t *iid); * @param[in,out] dad_ctr * @param[in] reason */ -bool stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); +bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); /** * @brief From 46b1107b3bc1b858d1b4bc58b2929072837389fa Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:40:20 +0100 Subject: [PATCH 26/36] No RFC7217 for 6LN link-local addresses Wrap in `if(is_rfc7217)`, use normal IDGEN if false --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 31f048e4873f..ab5e6c7a2f0f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -71,20 +71,25 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, bool new_address = false; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - if (ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, &dad_ctr) < 0) { - return; - } - flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); -#else - if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) { - DEBUG("nib: interface %i has no link-layer addresses\n", netif->pid); - return; - } - if (gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]) < 0) { - DEBUG("nib: Can't get IID on interface %u\n", netif->pid); - return; - } + bool is_rfc7217 = !(gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)); + if (is_rfc7217) { + if (ipv6_get_rfc7217_iid((eui64_t *) &addr.u64[1], netif, pfx, &dad_ctr) < 0) { + return; + } + flags |= (dad_ctr << GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS); + } else #endif + { + if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) { + DEBUG("nib: interface %i has no link-layer addresses\n", netif->pid); + return; + } + if (gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]) < 0) { + DEBUG("nib: Can't get IID on interface %u\n", netif->pid); + return; + } + } + ipv6_addr_init_prefix(&addr, pfx, pfx_len); if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) { if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len, @@ -96,8 +101,9 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) new_address = true; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ - } else { + } #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + else if (is_rfc7217) { /*"the same network prefix" - https://datatracker.ietf.org/doc/html/rfc7217#section-5*/ /*"unacceptable identifier" -> retry IDGEN (dad_ctr+1)*/ if (!_stable_privacy_should_retry_idgen(&dad_ctr, "Generated address already exists")) { @@ -106,8 +112,8 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, dad_ctr); return; -#endif } +#endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) /* mark link-local addresses as valid on 6LN */ From 63e98acb13045d1bfa44d0eae8f2a238d81aba36 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:05:15 +0100 Subject: [PATCH 27/36] IDGEN: require L2 addr Remove fallback to netif.pid because presumably doesn't fulfill the RFC stability requirements of "constant across system bootstrap sequences and other network events (e.g., bringing another interface up or down)" --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 17 +++++++++-------- .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index ab5e6c7a2f0f..3595ee22b15e 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -162,6 +162,14 @@ inline bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *rea int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t *dad_ctr) { +#if GNRC_NETIF_L2ADDR_MAXLEN > 0 + if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) +#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */ + { + LOG_ERROR("nib: interface %i has no link-layer addresses\n", netif->pid); + return -ENOTSUP; + } + #ifndef STABLE_PRIVACY_SECRET_KEY #error "Stable privacy requires a secret_key, this should have been configured by sys/net/gnrc/Makefile.dep" #endif @@ -174,14 +182,7 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_add sha256_context_t c; sha256_init(&c); sha256_update(&c, pfx, sizeof(*pfx)); - -#if GNRC_NETIF_L2ADDR_MAXLEN > 0 - if (netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR) { - sha256_update(&c, &netif->l2addr, netif->l2addr_len); - } else -#endif - sha256_update(&c, &netif->pid, sizeof(netif->pid)); - + sha256_update(&c, &netif->l2addr, netif->l2addr_len); sha256_update(&c, dad_ctr, sizeof(*dad_ctr)); sha256_update(&c, secret_key, sizeof(secret_key)); sha256_final(&c, digest); diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 2044d121f3f9..a8855fa27f3d 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -130,6 +130,7 @@ bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); * Value may increase and is to be stored associated with the address by caller * @return 0 on success * @return -1 if failed, because retry limit reached + * @return `-ENOTSUP`, if interface has no link-layer address. */ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t *dad_ctr); From 0962383367b870890ead80ec0facab18836525d5 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:44:50 +0100 Subject: [PATCH 28/36] finalize: vera++ style check --- sys/include/net/gnrc/netif/internal.h | 4 +++- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/include/net/gnrc/netif/internal.h b/sys/include/net/gnrc/netif/internal.h index d9d11cae4e40..358cf786655e 100644 --- a/sys/include/net/gnrc/netif/internal.h +++ b/sys/include/net/gnrc/netif/internal.h @@ -195,7 +195,9 @@ static inline uint8_t gnrc_netif_ipv6_addr_dad_trans(const gnrc_netif_t *netif, static inline uint8_t gnrc_netif_ipv6_addr_gen_retries(const gnrc_netif_t *netif, int idx) { - return (netif->ipv6.addrs_flags[idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES) >> GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS; + return (netif->ipv6.addrs_flags[idx] + & GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES) + >> GNRC_NETIF_IPV6_ADDRS_FLAGS_IDGEN_RETRIES_POS; } #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 3595ee22b15e..e8006c728032 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -302,7 +302,8 @@ void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) _auto_configure_addr_with_dad_ctr(netif, addr, SLAAC_PREFIX_LENGTH, dad_counter); } else { - //"hosts MUST NOT automatically fall back to employing other algorithms for generating Interface Identifiers" + //"hosts MUST NOT automatically fall back to employing other algorithms + // for generating Interface Identifiers" //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 //> If the address is a link-local address From ca4f23a891d8d27ef1c9db1a9d15e7b08095d27d Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Sat, 10 Feb 2024 19:51:14 +0100 Subject: [PATCH 29/36] Wrap --- sys/include/net/netopt.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 32d8cbf620be..9ecf76ad21e1 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -25,6 +25,7 @@ #ifndef NET_NETOPT_H #define NET_NETOPT_H +#include #include #include #include @@ -918,9 +919,12 @@ typedef enum { */ enum { NETOPT_IPV6_IID_HWADDR = 0, +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) NETOPT_IPV6_IID_RFC7217, +#endif }; +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) /** * @brief Data for @ref NETOPT_IPV6_IID when using RFC7217 */ @@ -929,6 +933,7 @@ typedef struct { const ipv6_addr_t *pfx; uint8_t *dad_ctr; } netopt_ipv6_rfc7217_iid_data; +#endif /** * @brief Option parameter to be used with @ref NETOPT_RF_TESTMODE From 36fb6b37fe784add8df4edab21e33771e629b187 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:36:21 +0100 Subject: [PATCH 30/36] doccheck --- sys/include/net/netopt.h | 13 ++++++++++++- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 8 ++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 9ecf76ad21e1..ffe4122be1a1 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -926,11 +926,22 @@ enum { #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) /** - * @brief Data for @ref NETOPT_IPV6_IID when using RFC7217 + * @brief Data for @ref NETOPT_IPV6_IID when using RFC7217, + * passed on to ipv6_get_rfc7217_iid, + * from which the descriptions are also copied */ typedef struct { + /** + * @param[out] where to store the generated interface identifier + */ eui64_t *iid; + /** + * @param[in] pfx The prefix for which the IID is to be generated. + */ const ipv6_addr_t *pfx; + /** + * @param[in,out] dad_ctr ("DAD_Counter" in rfc7217) + */ uint8_t *dad_ctr; } netopt_ipv6_rfc7217_iid_data; #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index a8855fa27f3d..ece69f580c2a 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -48,7 +48,7 @@ extern "C" { */ #define SLAAC_PREFIX_LENGTH (64U) -/* +/** * "the address architecture [RFC4291] also defines the length of the interface identifiers" * - https://datatracker.ietf.org/doc/html/rfc4862#section-2 * @@ -73,6 +73,9 @@ extern "C" { #define STABLE_PRIVACY_IDGEN_RETRIES (3U) /*default value*/ #endif +/** + * @brief Upper limit for random time to wait between IDGEN retries + */ #ifndef STABLE_PRIVACY_IDGEN_DELAY_MS #define STABLE_PRIVACY_IDGEN_DELAY_MS 1000 /*default value*/ #endif @@ -90,6 +93,7 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len); #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) /** + * @brief Overload of @ref _auto_configure_addr * @param dad_ctr rfc7217 DAD_Counter */ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, @@ -121,7 +125,7 @@ bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); /** * @brief * @pre @p iid is all 0 bits (iid->uint64.u64 == 0) - * @param[out] iid + * @param[out] iid where to store the generated interface identifier * @param[in] netif The network interface to use as source for IID generation. * ("Net_iface" in rfc7217) * @param[in] pfx The prefix for which the IID is to be generated. From af35c119901749eba8b1e1c21c64d95217ca7855 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:04:24 +0100 Subject: [PATCH 31/36] chore: Use C-style comments https://github.com/RIOT-OS/RIOT/pull/20370#discussion_r1498378096 and CODING_CONVENTIONS.md --- sys/net/gnrc/netif/gnrc_netif.c | 2 +- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 52 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 08912d4f892b..bc2d5c08e261 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -985,7 +985,7 @@ static int _idx(const gnrc_netif_t *netif, const ipv6_addr_t *addr, bool mcast) static int _pfx_idx(const gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, bool mcast) { - //same as function @ref _idx above, but with generalized condition + /*same as function @ref _idx above, but with generalized condition*/ if (!ipv6_addr_is_unspecified(pfx)) { const ipv6_addr_t *iplist = (mcast) ? netif->ipv6.groups : netif->ipv6.addrs; diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index e8006c728032..cb251fc1d1e5 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -147,13 +147,13 @@ bool _iid_is_iana_reserved(const eui64_t *iid) } inline bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason) { - if (*dad_ctr < STABLE_PRIVACY_IDGEN_RETRIES) { //within retry limit + if (*dad_ctr < STABLE_PRIVACY_IDGEN_RETRIES) { /*within retry limit*/ LOG_DEBUG("nib: %s", reason); *dad_ctr += 1; LOG_DEBUG(", retrying IDGEN. (%u/%u)\n", *dad_ctr, STABLE_PRIVACY_IDGEN_RETRIES); return true; } - //retried often enough + /*retried often enough*/ LOG_WARNING("nib: %s", reason); LOG_WARNING(", not retrying: IDGEN_RETRIES limit reached\n"); return false; @@ -174,7 +174,7 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_add #error "Stable privacy requires a secret_key, this should have been configured by sys/net/gnrc/Makefile.dep" #endif const uint8_t secret_key[16] = { STABLE_PRIVACY_SECRET_KEY }; - //SHOULD be of at least 128 bits - https://datatracker.ietf.org/doc/html/rfc7217 + /*SHOULD be of at least 128 bits - https://datatracker.ietf.org/doc/html/rfc7217*/ uint8_t digest[SHA256_DIGEST_LENGTH]; @@ -189,18 +189,18 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_add } iid->uint64.u64 = 0; - //uninitialized if called via gnrc_netapi_get (NETOPT_IPV6_IID_RFC7217) - //needs to be all zeros as precondition for the following copy operation - - assert(sizeof(digest) >= sizeof(*iid)); //as bits: 256 >= 64 //digest is large enough - - //copy digest into IID - //RFC 7217 says "starting from the least significant bit", - //i.e. in reverse order - for (uint8_t i = 0; i < sizeof(*iid); i++) { //for each of the 8 bytes - for (int j = 0; j < 8; j++) { //for each of the 8 bits _within byte_ - if ((digest[(sizeof(digest)-1)-i])&(1<uint8[i] |= 1 << ((8-1)-j); //set 1 //precondition: iid->uint8[i] = 0 + /* uninitialized if called via gnrc_netapi_get (NETOPT_IPV6_IID_RFC7217) + * needs to be all zeros as precondition for the following copy operation*/ + + assert(sizeof(digest) >= sizeof(*iid)); /*as bits: 256 >= 64, "digest is large enough"*/ + + /* copy digest into IID + * RFC 7217 says "starting from the least significant bit", + * i.e. in reverse order */ + for (uint8_t i = 0; i < sizeof(*iid); i++) { /*for each of the 8 bytes*/ + for (int j = 0; j < 8; j++) { /*for each of the 8 bits _within byte_*/ + if ((digest[(sizeof(digest)-1)-i])&(1<uint8[i] |= 1 << ((8-1)-j); /*set 1, precondition: iid->uint8[i] = 0*/ } } } @@ -295,22 +295,22 @@ void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) if (_stable_privacy_should_retry_idgen(&dad_counter, "Duplicate address detected")) { - //> Hosts SHOULD introduce a random delay between 0 and IDGEN_DELAY seconds - //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 + /* > Hosts SHOULD introduce a random delay between 0 and IDGEN_DELAY seconds + * - https://datatracker.ietf.org/doc/html/rfc7217#section-6 */ uint32_t random_delay_ms = random_uint32_range(0, STABLE_PRIVACY_IDGEN_DELAY_MS); ztimer_sleep(ZTIMER_MSEC, random_delay_ms); _auto_configure_addr_with_dad_ctr(netif, addr, SLAAC_PREFIX_LENGTH, dad_counter); } else { - //"hosts MUST NOT automatically fall back to employing other algorithms - // for generating Interface Identifiers" - //- https://datatracker.ietf.org/doc/html/rfc7217#section-6 - - //> If the address is a link-local address - //> [...] - //> not formed from an interface identifier based on the hardware address - //> IP operation on the interface MAY be continued - //- https://datatracker.ietf.org/doc/html/rfc4862#section-5.4.5 + /*"hosts MUST NOT automatically fall back to employing other algorithms + for generating Interface Identifiers" + - https://datatracker.ietf.org/doc/html/rfc7217#section-6*/ + + /*> If the address is a link-local address + > [...] + > not formed from an interface identifier based on the hardware address + > IP operation on the interface MAY be continued + - https://datatracker.ietf.org/doc/html/rfc4862#section-5.4.5*/ } #else if (!ipv6_addr_is_link_local(addr) || From a69adaae4ab91471b65ed052a3e0d34bc3d829b2 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:42:35 +0100 Subject: [PATCH 32/36] refactor: Make called function inline --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 14 +++++++++----- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index cb251fc1d1e5..b26f8f6cf10d 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -15,8 +15,8 @@ #include #include -#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) #include "_nib-slaac.h" +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) #include #include "ztimer.h" #include "random.h" @@ -36,19 +36,23 @@ #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) static char addr_str[IPV6_ADDR_MAX_STR_LEN]; -#if !IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) -void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len) -#else inline void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len) { +#if !IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) + _auto_configure_addr_default(netif, pfx, pfx_len); +#else _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, 0); +#endif } +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, uint8_t dad_ctr) +#else +void _auto_configure_addr_default(gnrc_netif_t *netif, + const ipv6_addr_t *pfx, uint8_t pfx_len) #endif { ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index ece69f580c2a..979fcb7a089c 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -91,13 +91,17 @@ extern "C" { */ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len); -#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) || defined(DOXYGEN) + +#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) /** * @brief Overload of @ref _auto_configure_addr * @param dad_ctr rfc7217 DAD_Counter */ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, uint8_t dad_ctr); +#else +void _auto_configure_addr_default(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len); #endif #else /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ From dfb5e1d2de5c7cdb317b7ebc1d6b2f7d7f1a183f Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:07:45 +0100 Subject: [PATCH 33/36] refactor: Rename _auto_configure_addr -> auto_configure_addr _auto_configure_addr_default -> _auto_configure_addr --- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c | 8 ++++---- sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h | 16 +++++++++++----- sys/net/gnrc/network_layer/ipv6/nib/nib.c | 4 ++-- .../gnrc/routing/rpl/gnrc_rpl_control_messages.c | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index b26f8f6cf10d..44eac76b1e22 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -36,11 +36,11 @@ #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) || IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) static char addr_str[IPV6_ADDR_MAX_STR_LEN]; -inline void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len) +inline void auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len) { #if !IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - _auto_configure_addr_default(netif, pfx, pfx_len); + _auto_configure_addr(netif, pfx, pfx_len); #else _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, 0); #endif @@ -51,7 +51,7 @@ void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, uint8_t dad_ctr) #else -void _auto_configure_addr_default(gnrc_netif_t *netif, +void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len) #endif { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 979fcb7a089c..6cc340865925 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -89,8 +89,8 @@ extern "C" { * @param[in] pfx The prefix for the address. * @param[in] pfx_len Length of @p pfx in bits. */ -void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len); +void auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len); #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) /** @@ -100,12 +100,18 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, void _auto_configure_addr_with_dad_ctr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t pfx_len, uint8_t dad_ctr); #else -void _auto_configure_addr_default(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len); +/** + * @brief Auto-configures an address from a given prefix. + * Internal method without a DAD_Counter. + * Use auto_configure_addr() instead + * to automatically use the appropriate function. + */ +void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len); #endif #else /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ -#define _auto_configure_addr(netif, pfx, pfx_len) \ +#define auto_configure_addr(netif, pfx, pfx_len) \ (void)netif; (void)pfx; (void)pfx_len; #endif /* CONFIG_GNRC_IPV6_NIB_6LN || CONFIG_GNRC_IPV6_NIB_SLAAC */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 3b9a3c6d05e3..45d7c900b9ee 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -171,7 +171,7 @@ void gnrc_ipv6_nib_iface_up(gnrc_netif_t *netif) DEBUG("nib: Can't join link-local all-nodes on interface %u\n", netif->pid); } _add_static_lladdr(netif); - _auto_configure_addr(netif, &ipv6_addr_link_local_prefix, 64U); + auto_configure_addr(netif, &ipv6_addr_link_local_prefix, 64U); if (_should_search_rtr(netif)) { uint32_t next_rs_time = random_uint32_range(0, NDP_MAX_RS_MS_DELAY); @@ -1668,7 +1668,7 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6, * */ #endif ) { - _auto_configure_addr(netif, &pio->prefix, pio->prefix_len); + auto_configure_addr(netif, &pio->prefix, pio->prefix_len); } if ((pio->flags & (NDP_OPT_PI_FLAGS_A | NDP_OPT_PI_FLAGS_L)) || _multihop_p6c(netif, abr)) { diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c index de3ee7437a8c..4af3129b5fad 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c @@ -586,7 +586,7 @@ static bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt && !(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) { break; } - _auto_configure_addr(netif, &pi->prefix, pi->prefix_len); + auto_configure_addr(netif, &pi->prefix, pi->prefix_len); /* set lifetimes */ gnrc_ipv6_nib_pl_set(netif->pid, &pi->prefix, pi->prefix_len, From 35e23262035fbe1132760b4bff028c9053d333c5 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Sat, 24 Feb 2024 11:54:56 +0100 Subject: [PATCH 34/36] fix: Don't generate already assigned addresses Not only for the caller `_auto_configure_addr`. Other caller is NETOPT_IPV6_IID. Move check to callee. Probably low severity because address conflicts are unlikely anyway. --- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 23 +++++++------------ .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 3 ++- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 44eac76b1e22..673078ca709e 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -106,18 +106,6 @@ void _auto_configure_addr(gnrc_netif_t *netif, new_address = true; #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - else if (is_rfc7217) { - /*"the same network prefix" - https://datatracker.ietf.org/doc/html/rfc7217#section-5*/ - /*"unacceptable identifier" -> retry IDGEN (dad_ctr+1)*/ - if (!_stable_privacy_should_retry_idgen(&dad_ctr, "Generated address already exists")) { - return; - } - - _auto_configure_addr_with_dad_ctr(netif, pfx, pfx_len, dad_ctr); - return; - } -#endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) /* mark link-local addresses as valid on 6LN */ @@ -163,7 +151,7 @@ inline bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *rea return false; } -int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, +int ipv6_get_rfc7217_iid(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t *dad_ctr) { #if GNRC_NETIF_L2ADDR_MAXLEN > 0 @@ -211,10 +199,15 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_add /* "The resulting Interface Identifier SHOULD be compared against * the reserved IPv6 Interface Identifiers" + * "and against those Interface Identifiers already employed [...]" * - https://datatracker.ietf.org/doc/html/rfc7217#section-5 */ - if (_iid_is_iana_reserved(iid)) { + ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; + ipv6_addr_init_prefix(&addr, pfx, SLAAC_PREFIX_LENGTH); + ipv6_addr_set_aiid(&addr, iid->uint8); + if (_iid_is_iana_reserved(iid) || ((gnrc_netif_ipv6_addr_idx(netif, &addr)) >= 0)) { if (!_stable_privacy_should_retry_idgen(dad_ctr, - "IANA reserved IID generated")) { + "IANA reserved IID generated" + " or generated address already exists")) { return -1; } iid->uint64.u64 = 0; /* @pre for method call */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 6cc340865925..0558c4e43598 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -140,13 +140,14 @@ bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); * ("Net_iface" in rfc7217) * @param[in] pfx The prefix for which the IID is to be generated. * ("Prefix" in rfc7217) + * It is assumed to be of length @ref SLAAC_PREFIX_LENGTH * @param[in,out] dad_ctr ("DAD_Counter" in rfc7217) * Value may increase and is to be stored associated with the address by caller * @return 0 on success * @return -1 if failed, because retry limit reached * @return `-ENOTSUP`, if interface has no link-layer address. */ -int ipv6_get_rfc7217_iid(eui64_t *iid, const gnrc_netif_t *netif, const ipv6_addr_t *pfx, +int ipv6_get_rfc7217_iid(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t *dad_ctr); #endif From 6cbd58dfd2a8a0dc80d6d72074e2a40516749c86 Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Tue, 27 Feb 2024 21:09:14 +0100 Subject: [PATCH 35/36] fixup! RFC7217 for NETOPT_IPV6_IID `-Werror=maybe-uninitialized` --- sys/net/gnrc/netif/gnrc_netif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index bc2d5c08e261..0efc06067631 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -1345,7 +1345,7 @@ int gnrc_netif_ipv6_add_prefix(gnrc_netif_t *netif, DEBUG("gnrc_netif: (re-)configure prefix %s/%d\n", ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), pfx_len); #if IS_ACTIVE(CONFIG_GNRC_IPV6_STABLE_PRIVACY) - uint8_t dad_ctr; + uint8_t dad_ctr = 0; netopt_ipv6_rfc7217_iid_data data; data.iid = &iid; data.pfx = pfx; From 3af0785da15cdba0c06b4866a38d82feba01afdd Mon Sep 17 00:00:00 2001 From: xnumad <34810600+xnumad@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:43:05 +0100 Subject: [PATCH 36/36] fix: Idempotency wrapper for callers Example for a caller assuming idempotency: uhcp (-> `gnrc_netif_ipv6_add_prefix` -> `NETOPT_IPV6_IID`) --- sys/net/gnrc/netif/gnrc_netif.c | 2 +- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 24 +++++++++++++++++++ .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 7 ++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 0efc06067631..60dd8a963405 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -280,7 +280,7 @@ int gnrc_netif_get_from_netdev(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt) assert(opt->data_len == sizeof(netopt_ipv6_rfc7217_iid_data)); netopt_ipv6_rfc7217_iid_data *data = (netopt_ipv6_rfc7217_iid_data *) opt->data; - res = ipv6_get_rfc7217_iid( + res = ipv6_get_rfc7217_iid_idempotent( data->iid, netif, data->pfx, data->dad_ctr); break; #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 673078ca709e..61777bc142e7 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -216,6 +216,30 @@ int ipv6_get_rfc7217_iid(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *p return 0; } + +inline int ipv6_get_rfc7217_iid_idempotent(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr) { + int idx; + if ((idx = gnrc_netif_ipv6_addr_pfx_idx(netif, pfx, SLAAC_PREFIX_LENGTH)) >= 0) { + /* if the prefix is already known, + * do not cause generation of a potentially different + * stable privacy address (keyword DAD_Counter). + * refer to https://datatracker.ietf.org/doc/html/rfc4862#section-5.5.3 d) + * */ + DEBUG("nib: Not calling IDGEN, prefix already known.\n"); + + //write out params + //- dad_ctr + *dad_ctr = gnrc_netif_ipv6_addr_gen_retries(netif, idx); + //- iid + ipv6_addr_t *addr = &netif->ipv6.addrs[idx]; + memcpy(iid, &addr->u64[1], sizeof(*iid)); + + return 1; + } + + return ipv6_get_rfc7217_iid(iid, netif, pfx,dad_ctr); +} #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h index 0558c4e43598..c2c392607420 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -149,6 +149,13 @@ bool _stable_privacy_should_retry_idgen(uint8_t *dad_ctr, const char *reason); */ int ipv6_get_rfc7217_iid(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *pfx, uint8_t *dad_ctr); + +/** + * @brief @ref ipv6_get_rfc7217_iid for those callers which assume idempotency. + * @return 1 if ignored for idempotency, else @ref ipv6_get_rfc7217_iid + */ +int ipv6_get_rfc7217_iid_idempotent(eui64_t *iid, gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t *dad_ctr); #endif #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) || defined(DOXYGEN)