aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a9b08a2422e0..8d00a9d77f01 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1279,19 +1279,18 @@ static int ip6_route_del(struct fib6_config *cfg)
1279/* 1279/*
1280 * Handle redirects 1280 * Handle redirects
1281 */ 1281 */
1282void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, 1282struct ip6rd_flowi {
1283 struct in6_addr *saddr, 1283 struct flowi fl;
1284 struct neighbour *neigh, u8 *lladdr, int on_link) 1284 struct in6_addr gateway;
1285};
1286
1287static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
1288 struct flowi *fl,
1289 int flags)
1285{ 1290{
1286 struct rt6_info *rt, *nrt = NULL; 1291 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl;
1292 struct rt6_info *rt;
1287 struct fib6_node *fn; 1293 struct fib6_node *fn;
1288 struct fib6_table *table;
1289 struct netevent_redirect netevent;
1290
1291 /* TODO: Very lazy, might need to check all tables */
1292 table = fib6_get_table(RT6_TABLE_MAIN);
1293 if (table == NULL)
1294 return;
1295 1294
1296 /* 1295 /*
1297 * Get the "current" route for this destination and 1296 * Get the "current" route for this destination and
@@ -1305,7 +1304,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1305 */ 1304 */
1306 1305
1307 read_lock_bh(&table->tb6_lock); 1306 read_lock_bh(&table->tb6_lock);
1308 fn = fib6_lookup(&table->tb6_root, dest, src); 1307 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
1309restart: 1308restart:
1310 for (rt = fn->leaf; rt; rt = rt->u.next) { 1309 for (rt = fn->leaf; rt; rt = rt->u.next) {
1311 /* 1310 /*
@@ -1320,29 +1319,67 @@ restart:
1320 continue; 1319 continue;
1321 if (!(rt->rt6i_flags & RTF_GATEWAY)) 1320 if (!(rt->rt6i_flags & RTF_GATEWAY))
1322 continue; 1321 continue;
1323 if (neigh->dev != rt->rt6i_dev) 1322 if (fl->oif != rt->rt6i_dev->ifindex)
1324 continue; 1323 continue;
1325 if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) 1324 if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
1326 continue; 1325 continue;
1327 break; 1326 break;
1328 } 1327 }
1329 if (rt) 1328
1330 dst_hold(&rt->u.dst); 1329 if (!rt) {
1331 else if (rt6_need_strict(dest)) { 1330 if (rt6_need_strict(&fl->fl6_dst)) {
1332 while ((fn = fn->parent) != NULL) { 1331 while ((fn = fn->parent) != NULL) {
1333 if (fn->fn_flags & RTN_ROOT) 1332 if (fn->fn_flags & RTN_ROOT)
1334 break; 1333 break;
1335 if (fn->fn_flags & RTN_RTINFO) 1334 if (fn->fn_flags & RTN_RTINFO)
1336 goto restart; 1335 goto restart;
1336 }
1337 } 1337 }
1338 rt = &ip6_null_entry;
1338 } 1339 }
1340 dst_hold(&rt->u.dst);
1341
1339 read_unlock_bh(&table->tb6_lock); 1342 read_unlock_bh(&table->tb6_lock);
1340 1343
1341 if (!rt) { 1344 return rt;
1345};
1346
1347static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1348 struct in6_addr *src,
1349 struct in6_addr *gateway,
1350 struct net_device *dev)
1351{
1352 struct ip6rd_flowi rdfl = {
1353 .fl = {
1354 .oif = dev->ifindex,
1355 .nl_u = {
1356 .ip6_u = {
1357 .daddr = *dest,
1358 .saddr = *src,
1359 },
1360 },
1361 },
1362 .gateway = *gateway,
1363 };
1364 int flags = rt6_need_strict(dest) ? RT6_F_STRICT : 0;
1365
1366 return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
1367}
1368
1369void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1370 struct in6_addr *saddr,
1371 struct neighbour *neigh, u8 *lladdr, int on_link)
1372{
1373 struct rt6_info *rt, *nrt = NULL;
1374 struct netevent_redirect netevent;
1375
1376 rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
1377
1378 if (rt == &ip6_null_entry) {
1342 if (net_ratelimit()) 1379 if (net_ratelimit())
1343 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " 1380 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
1344 "for redirect target\n"); 1381 "for redirect target\n");
1345 return; 1382 goto out;
1346 } 1383 }
1347 1384
1348 /* 1385 /*