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.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 751e98f9b8b4..5d6c166dfbb6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -228,7 +228,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt)
228static inline int rt6_need_strict(struct in6_addr *daddr) 228static inline int rt6_need_strict(struct in6_addr *daddr)
229{ 229{
230 return (ipv6_addr_type(daddr) & 230 return (ipv6_addr_type(daddr) &
231 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); 231 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK));
232} 232}
233 233
234/* 234/*
@@ -237,15 +237,20 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
237 237
238static inline struct rt6_info *rt6_device_match(struct net *net, 238static inline struct rt6_info *rt6_device_match(struct net *net,
239 struct rt6_info *rt, 239 struct rt6_info *rt,
240 struct in6_addr *saddr,
240 int oif, 241 int oif,
241 int flags) 242 int flags)
242{ 243{
243 struct rt6_info *local = NULL; 244 struct rt6_info *local = NULL;
244 struct rt6_info *sprt; 245 struct rt6_info *sprt;
245 246
246 if (oif) { 247 if (!oif && ipv6_addr_any(saddr))
247 for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { 248 goto out;
248 struct net_device *dev = sprt->rt6i_dev; 249
250 for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
251 struct net_device *dev = sprt->rt6i_dev;
252
253 if (oif) {
249 if (dev->ifindex == oif) 254 if (dev->ifindex == oif)
250 return sprt; 255 return sprt;
251 if (dev->flags & IFF_LOOPBACK) { 256 if (dev->flags & IFF_LOOPBACK) {
@@ -259,14 +264,21 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
259 } 264 }
260 local = sprt; 265 local = sprt;
261 } 266 }
267 } else {
268 if (ipv6_chk_addr(net, saddr, dev,
269 flags & RT6_LOOKUP_F_IFACE))
270 return sprt;
262 } 271 }
272 }
263 273
274 if (oif) {
264 if (local) 275 if (local)
265 return local; 276 return local;
266 277
267 if (flags & RT6_LOOKUP_F_IFACE) 278 if (flags & RT6_LOOKUP_F_IFACE)
268 return net->ipv6.ip6_null_entry; 279 return net->ipv6.ip6_null_entry;
269 } 280 }
281out:
270 return rt; 282 return rt;
271} 283}
272 284
@@ -539,7 +551,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
539 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); 551 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
540restart: 552restart:
541 rt = fn->leaf; 553 rt = fn->leaf;
542 rt = rt6_device_match(net, rt, fl->oif, flags); 554 rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
543 BACKTRACK(net, &fl->fl6_src); 555 BACKTRACK(net, &fl->fl6_src);
544out: 556out:
545 dst_use(&rt->u.dst, jiffies); 557 dst_use(&rt->u.dst, jiffies);