Source Address Autoselection (Sort of Long)

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

 



I have a question about source address auto selection.

Background
**********
I am building a Linux router and the configuration looks something like:

eth0 - aaa.bbb.ccc.ddd Valid IP Address
Wan0 - 192.168.104.2 <--> ISP IF 192.168.104.1 <--> Internet
eth1 - 192.168.1.0

The kicker is that the Wan IP address is a Reserved Class C address block
and not routable.

If I try to ping from the router the source address will be 192.168.104.2
which will not be routable and will fail. This also kills masquerading.


>From /usr/src/linux/Documentation/networking/ip-sysctl.txt

/proc/sys/net/ipv4/conf/<ifname>/hidden - BOOLEAN
	Hide addresses attached to this device from another devices.
	Such addresses will never be selected by source address autoselection
	mechanism, ....

First is my interpretation that by setting this, the packets should never be
addressed with this interface address correct? Even if the route to the
destination is through the interface marked hidden? I tried changing this
setting and it was without effect. I then looked at the kernel source.
devinet.c seems to be the relevant file with the function inet_select_addr()
being the precise area. When I added

if (IN_DEV_HIDDEN(in_dev))
	continue;

to the top of the for_primary_ifa() loop and re-compiled the kernel I get
the desired behavior. I can now ping from the router out to the internet.

I wanted to get some feedback on this problem and my "solution" to it from
people more experienced than myself. Does my tweak make sense to include in
the kernel? I am afraid that this will perhaps break something else in a
large way. If this is not the correct solution does it make sense to add
another proc entry to cover this case? I searched deja.com and at least some
other people are hitting this kind of problem.



u32 inet_select_addr(struct device *dev, u32 dst, int scope)
{
	u32 addr = 0;
	struct in_device *in_dev = dev->ip_ptr;

	if (in_dev == NULL)
		return 0;

	for_primary_ifa(in_dev) {
		if (ifa->ifa_scope > scope)
			continue;
		if (!dst || inet_ifa_match(dst, ifa))
			return ifa->ifa_local;
		if (!addr)
			addr = ifa->ifa_local;
	} endfor_ifa(in_dev);

	if (addr)
		return addr;

	/* Not loopback addresses on loopback should be preferred
	   in this case. It is importnat that lo is the first interface
	   in dev_base list.
	 */
	for (dev=dev_base; dev; dev=dev->next) {
		if ((in_dev=dev->ip_ptr) == NULL)
			continue;

		for_primary_ifa(in_dev) {
			if (!IN_DEV_HIDDEN(in_dev) &&
			    ifa->ifa_scope <= scope &&
			    ifa->ifa_scope != RT_SCOPE_LINK)
				return ifa->ifa_local;
		} endfor_ifa(in_dev);
	}

	return 0;
}


George Sexton
MH Software, Inc.
Voice: 303 438 9585
http://www.mhsoftware.com


-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.rutgers.edu


[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