@@ -135,6 +135,7 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
}
#endif
+static bool ipv6_reserved_interfaceid(struct in6_addr address);
static void ipv6_gen_rnd_iid(struct in6_addr *addr);
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
@@ -2352,32 +2353,12 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
static void ipv6_gen_rnd_iid(struct in6_addr *addr)
{
-regen:
- get_random_bytes(&addr->s6_addr[8], 8);
-
- /* <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1:
- * check if generated address is not inappropriate:
- *
- * - Reserved IPv6 Interface Identifers
- * - XXX: already assigned to an address on the device
- */
-
- /* Subnet-router anycast: 0000:0000:0000:0000 */
- if (!(addr->s6_addr32[2] | addr->s6_addr32[3]))
- goto regen;
-
- /* IANA Ethernet block: 0200:5EFF:FE00:0000-0200:5EFF:FE00:5212
- * Proxy Mobile IPv6: 0200:5EFF:FE00:5213
- * IANA Ethernet block: 0200:5EFF:FE00:5214-0200:5EFF:FEFF:FFFF
- */
- if (ntohl(addr->s6_addr32[2]) == 0x02005eff &&
- (ntohl(addr->s6_addr32[3]) & 0Xff000000) == 0xfe000000)
- goto regen;
+ struct in6_addr temp;
- /* Reserved subnet anycast addresses */
- if (ntohl(addr->s6_addr32[2]) == 0xfdffffff &&
- ntohl(addr->s6_addr32[3]) >= 0Xffffff80)
- goto regen;
+ do {
+ get_random_bytes(&addr->s6_addr[8], 8);
+ temp = *addr;
+ } while (ipv6_reserved_interfaceid(temp));
}
/*
@@ -3189,15 +3170,27 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
}
EXPORT_SYMBOL_GPL(addrconf_add_linklocal);
+/* <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1:
+ * check if generated address is not inappropriate:
+ *
+ * - Reserved IPv6 Interface Identifers
+ * - XXX: already assigned to an address on the device
+ */
static bool ipv6_reserved_interfaceid(struct in6_addr address)
{
+ /* Subnet-router anycast: 0000:0000:0000:0000 */
if ((address.s6_addr32[2] | address.s6_addr32[3]) == 0)
return true;
+ /* IANA Ethernet block: 0200:5EFF:FE00:0000-0200:5EFF:FE00:5212
+ * Proxy Mobile IPv6: 0200:5EFF:FE00:5213
+ * IANA Ethernet block: 0200:5EFF:FE00:5214-0200:5EFF:FEFF:FFFF
+ */
if (address.s6_addr32[2] == htonl(0x02005eff) &&
- ((address.s6_addr32[3] & htonl(0xfe000000)) == htonl(0xfe000000)))
+ ((address.s6_addr32[3] & htonl(0xff000000)) == htonl(0xfe000000)))
return true;
+ /* Reserved subnet anycast addresses */
if (address.s6_addr32[2] == htonl(0xfdffffff) &&
((address.s6_addr32[3] & htonl(0xffffff80)) == htonl(0xffffff80)))
return true;
Using the ipv6_reserved_interfaceid for interface id checking. Signed-off-by: zhang kai <zhangkaiheb@126.com> --- net/ipv6/addrconf.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-)