OSDN Git Service

net: ipv4: new arp_accept option to accept garp only if in-network
authorJaehee Park <jhpark1013@gmail.com>
Wed, 13 Jul 2022 23:40:47 +0000 (16:40 -0700)
committerJakub Kicinski <kuba@kernel.org>
Sat, 16 Jul 2022 01:55:49 +0000 (18:55 -0700)
In many deployments, we want the option to not learn a neighbor from
garp if the src ip is not in the same subnet as an address configured
on the interface that received the garp message. net.ipv4.arp_accept
sysctl is currently used to control creation of a neigh from a
received garp packet. This patch adds a new option '2' to
net.ipv4.arp_accept which extends option '1' by including the subnet
check.

Signed-off-by: Jaehee Park <jhpark1013@gmail.com>
Suggested-by: Roopa Prabhu <roopa@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/ip-sysctl.rst
include/linux/inetdevice.h
net/ipv4/arp.c

index 2b32904..b316014 100644 (file)
@@ -1633,12 +1633,15 @@ arp_notify - BOOLEAN
             or hardware address changes.
         ==  ==========================================================
 
-arp_accept - BOOLEAN
-       Define behavior for gratuitous ARP frames who's IP is not
-       already present in the ARP table:
+arp_accept - INTEGER
+       Define behavior for accepting gratuitous ARP (garp) frames from devices
+       that are not already present in the ARP table:
 
        - 0 - don't create new entries in the ARP table
        - 1 - create new entries in the ARP table
+       - 2 - create new entries only if the source IP address is in the same
+         subnet as an address configured on the interface that received the
+         garp message.
 
        Both replies and requests type gratuitous arp will trigger the
        ARP table to be updated, if this setting is on.
index ead3232..ddb27fc 100644 (file)
@@ -131,7 +131,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
        IN_DEV_ORCONF((in_dev), IGNORE_ROUTES_WITH_LINKDOWN)
 
 #define IN_DEV_ARPFILTER(in_dev)       IN_DEV_ORCONF((in_dev), ARPFILTER)
-#define IN_DEV_ARP_ACCEPT(in_dev)      IN_DEV_ORCONF((in_dev), ARP_ACCEPT)
+#define IN_DEV_ARP_ACCEPT(in_dev)      IN_DEV_MAXCONF((in_dev), ARP_ACCEPT)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)    IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)      IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
 #define IN_DEV_ARP_NOTIFY(in_dev)      IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
index af2f12f..87c7e3f 100644 (file)
@@ -429,6 +429,26 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
        return !inet_confirm_addr(net, in_dev, sip, tip, scope);
 }
 
+static int arp_accept(struct in_device *in_dev, __be32 sip)
+{
+       struct net *net = dev_net(in_dev->dev);
+       int scope = RT_SCOPE_LINK;
+
+       switch (IN_DEV_ARP_ACCEPT(in_dev)) {
+       case 0: /* Don't create new entries from garp */
+               return 0;
+       case 1: /* Create new entries from garp */
+               return 1;
+       case 2: /* Create a neighbor in the arp table only if sip
+                * is in the same subnet as an address configured
+                * on the interface that received the garp message
+                */
+               return !!inet_confirm_addr(net, in_dev, sip, 0, scope);
+       default:
+               return 0;
+       }
+}
+
 static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
 {
        struct rtable *rt;
@@ -868,12 +888,12 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
        n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
        addr_type = -1;
-       if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
+       if (n || arp_accept(in_dev, sip)) {
                is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
                                      sip, tip, sha, tha);
        }
 
-       if (IN_DEV_ARP_ACCEPT(in_dev)) {
+       if (arp_accept(in_dev, sip)) {
                /* Unsolicited ARP is not accepted by default.
                   It is possible, that this option should be enabled for some
                   devices (strip is candidate)