Commit e68c5dcf authored by Jaehee Park's avatar Jaehee Park Committed by Jakub Kicinski

net: ipv4: new arp_accept option to accept garp only if in-network

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: default avatarJaehee Park <jhpark1013@gmail.com>
Suggested-by: default avatarRoopa Prabhu <roopa@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 459f326e
...@@ -1633,12 +1633,15 @@ arp_notify - BOOLEAN ...@@ -1633,12 +1633,15 @@ arp_notify - BOOLEAN
or hardware address changes. or hardware address changes.
== ========================================================== == ==========================================================
arp_accept - BOOLEAN arp_accept - INTEGER
Define behavior for gratuitous ARP frames who's IP is not Define behavior for accepting gratuitous ARP (garp) frames from devices
already present in the ARP table: that are not already present in the ARP table:
- 0 - don't create new entries in the ARP table - 0 - don't create new entries in the ARP table
- 1 - 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 Both replies and requests type gratuitous arp will trigger the
ARP table to be updated, if this setting is on. ARP table to be updated, if this setting is on.
......
...@@ -131,7 +131,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) ...@@ -131,7 +131,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
IN_DEV_ORCONF((in_dev), IGNORE_ROUTES_WITH_LINKDOWN) IN_DEV_ORCONF((in_dev), IGNORE_ROUTES_WITH_LINKDOWN)
#define IN_DEV_ARPFILTER(in_dev) IN_DEV_ORCONF((in_dev), ARPFILTER) #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_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_IGNORE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
#define IN_DEV_ARP_NOTIFY(in_dev) IN_DEV_MAXCONF((in_dev), ARP_NOTIFY) #define IN_DEV_ARP_NOTIFY(in_dev) IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
......
...@@ -429,6 +429,26 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) ...@@ -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); 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) static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
{ {
struct rtable *rt; struct rtable *rt;
...@@ -868,12 +888,12 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) ...@@ -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); n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
addr_type = -1; 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, is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
sip, tip, sha, tha); sip, tip, sha, tha);
} }
if (IN_DEV_ARP_ACCEPT(in_dev)) { if (arp_accept(in_dev, sip)) {
/* Unsolicited ARP is not accepted by default. /* Unsolicited ARP is not accepted by default.
It is possible, that this option should be enabled for some It is possible, that this option should be enabled for some
devices (strip is candidate) devices (strip is candidate)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment