SRC IP selection in ARP request (Was: bugfix: ARP respond on all devices)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Aug 17, 2003 at 06:27:13PM +0200, Carlos Velasco wrote:
> If you send a packet through dev eth0 to dev lo IP address or other
                                        ^^
	Did you mean "from"?

> interface, when Linux try to map the MAC address with the IP address of
> the default gateway (or the gateway to reach the packet Source IP
> address), it uses the lo IP address (or other dev) in the ARP Request.

I think I saw this problem, but in another situation:
Suppose we are the server and have TCP connection established,
using src address 10.0.0.1 (because the client have chosen this address 
to connect to). But the route to the client leads via gateway 10.1.0.1,
reachable through dev eth0. We have address 10.1.0.2/24 assigned to
eth0. All is fine until ARP table entry for 10.1.0.1 is expired and
we start to send ARP requests. We choose 10.0.0.1 for src ip in the
requests, because that's what upper layer uses, and gateway doesn't
respond because it's Cisco or BSD.

I didn't test arpfilter (I think it wasn't there when I met this
problem), but it can be solved with the following simple patch
(implemented as a new per-interface sysctl). I just tested it, works for
me. echo 1 > /proc/sys/net/ipv4/conf/all/arp_select_clean_src

diff -ur _orig_linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- _orig_linux/include/linux/inetdevice.h	Mon Aug 11 13:24:51 2003
+++ linux/include/linux/inetdevice.h	Mon Aug 18 18:21:30 2003
@@ -18,6 +18,7 @@
 	int	mc_forwarding;
 	int	tag;
 	int     arp_filter;
+	int 	arp_select_clean_src;
 	int	medium_id;
 	void	*sysctl;
 };
@@ -68,6 +69,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_CLEAN_SRC(in_dev)	(ipv4_devconf.arp_select_clean_src || (in_dev)->cnf.arp_select_clean_src)
 
 struct in_ifaddr
 {
diff -ur _orig_linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- _orig_linux/include/linux/sysctl.h	Mon Aug 11 13:28:18 2003
+++ linux/include/linux/sysctl.h	Mon Aug 18 18:52:01 2003
@@ -349,6 +349,7 @@
 	NET_IPV4_CONF_TAG=12,
 	NET_IPV4_CONF_ARPFILTER=13,
 	NET_IPV4_CONF_MEDIUM_ID=14,
+	NET_IPV4_CONF_ARPSRC=15,
 };
 
 /* /proc/sys/net/ipv6 */
diff -ur _orig_linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- _orig_linux/net/ipv4/arp.c	Mon Aug 11 13:24:52 2003
+++ linux/net/ipv4/arp.c	Mon Aug 18 18:36:44 2003
@@ -322,8 +322,20 @@
 	struct net_device *dev = neigh->dev;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
+	int inherit_src;
+	struct in_device *in_dev;
 
-	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+	read_lock(&inetdev_lock);
+	in_dev = __in_dev_get(dev);
+	if (in_dev != NULL) {
+		inherit_src = !IN_DEV_ARP_CLEAN_SRC(in_dev);
+	} else {
+		inherit_src = 1;
+	}
+	read_unlock(&inetdev_lock);
+
+	if ( inherit_src &&
+		  skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
 		saddr = skb->nh.iph->saddr;
 	else
 		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
diff -ur _orig_linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- _orig_linux/net/ipv4/devinet.c	Fri Jun 13 18:51:39 2003
+++ linux/net/ipv4/devinet.c	Mon Aug 18 18:54:07 2003
@@ -1056,7 +1056,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[15];
+	ctl_table devinet_vars[16];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1104,6 +1104,9 @@
 	 &proc_dointvec},
 	{NET_IPV4_CONF_ARPFILTER, "arp_filter",
 	 &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_IPV4_CONF_ARPSRC, "arp_select_clean_src",
+	 &ipv4_devconf.arp_select_clean_src, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
 	 {0}},
 

:wq
                                        With best regards, 
                                           Vladimir Savkin. 

-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux