ipv4: fix confirm_addr_indev() when enable route_localnet
authorShijie Luo <luoshijie1@huawei.com>
Tue, 18 Jun 2019 15:14:04 +0000 (15:14 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 Jun 2019 16:02:47 +0000 (09:02 -0700)
When arp_ignore=3, the NIC won't reply for scope host addresses, but
if enable route_locanet, we need to reply ip address with head 127 and
scope RT_SCOPE_HOST.

Fixes: d0daebc3d622 ("ipv4: Add interface option to enable routing of 127.0.0.0/8")
Signed-off-by: Shijie Luo <luoshijie1@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/devinet.c

index 6fd4628d10b9c14524910ecc2d4a39e997aeac5d..7874303220c504edcd705ed2fefbc0d9ec020397 100644 (file)
@@ -1356,14 +1356,20 @@ EXPORT_SYMBOL(inet_select_addr);
 static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
                              __be32 local, int scope)
 {
+       unsigned char localnet_scope = RT_SCOPE_HOST;
        const struct in_ifaddr *ifa;
        __be32 addr = 0;
        int same = 0;
 
+       if (unlikely(IN_DEV_ROUTE_LOCALNET(in_dev)))
+               localnet_scope = RT_SCOPE_LINK;
+
        in_dev_for_each_ifa_rcu(ifa, in_dev) {
+               unsigned char min_scope = min(ifa->ifa_scope, localnet_scope);
+
                if (!addr &&
                    (local == ifa->ifa_local || !local) &&
-                   ifa->ifa_scope <= scope) {
+                   min_scope <= scope) {
                        addr = ifa->ifa_local;
                        if (same)
                                break;
@@ -1378,7 +1384,7 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
                                if (inet_ifa_match(addr, ifa))
                                        break;
                                /* No, then can we use new local src? */
-                               if (ifa->ifa_scope <= scope) {
+                               if (min_scope <= scope) {
                                        addr = ifa->ifa_local;
                                        break;
                                }