Hi folks,
Linux 2.2.17 (only tested version, I assume all other 2.2 series suffer from
the same problem and possibly 2.4 as well - but I havent even looked at that).
Assuming a configuration with linuxbox1 eth0 has adresses 192.168.129.1 and
192.168.130.1, and IP forward being enabled, and another box on the same
ethernet with IP 192.168.129.10 and a route to 192.168.130.1 via 192.168.129.1
(eg that machine doesnt handle multiple logical nets on the same ether very
well). Now this machine pings eg 192.168.130.10.
The linux box will issue a redirect redirecting to 192.168.130.10, assuming
that 192.168.129.10 can talk directly to 192.168.130.10. Under RFC 1812
Rule 5.2.7.2 I think this is illegal (different IP networks...).
There actually is the "shared_media" sysctl, which is not properly documented
in Documentation/network/ip-sysctl.txt. Attached ip-sysctl.txt.patch fixes
that and also documents the behaviour of the ../all/.. and the ../default/..
sysctl directories as best to my knowledge (ie, I may be wrong)
That sysctl defaults to 1. It could be argued that it should be better turned
be 0 (so that RFC1812 compliance is the default).
But anyway, that sysctl does not work in the situation outlined above,
since the inet_addr_onlink check in net/ipv4/route.c will return true, because
FIB_RES_GW(res) will be 0 in that case (192.168.130.0 is directly connected).
Since I am not sure if patching that inet_addr_onlink routine may break other
stuff, I propose attached route.c.patch, which checks for this condition and
puts in the destination address (which is the next hop in this case) on that
check.
Comments ?
Greetings,
Mario
*** route.c.orig Fri Oct 6 13:41:50 2000
--- route.c Fri Oct 6 15:12:25 2000
***************
*** 1215,1221 ****
if (out_dev == in_dev && err && !(flags&(RTCF_NAT|RTCF_MASQ)) &&
(IN_DEV_SHARED_MEDIA(out_dev)
! || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
flags |= RTCF_DOREDIRECT;
if (skb->protocol != __constant_htons(ETH_P_IP)) {
--- 1215,1222 ----
if (out_dev == in_dev && err && !(flags&(RTCF_NAT|RTCF_MASQ)) &&
(IN_DEV_SHARED_MEDIA(out_dev)
! || inet_addr_onlink(out_dev, saddr,
! FIB_RES_GW(res) ? FIB_RES_GW(res) : daddr)))
flags |= RTCF_DOREDIRECT;
if (skb->protocol != __constant_htons(ETH_P_IP)) {
*** ip-sysctl.txt.orig Fri Oct 6 15:14:40 2000
--- ip-sysctl.txt Fri Oct 6 15:22:41 2000
***************
*** 136,142 ****
conf/interface/*:
conf/all/* is special and changes the settings for all interfaces.
! Change special settings per interface.
log_martians - BOOLEAN
Log packets with impossible addresses to kernel log.
--- 136,149 ----
conf/interface/*:
conf/all/* is special and changes the settings for all interfaces.
! Change special settings per interface. Settings are logically
! ORed with the device specific settings in conf/<device>/*,
! so if you want to disable a feature on a specific device, you
! may have to disable it in conf/all/* and reenable it on all
! devices where you want that feature to be enabled.
!
! conf/default/* is special. The settings here are used as the default settings
! for all newly created interfaces.
log_martians - BOOLEAN
Log packets with impossible addresses to kernel log.
***************
*** 165,172 ****
enabled both in specific device section and in "all" section.
shared_media - BOOLEAN
! undocumented.
!
secure_redirects - BOOLEAN
Accept ICMP redirect messages only for gateways,
listed in default gateway list.
--- 172,181 ----
enabled both in specific device section and in "all" section.
shared_media - BOOLEAN
! If it is set the kernel does assume that different subnets
! on this device can communicate directly.
! default TRUE
!
secure_redirects - BOOLEAN
Accept ICMP redirect messages only for gateways,
listed in default gateway list.