netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Restrict local IP announcements in ARP requests
@ 2004-02-08  9:59 Julian Anastasov
  2004-02-09 22:08 ` David S. Miller
  0 siblings, 1 reply; 17+ messages in thread
From: Julian Anastasov @ 2004-02-08  9:59 UTC (permalink / raw)
  To: netdev; +Cc: linux-net


	Hello,

	I'm opening again the discussion about src IP selection
in ARP requests. We know that there are tools and framework for
ARP filtering and mangling. The question is whether we need a
simple interface flag to restrict the local src IP address for cases
where the target hosts require sender to be from same known logical
subnet due to [wrong] policy or topology reasons.

	I'm proposing simple flag that controls the src selection
in our ARP requests. I named it arp_announce - mode used to define
different restriction levels for announcing the local source address
from IP packets in ARP requests:

0 - the current behavior: use any local address if possible

	as it appears it is not the most safe mode in some cases

1 - restrict saddr to the target's subnet

	this behavior is useful in setups where the target hosts
	have [sometimes default] policy to drop incoming requests by
	checking the src IP. The result is that we can announce
	only addresses from same logical subnet as the target.

2 - always use the best source address for this target

	This is the most restrictive mode that expects answer
	from the target host. In this case we can announce only
	preferred/primary IP address. Useful for setups where we
	do not want to announce secondary IPs, for example, if
	they are shared from many hosts.

Draft version can be found here:

http://www.ssi.bg/~ja/#arp_announce

and it is also appended here. Comments?

Regards

--
Julian Anastasov <ja@ssi.bg>

diff -ur v2.6.2/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.6.2/linux/Documentation/networking/ip-sysctl.txt	2004-02-05 00:23:10.000000000 +0200
+++ linux/Documentation/networking/ip-sysctl.txt	2004-02-08 11:35:04.617310560 +0200
@@ -486,6 +486,21 @@
 	conf/{all,interface}/arp_filter is set to TRUE,
 	it will be disabled otherwise
 
+arp_announce - INTEGER
+	Define different restriction levels for announcing the local
+	source IP address from IP packets in ARP requests sent on
+	interface:
+	0 - (default) Use any local address, configured on any interface
+	1 - Try to avoid local addresses that are not in the target's
+	subnet for this interface
+	2 - Always use the best source address for this target
+
+	The max value from conf/{all,interface}/arp_announce is used.
+
+	Increasing the restriction level gives more chance for
+	receiving answer from the resolved target while decreasing
+	the level announces more valid sender's information.
+
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
diff -ur v2.6.2/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.6.2/linux/include/linux/inetdevice.h	2003-08-23 19:42:33.000000000 +0300
+++ linux/include/linux/inetdevice.h	2004-02-07 17:57:38.000000000 +0200
@@ -18,6 +18,7 @@
 	int	mc_forwarding;
 	int	tag;
 	int     arp_filter;
+	int	arp_announce;
 	int	medium_id;
 	int	no_xfrm;
 	int	no_policy;
@@ -70,6 +71,7 @@
 	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
 
 #define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
+#define IN_DEV_ARP_ANNOUNCE(in_dev)	(max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
 
 struct in_ifaddr
 {
diff -ur v2.6.2/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.6.2/linux/include/linux/sysctl.h	2004-02-05 00:23:17.000000000 +0200
+++ linux/include/linux/sysctl.h	2004-02-07 18:01:58.000000000 +0200
@@ -360,6 +360,7 @@
 	NET_IPV4_CONF_MEDIUM_ID=14,
 	NET_IPV4_CONF_NOXFRM=15,
 	NET_IPV4_CONF_NOPOLICY=16,
+	NET_IPV4_CONF_ARP_ANNOUNCE=17,
 };
 
 /* /proc/sys/net/ipv4/netfilter */
diff -ur v2.6.2/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.6.2/linux/net/ipv4/arp.c	2004-02-05 00:23:18.000000000 +0200
+++ linux/net/ipv4/arp.c	2004-02-08 11:37:24.551037400 +0200
@@ -321,15 +321,57 @@
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	u32 saddr;
+	u32 saddr = 0;
 	u8  *dst_ha = NULL;
 	struct net_device *dev = neigh->dev;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
+	struct rtable *rt;
+	struct in_device *in_dev = in_dev_get(dev);
 
-	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+	if (!in_dev)
+		return;
+
+	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+	default:
+	case 0:		/* By default announce any local IP */
+		if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+			saddr = skb->nh.iph->saddr;
+		break;
+	case 1:		/* Restrict announcements of saddr in same subnet */
+		if (!skb || !(rt = (struct rtable *) skb->dst) || rt->fl.iif)
+			break;
 		saddr = skb->nh.iph->saddr;
-	else
+		/* rt_src is always a local address */
+		if (saddr == rt->rt_src || inet_addr_type(saddr) == RTN_LOCAL) {
+			/* saddr should be known to target */
+			if (inet_addr_onlink(in_dev, target, saddr))
+				break;
+		}
+		saddr = 0;
+		break;
+	case 2:		/* Avoid secondary IPs, get a primary/preferred one */
+#if 0
+		{
+			struct flowi fl = {
+				.nl_u = { .ip4_u = { .daddr = target } },
+				.oif = dev->ifindex };
+
+			in_dev_put(in_dev);
+			in_dev = NULL;
+			if (ip_route_output_key(&rt, &fl) < 0)
+				return;
+			saddr = rt->rt_src;
+			ip_rt_put(rt);
+		}
+#endif
+
+		break;
+	}
+
+	if (in_dev)
+		in_dev_put(in_dev);
+	if (!saddr)
 		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
diff -ur v2.6.2/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.6.2/linux/net/ipv4/devinet.c	2004-02-05 00:23:18.000000000 +0200
+++ linux/net/ipv4/devinet.c	2004-02-07 18:03:04.000000000 +0200
@@ -1132,7 +1132,7 @@
 
 static struct devinet_sysctl_table {
 	struct ctl_table_header *sysctl_header;
-	ctl_table		devinet_vars[17];
+	ctl_table		devinet_vars[18];
 	ctl_table		devinet_dev[2];
 	ctl_table		devinet_conf_dir[2];
 	ctl_table		devinet_proto_dir[2];
@@ -1252,6 +1252,14 @@
 			.proc_handler	= &proc_dointvec,
 		},
 		{
+			.ctl_name	= NET_IPV4_CONF_ARP_ANNOUNCE,
+			.procname	= "arp_announce",
+			.data		= &ipv4_devconf.arp_announce,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
 			.ctl_name	= NET_IPV4_CONF_NOXFRM,
 			.procname	= "disable_xfrm",
 			.data		= &ipv4_devconf.no_xfrm,

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2004-02-18 21:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-08  9:59 Restrict local IP announcements in ARP requests Julian Anastasov
2004-02-09 22:08 ` David S. Miller
2004-02-09 22:20   ` David S. Miller
2004-02-09 23:06   ` Julian Anastasov
2004-02-09 23:10     ` David S. Miller
2004-02-10  0:31       ` Julian Anastasov
2004-02-12  4:22         ` David S. Miller
2004-02-15 10:04           ` Julian Anastasov
2004-02-18  3:07             ` David S. Miller
2004-02-18  8:22               ` Julian Anastasov
2004-02-18 21:03                 ` David S. Miller
2004-02-10  1:00       ` Julian Anastasov
2004-02-12  4:16         ` David S. Miller
2004-02-12 23:50           ` Julian Anastasov
2004-02-14  7:24             ` David S. Miller
2004-02-14 12:03               ` Julian Anastasov
2004-02-14 20:37                 ` David S. Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).