diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 96228a9dc..01bb9c1d4 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -3548,6 +3548,31 @@ nm_utils_stable_id_parse (const char *stable_id, /*****************************************************************************/ +static gboolean +_is_reserved_ipv6_iid (const guint8 *iid) +{ + /* https://tools.ietf.org/html/rfc5453 */ + /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */ + + /* 0000:0000:0000:0000 (Subnet-Router Anycast [RFC4291]) */ + if (memcmp (iid, &nm_ip_addr_zero.addr6.s6_addr[8], 8) == 0) + return TRUE; + + /* 0200:5EFF:FE00:0000 - 0200:5EFF:FE00:5212 (Reserved IPv6 Interface Identifiers corresponding to the IANA Ethernet Block [RFC4291]) + * 0200:5EFF:FE00:5213 (Proxy Mobile IPv6 [RFC6543]) + * 0200:5EFF:FE00:5214 - 0200:5EFF:FEFF:FFFF (Reserved IPv6 Interface Identifiers corresponding to the IANA Ethernet Block [RFC4291]) */ + if (memcmp (iid, (const guint8[]) { 0x02, 0x00, 0x5E, 0xFF, 0xFE }, 5) == 0) + return TRUE; + + /* FDFF:FFFF:FFFF:FF80 - FDFF:FFFF:FFFF:FFFF (Reserved Subnet Anycast Addresses [RFC2526]) */ + if (memcmp (iid, (const guint8[]) { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, 7) == 0) { + if (iid[7] & 0x80) + return TRUE; + } + + return FALSE; +} + static gboolean _set_stable_privacy (NMUtilsStableType stable_type, struct in6_addr *addr, @@ -3604,9 +3629,19 @@ _set_stable_privacy (NMUtilsStableType stable_type, g_checksum_update (sum, (const guchar *) secret_key, key_len); g_checksum_get_digest (sum, digest, &len); - g_checksum_free (sum); - g_return_val_if_fail (len == 32, FALSE); + nm_assert (len == sizeof (digest)); + + while (_is_reserved_ipv6_iid (digest)) { + g_checksum_reset (sum); + tmp[0] = htonl (++dad_counter); + g_checksum_update (sum, digest, len); + g_checksum_update (sum, (const guchar *) &tmp[0], sizeof (tmp[0])); + g_checksum_get_digest (sum, digest, &len); + nm_assert (len == sizeof (digest)); + } + + g_checksum_free (sum); memcpy (addr->s6_addr + 8, &digest[0], 8);