ipv4/route.c: respect prefsrc for local routes [Linux 2.6.37]

This Linux kernel change "ipv4/route.c: respect prefsrc for local routes" is included in the Linux 2.6.37 release. This change is authored by Joel Sing <jsing [at] google.com> on Mon Jan 3 20:24:20 2011 +0000. The commit for this change in Linux stable tree is 9fc3bbb (patch).

ipv4/route.c: respect prefsrc for local routes

The preferred source address is currently ignored for local routes,
which results in all local connections having a src address that is the
same as the local dst address. Fix this by respecting the preferred source
address when it is provided for local routes.

This bug can be demonstrated as follows:

 # ifconfig dummy0 192.168.0.1
 # ip route show table local | grep local.*dummy0
 local 192.168.0.1 dev dummy0  proto kernel  scope host  src 192.168.0.1
 # ip route change table local local 192.168.0.1 dev dummy0 
     proto kernel scope host src 127.0.0.1
 # ip route show table local | grep local.*dummy0
 local 192.168.0.1 dev dummy0  proto kernel  scope host  src 127.0.0.1

We now establish a local connection and verify the source IP
address selection:

 # nc -l 192.168.0.1 3128 &
 # nc 192.168.0.1 3128 &
 # netstat -ant | grep 192.168.0.1:3128.*EST
 tcp        0      0 192.168.0.1:3128        192.168.0.1:33228 ESTABLISHED
 tcp        0      0 192.168.0.1:33228       192.168.0.1:3128  ESTABLISHED

Signed-off-by: Joel Sing <[email protected]>
Signed-off-by: David S. Miller <[email protected]>

There are 8 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/ipv4/route.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index df948b0..93bfd95 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2649,8 +2649,12 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
    }

    if (res.type == RTN_LOCAL) {
-       if (!fl.fl4_src)
-           fl.fl4_src = fl.fl4_dst;
+       if (!fl.fl4_src) {
+           if (res.fi->fib_prefsrc)
+               fl.fl4_src = res.fi->fib_prefsrc;
+           else
+               fl.fl4_src = fl.fl4_dst;
+       }
        dev_out = net->loopback_dev;
        fl.oif = dev_out->ifindex;
        res.fi = NULL;

Leave a Reply

Your email address will not be published. Required fields are marked *