diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 74 |
1 files changed, 23 insertions, 51 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7ff687020fa9..615b328de251 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
12 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
@@ -230,7 +228,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt) | |||
230 | static inline int rt6_need_strict(struct in6_addr *daddr) | 228 | static inline int rt6_need_strict(struct in6_addr *daddr) |
231 | { | 229 | { |
232 | return (ipv6_addr_type(daddr) & | 230 | return (ipv6_addr_type(daddr) & |
233 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); | 231 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK)); |
234 | } | 232 | } |
235 | 233 | ||
236 | /* | 234 | /* |
@@ -239,15 +237,20 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
239 | 237 | ||
240 | static inline struct rt6_info *rt6_device_match(struct net *net, | 238 | static inline struct rt6_info *rt6_device_match(struct net *net, |
241 | struct rt6_info *rt, | 239 | struct rt6_info *rt, |
240 | struct in6_addr *saddr, | ||
242 | int oif, | 241 | int oif, |
243 | int flags) | 242 | int flags) |
244 | { | 243 | { |
245 | struct rt6_info *local = NULL; | 244 | struct rt6_info *local = NULL; |
246 | struct rt6_info *sprt; | 245 | struct rt6_info *sprt; |
247 | 246 | ||
248 | if (oif) { | 247 | if (!oif && ipv6_addr_any(saddr)) |
249 | for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { | 248 | goto out; |
250 | 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) { | ||
251 | if (dev->ifindex == oif) | 254 | if (dev->ifindex == oif) |
252 | return sprt; | 255 | return sprt; |
253 | if (dev->flags & IFF_LOOPBACK) { | 256 | if (dev->flags & IFF_LOOPBACK) { |
@@ -261,14 +264,21 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
261 | } | 264 | } |
262 | local = sprt; | 265 | local = sprt; |
263 | } | 266 | } |
267 | } else { | ||
268 | if (ipv6_chk_addr(net, saddr, dev, | ||
269 | flags & RT6_LOOKUP_F_IFACE)) | ||
270 | return sprt; | ||
264 | } | 271 | } |
272 | } | ||
265 | 273 | ||
274 | if (oif) { | ||
266 | if (local) | 275 | if (local) |
267 | return local; | 276 | return local; |
268 | 277 | ||
269 | if (flags & RT6_LOOKUP_F_IFACE) | 278 | if (flags & RT6_LOOKUP_F_IFACE) |
270 | return net->ipv6.ip6_null_entry; | 279 | return net->ipv6.ip6_null_entry; |
271 | } | 280 | } |
281 | out: | ||
272 | return rt; | 282 | return rt; |
273 | } | 283 | } |
274 | 284 | ||
@@ -541,7 +551,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net, | |||
541 | 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); |
542 | restart: | 552 | restart: |
543 | rt = fn->leaf; | 553 | rt = fn->leaf; |
544 | rt = rt6_device_match(net, rt, fl->oif, flags); | 554 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); |
545 | BACKTRACK(net, &fl->fl6_src); | 555 | BACKTRACK(net, &fl->fl6_src); |
546 | out: | 556 | out: |
547 | dst_use(&rt->u.dst, jiffies); | 557 | dst_use(&rt->u.dst, jiffies); |
@@ -666,7 +676,7 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, | |||
666 | int strict = 0; | 676 | int strict = 0; |
667 | int attempts = 3; | 677 | int attempts = 3; |
668 | int err; | 678 | int err; |
669 | int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; | 679 | int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; |
670 | 680 | ||
671 | strict |= flags & RT6_LOOKUP_F_IFACE; | 681 | strict |= flags & RT6_LOOKUP_F_IFACE; |
672 | 682 | ||
@@ -1048,7 +1058,7 @@ int ip6_dst_hoplimit(struct dst_entry *dst) | |||
1048 | hoplimit = idev->cnf.hop_limit; | 1058 | hoplimit = idev->cnf.hop_limit; |
1049 | in6_dev_put(idev); | 1059 | in6_dev_put(idev); |
1050 | } else | 1060 | } else |
1051 | hoplimit = ipv6_devconf.hop_limit; | 1061 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; |
1052 | } | 1062 | } |
1053 | return hoplimit; | 1063 | return hoplimit; |
1054 | } | 1064 | } |
@@ -2406,26 +2416,7 @@ static int ipv6_route_show(struct seq_file *m, void *v) | |||
2406 | 2416 | ||
2407 | static int ipv6_route_open(struct inode *inode, struct file *file) | 2417 | static int ipv6_route_open(struct inode *inode, struct file *file) |
2408 | { | 2418 | { |
2409 | int err; | 2419 | return single_open_net(inode, file, ipv6_route_show); |
2410 | struct net *net = get_proc_net(inode); | ||
2411 | if (!net) | ||
2412 | return -ENXIO; | ||
2413 | |||
2414 | err = single_open(file, ipv6_route_show, net); | ||
2415 | if (err < 0) { | ||
2416 | put_net(net); | ||
2417 | return err; | ||
2418 | } | ||
2419 | |||
2420 | return 0; | ||
2421 | } | ||
2422 | |||
2423 | static int ipv6_route_release(struct inode *inode, struct file *file) | ||
2424 | { | ||
2425 | struct seq_file *seq = file->private_data; | ||
2426 | struct net *net = seq->private; | ||
2427 | put_net(net); | ||
2428 | return single_release(inode, file); | ||
2429 | } | 2420 | } |
2430 | 2421 | ||
2431 | static const struct file_operations ipv6_route_proc_fops = { | 2422 | static const struct file_operations ipv6_route_proc_fops = { |
@@ -2433,7 +2424,7 @@ static const struct file_operations ipv6_route_proc_fops = { | |||
2433 | .open = ipv6_route_open, | 2424 | .open = ipv6_route_open, |
2434 | .read = seq_read, | 2425 | .read = seq_read, |
2435 | .llseek = seq_lseek, | 2426 | .llseek = seq_lseek, |
2436 | .release = ipv6_route_release, | 2427 | .release = single_release_net, |
2437 | }; | 2428 | }; |
2438 | 2429 | ||
2439 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 2430 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |
@@ -2453,26 +2444,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v) | |||
2453 | 2444 | ||
2454 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) | 2445 | static int rt6_stats_seq_open(struct inode *inode, struct file *file) |
2455 | { | 2446 | { |
2456 | int err; | 2447 | return single_open_net(inode, file, rt6_stats_seq_show); |
2457 | struct net *net = get_proc_net(inode); | ||
2458 | if (!net) | ||
2459 | return -ENXIO; | ||
2460 | |||
2461 | err = single_open(file, rt6_stats_seq_show, net); | ||
2462 | if (err < 0) { | ||
2463 | put_net(net); | ||
2464 | return err; | ||
2465 | } | ||
2466 | |||
2467 | return 0; | ||
2468 | } | ||
2469 | |||
2470 | static int rt6_stats_seq_release(struct inode *inode, struct file *file) | ||
2471 | { | ||
2472 | struct seq_file *seq = file->private_data; | ||
2473 | struct net *net = (struct net *)seq->private; | ||
2474 | put_net(net); | ||
2475 | return single_release(inode, file); | ||
2476 | } | 2448 | } |
2477 | 2449 | ||
2478 | static const struct file_operations rt6_stats_seq_fops = { | 2450 | static const struct file_operations rt6_stats_seq_fops = { |
@@ -2480,7 +2452,7 @@ static const struct file_operations rt6_stats_seq_fops = { | |||
2480 | .open = rt6_stats_seq_open, | 2452 | .open = rt6_stats_seq_open, |
2481 | .read = seq_read, | 2453 | .read = seq_read, |
2482 | .llseek = seq_lseek, | 2454 | .llseek = seq_lseek, |
2483 | .release = rt6_stats_seq_release, | 2455 | .release = single_release_net, |
2484 | }; | 2456 | }; |
2485 | #endif /* CONFIG_PROC_FS */ | 2457 | #endif /* CONFIG_PROC_FS */ |
2486 | 2458 | ||