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: Jaehee Park <jhpark1013@gmail.com> Suggested-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
459f326e99
commit
e68c5dcf0a
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue