BACKPORT: ipv6: Implement draft-ietf-6man-rfc4941bis
authorFernando Gont <fgont@si6networks.com>
Fri, 1 May 2020 03:51:47 +0000 (00:51 -0300)
committerLee Jones <lee.jones@linaro.org>
Mon, 31 Jan 2022 15:13:30 +0000 (15:13 +0000)
Implement the upcoming rev of RFC4941 (IPv6 temporary addresses):
https://tools.ietf.org/html/draft-ietf-6man-rfc4941bis-09

* Reduces the default Valid Lifetime to 2 days
  The number of extra addresses employed when Valid Lifetime was
  7 days exacerbated the stress caused on network
  elements/devices. Additionally, the motivation for temporary
  addresses is indeed privacy and reduced exposure. With a
  default Valid Lifetime of 7 days, an address that becomes
  revealed by active communication is reachable and exposed for
  one whole week. The only use case for a Valid Lifetime of 7
  days could be some application that is expecting to have long
  lived connections. But if you want to have a long lived
  connections, you shouldn't be using a temporary address in the
  first place. Additionally, in the era of mobile devices, general
  applications should nevertheless be prepared and robust to
  address changes (e.g. nodes swap wifi <-> 4G, etc.)

* Employs different IIDs for different prefixes
  To avoid network activity correlation among addresses configured
  for different prefixes

* Uses a simpler algorithm for IID generation
  No need to store "history" anywhere

Bug: 175340972
Signed-off-by: Fernando Gont <fgont@si6networks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 969c54646af0d7d94a5f0f37adbbfe024e85466e)
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Change-Id: Idce8f00b9b29ad329b6b90a5a4a9641c3d2b96d9

Documentation/networking/ip-sysctl.txt
include/net/if_inet6.h
net/ipv6/addrconf.c

index b648c006b7d2dd6addfde9046e7a21c0f237f0a1..fb4f2b3bc2b0710d06a46fae0544ef7a7bf6eb74 100644 (file)
@@ -1644,7 +1644,7 @@ use_tempaddr - INTEGER
 
 temp_valid_lft - INTEGER
        valid lifetime (in seconds) for temporary addresses.
-       Default: 604800 (7 days)
+       Default: 172800 (2 days)
 
 temp_prefered_lft - INTEGER
        Preferred lifetime (in seconds) for temporary addresses.
index d4088d1a688d49fd3bb5ed3791c7755fd75c6ffe..c8569e7a9f68ff21ea27b75a30788ebad066d993 100644 (file)
@@ -193,7 +193,6 @@ struct inet6_dev {
        int                     dead;
 
        u32                     desync_factor;
-       u8                      rndid[8];
        struct list_head        tempaddr_list;
 
        struct in6_addr         token;
index c16ea7055f241304c06241281d01b1be3ef43266..59ee7d78db605b975b0ceb2c855acd65400c7dce 100644 (file)
@@ -148,8 +148,7 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
 }
 #endif
 
-static void ipv6_regen_rndid(struct inet6_dev *idev);
-static void ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
+static void ipv6_gen_rnd_iid(struct in6_addr *addr);
 
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
 static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -449,8 +448,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
            dev->type == ARPHRD_SIT ||
            dev->type == ARPHRD_NONE) {
                ndev->cnf.use_tempaddr = -1;
-       } else
-               ipv6_regen_rndid(ndev);
+       }
 
        ndev->token = in6addr_any;
 
@@ -1230,28 +1228,22 @@ out:
        in6_ifa_put(ifp);
 }
 
-static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift)
+static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
-       struct in6_addr addr, *tmpaddr;
        unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_tstamp, age;
        unsigned long regen_advance;
-       int tmp_plen;
-       int ret = 0;
-       u32 addr_flags;
        unsigned long now = jiffies;
-       long max_desync_factor;
        s32 cnf_temp_preferred_lft;
+       struct inet6_ifaddr *ift;
+       long max_desync_factor;
+       struct in6_addr addr;
+       int ret = 0;
+       int tmp_plen;
+       u32 addr_flags;
 
        write_lock_bh(&idev->lock);
-       if (ift) {
-               spin_lock_bh(&ift->lock);
-               memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
-               spin_unlock_bh(&ift->lock);
-               tmpaddr = &addr;
-       } else {
-               tmpaddr = NULL;
-       }
+
 retry:
        in6_dev_hold(idev);
        if (idev->cnf.use_tempaddr <= 0) {
@@ -1274,8 +1266,8 @@ retry:
        }
        in6_ifa_hold(ifp);
        memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
-       ipv6_try_regen_rndid(idev, tmpaddr);
-       memcpy(&addr.s6_addr[8], idev->rndid, 8);
+       ipv6_gen_rnd_iid(&addr);
+
        age = (now - ifp->tstamp) / HZ;
 
        regen_advance = idev->cnf.regen_max_retry *
@@ -1339,7 +1331,6 @@ retry:
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
-               tmpaddr = &addr;
                write_lock_bh(&idev->lock);
                goto retry;
        }
@@ -1946,7 +1937,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
                if (ifpub) {
                        in6_ifa_hold(ifpub);
                        spin_unlock_bh(&ifp->lock);
-                       ipv6_create_tempaddr(ifpub, ifp);
+                       ipv6_create_tempaddr(ifpub);
                        in6_ifa_put(ifpub);
                } else {
                        spin_unlock_bh(&ifp->lock);
@@ -2241,40 +2232,38 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
        return err;
 }
 
-/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
-static void ipv6_regen_rndid(struct inet6_dev *idev)
+/* Generation of a randomized Interface Identifier
+ * draft-ietf-6man-rfc4941bis, Section 3.3.1
+ */
+
+static void ipv6_gen_rnd_iid(struct in6_addr *addr)
 {
 regen:
-       get_random_bytes(idev->rndid, sizeof(idev->rndid));
-       idev->rndid[0] &= ~0x02;
+       get_random_bytes(&addr->s6_addr[8], 8);
 
-       /*
-        * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
-        * check if generated address is not inappropriate
+       /* <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1:
+        * check if generated address is not inappropriate:
         *
-        *  - Reserved subnet anycast (RFC 2526)
-        *      11111101 11....11 1xxxxxxx
-        *  - ISATAP (RFC4214) 6.1
-        *      00-00-5E-FE-xx-xx-xx-xx
-        *  - value 0
-        *  - XXX: already assigned to an address on the device
+        * - Reserved IPv6 Interface Identifers
+        * - XXX: already assigned to an address on the device
         */
-       if (idev->rndid[0] == 0xfd &&
-           (idev->rndid[1]&idev->rndid[2]&idev->rndid[3]&idev->rndid[4]&idev->rndid[5]&idev->rndid[6]) == 0xff &&
-           (idev->rndid[7]&0x80))
+
+       /* Subnet-router anycast: 0000:0000:0000:0000 */
+       if (!(addr->s6_addr32[2] | addr->s6_addr32[3]))
                goto regen;
-       if ((idev->rndid[0]|idev->rndid[1]) == 0) {
-               if (idev->rndid[2] == 0x5e && idev->rndid[3] == 0xfe)
-                       goto regen;
-               if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
-                       goto regen;
-       }
-}
 
-static void  ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
-{
-       if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
-               ipv6_regen_rndid(idev);
+       /* 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;
+
+       /* Reserved subnet anycast addresses */
+       if (ntohl(addr->s6_addr32[2]) == 0xfdffffff &&
+           ntohl(addr->s6_addr32[3]) >= 0Xffffff80)
+               goto regen;
 }
 
 u32 addrconf_rt_table(const struct net_device *dev, u32 default_table) {
@@ -2472,7 +2461,7 @@ static void manage_tempaddrs(struct inet6_dev *idev,
                 * no temporary address currently exists.
                 */
                read_unlock_bh(&idev->lock);
-               ipv6_create_tempaddr(ifp, NULL);
+               ipv6_create_tempaddr(ifp);
        } else {
                read_unlock_bh(&idev->lock);
        }
@@ -4404,7 +4393,7 @@ restart:
                                                spin_lock(&ifpub->lock);
                                                ifpub->regen_count = 0;
                                                spin_unlock(&ifpub->lock);
-                                               ipv6_create_tempaddr(ifpub, ifp);
+                                               ipv6_create_tempaddr(ifpub);
                                                in6_ifa_put(ifpub);
                                                in6_ifa_put(ifp);
                                                goto restart;