aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-10-24 18:18:09 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-24 18:18:09 -0400
commit1805b2f04855f07afe3a71d620a68f483b0ed74f (patch)
treeb823b90f37f5404fcaef70f785c70112ca74a329 /net/ipv4/route.c
parent78d81d15b74246c7cedf84894434890b33da3907 (diff)
parentf42af6c486aa5ca6ee62800cb45c5b252020509d (diff)
Merge branch 'master' of ra.kernel.org:/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 26c77e14395f..1082460daca7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1308,7 +1308,12 @@ static void rt_del(unsigned hash, struct rtable *rt)
1308void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, 1308void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1309 __be32 saddr, struct net_device *dev) 1309 __be32 saddr, struct net_device *dev)
1310{ 1310{
1311 int s, i;
1311 struct in_device *in_dev = __in_dev_get_rcu(dev); 1312 struct in_device *in_dev = __in_dev_get_rcu(dev);
1313 struct rtable *rt;
1314 __be32 skeys[2] = { saddr, 0 };
1315 int ikeys[2] = { dev->ifindex, 0 };
1316 struct flowi4 fl4;
1312 struct inet_peer *peer; 1317 struct inet_peer *peer;
1313 struct net *net; 1318 struct net *net;
1314 1319
@@ -1331,13 +1336,34 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1331 goto reject_redirect; 1336 goto reject_redirect;
1332 } 1337 }
1333 1338
1334 peer = inet_getpeer_v4(daddr, 1); 1339 memset(&fl4, 0, sizeof(fl4));
1335 if (peer) { 1340 fl4.daddr = daddr;
1336 peer->redirect_learned.a4 = new_gw; 1341 for (s = 0; s < 2; s++) {
1342 for (i = 0; i < 2; i++) {
1343 fl4.flowi4_oif = ikeys[i];
1344 fl4.saddr = skeys[s];
1345 rt = __ip_route_output_key(net, &fl4);
1346 if (IS_ERR(rt))
1347 continue;
1337 1348
1338 inet_putpeer(peer); 1349 if (rt->dst.error || rt->dst.dev != dev ||
1350 rt->rt_gateway != old_gw) {
1351 ip_rt_put(rt);
1352 continue;
1353 }
1339 1354
1340 atomic_inc(&__rt_peer_genid); 1355 if (!rt->peer)
1356 rt_bind_peer(rt, rt->rt_dst, 1);
1357
1358 peer = rt->peer;
1359 if (peer) {
1360 peer->redirect_learned.a4 = new_gw;
1361 atomic_inc(&__rt_peer_genid);
1362 }
1363
1364 ip_rt_put(rt);
1365 return;
1366 }
1341 } 1367 }
1342 return; 1368 return;
1343 1369