@@ -1279,19 +1279,18 @@ static int ip6_route_del(struct fib6_config *cfg)
12791279/*
12801280 * Handle redirects
12811281 */
1282- void rt6_redirect (struct in6_addr * dest , struct in6_addr * src ,
1283- struct in6_addr * saddr ,
1284- struct neighbour * neigh , u8 * lladdr , int on_link )
1282+ struct ip6rd_flowi {
1283+ struct flowi fl ;
1284+ struct in6_addr gateway ;
1285+ };
1286+
1287+ static struct rt6_info * __ip6_route_redirect (struct fib6_table * table ,
1288+ struct flowi * fl ,
1289+ int flags )
12851290{
1286- struct rt6_info * rt , * nrt = NULL ;
1291+ struct ip6rd_flowi * rdfl = (struct ip6rd_flowi * )fl ;
1292+ struct rt6_info * rt ;
12871293 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 ;
12951294
12961295 /*
12971296 * Get the "current" route for this destination and
@@ -1305,7 +1304,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
13051304 */
13061305
13071306 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 );
13091308restart :
13101309 for (rt = fn -> leaf ; rt ; rt = rt -> u .next ) {
13111310 /*
@@ -1320,29 +1319,67 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
13201319 continue ;
13211320 if (!(rt -> rt6i_flags & RTF_GATEWAY ))
13221321 continue ;
1323- if (neigh -> dev != rt -> rt6i_dev )
1322+ if (fl -> oif != rt -> rt6i_dev -> ifindex )
13241323 continue ;
1325- if (!ipv6_addr_equal (saddr , & rt -> rt6i_gateway ))
1324+ if (!ipv6_addr_equal (& rdfl -> gateway , & rt -> rt6i_gateway ))
13261325 continue ;
13271326 break ;
13281327 }
1329- if (rt )
1330- dst_hold (& rt -> u .dst );
1331- else if (rt6_need_strict (dest )) {
1332- while ((fn = fn -> parent ) != NULL ) {
1333- if (fn -> fn_flags & RTN_ROOT )
1334- break ;
1335- if (fn -> fn_flags & RTN_RTINFO )
1336- goto restart ;
1328+
1329+ if (!rt ) {
1330+ if (rt6_need_strict (& fl -> fl6_dst )) {
1331+ while ((fn = fn -> parent ) != NULL ) {
1332+ if (fn -> fn_flags & RTN_ROOT )
1333+ break ;
1334+ if (fn -> fn_flags & RTN_RTINFO )
1335+ goto restart ;
1336+ }
13371337 }
1338+ rt = & ip6_null_entry ;
13381339 }
1340+ dst_hold (& rt -> u .dst );
1341+
13391342 read_unlock_bh (& table -> tb6_lock );
13401343
1341- if (!rt ) {
1344+ return rt ;
1345+ };
1346+
1347+ static 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+
1369+ void 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 ) {
13421379 if (net_ratelimit ())
13431380 printk (KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
13441381 "for redirect target\n" );
1345- return ;
1382+ goto out ;
13461383 }
13471384
13481385 /*
0 commit comments