diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 309 |
1 files changed, 165 insertions, 144 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b582a0a0f1c5..4a62c47599b4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -62,17 +62,6 @@ | |||
62 | #include <linux/sysctl.h> | 62 | #include <linux/sysctl.h> |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | /* Set to 3 to get tracing. */ | ||
66 | #define RT6_DEBUG 2 | ||
67 | |||
68 | #if RT6_DEBUG >= 3 | ||
69 | #define RDBG(x) printk x | ||
70 | #define RT6_TRACE(x...) printk(KERN_DEBUG x) | ||
71 | #else | ||
72 | #define RDBG(x) | ||
73 | #define RT6_TRACE(x...) do { ; } while (0) | ||
74 | #endif | ||
75 | |||
76 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 65 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
77 | const struct in6_addr *dest); | 66 | const struct in6_addr *dest); |
78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 67 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
@@ -134,7 +123,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
134 | 123 | ||
135 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 124 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
136 | { | 125 | { |
137 | return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev); | 126 | struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); |
127 | if (n) | ||
128 | return n; | ||
129 | return neigh_create(&nd_tbl, daddr, dst->dev); | ||
130 | } | ||
131 | |||
132 | static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev) | ||
133 | { | ||
134 | struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dev, &rt->rt6i_gateway); | ||
135 | if (!n) { | ||
136 | n = neigh_create(&nd_tbl, &rt->rt6i_gateway, dev); | ||
137 | if (IS_ERR(n)) | ||
138 | return PTR_ERR(n); | ||
139 | } | ||
140 | dst_set_neighbour(&rt->dst, n); | ||
141 | |||
142 | return 0; | ||
138 | } | 143 | } |
139 | 144 | ||
140 | static struct dst_ops ip6_dst_ops_template = { | 145 | static struct dst_ops ip6_dst_ops_template = { |
@@ -247,9 +252,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | |||
247 | { | 252 | { |
248 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); | 253 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
249 | 254 | ||
250 | if (rt != NULL) | 255 | if (rt) |
251 | memset(&rt->rt6i_table, 0, | 256 | memset(&rt->rt6i_table, 0, |
252 | sizeof(*rt) - sizeof(struct dst_entry)); | 257 | sizeof(*rt) - sizeof(struct dst_entry)); |
253 | 258 | ||
254 | return rt; | 259 | return rt; |
255 | } | 260 | } |
@@ -263,7 +268,7 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
263 | if (!(rt->dst.flags & DST_HOST)) | 268 | if (!(rt->dst.flags & DST_HOST)) |
264 | dst_destroy_metrics_generic(dst); | 269 | dst_destroy_metrics_generic(dst); |
265 | 270 | ||
266 | if (idev != NULL) { | 271 | if (idev) { |
267 | rt->rt6i_idev = NULL; | 272 | rt->rt6i_idev = NULL; |
268 | in6_dev_put(idev); | 273 | in6_dev_put(idev); |
269 | } | 274 | } |
@@ -299,10 +304,10 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
299 | struct net_device *loopback_dev = | 304 | struct net_device *loopback_dev = |
300 | dev_net(dev)->loopback_dev; | 305 | dev_net(dev)->loopback_dev; |
301 | 306 | ||
302 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { | 307 | if (dev != loopback_dev && idev && idev->dev == dev) { |
303 | struct inet6_dev *loopback_idev = | 308 | struct inet6_dev *loopback_idev = |
304 | in6_dev_get(loopback_dev); | 309 | in6_dev_get(loopback_dev); |
305 | if (loopback_idev != NULL) { | 310 | if (loopback_idev) { |
306 | rt->rt6i_idev = loopback_idev; | 311 | rt->rt6i_idev = loopback_idev; |
307 | in6_dev_put(idev); | 312 | in6_dev_put(idev); |
308 | } | 313 | } |
@@ -312,7 +317,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
312 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) | 317 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) |
313 | { | 318 | { |
314 | return (rt->rt6i_flags & RTF_EXPIRES) && | 319 | return (rt->rt6i_flags & RTF_EXPIRES) && |
315 | time_after(jiffies, rt->rt6i_expires); | 320 | time_after(jiffies, rt->dst.expires); |
316 | } | 321 | } |
317 | 322 | ||
318 | static inline int rt6_need_strict(const struct in6_addr *daddr) | 323 | static inline int rt6_need_strict(const struct in6_addr *daddr) |
@@ -338,13 +343,13 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
338 | goto out; | 343 | goto out; |
339 | 344 | ||
340 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { | 345 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { |
341 | struct net_device *dev = sprt->rt6i_dev; | 346 | struct net_device *dev = sprt->dst.dev; |
342 | 347 | ||
343 | if (oif) { | 348 | if (oif) { |
344 | if (dev->ifindex == oif) | 349 | if (dev->ifindex == oif) |
345 | return sprt; | 350 | return sprt; |
346 | if (dev->flags & IFF_LOOPBACK) { | 351 | if (dev->flags & IFF_LOOPBACK) { |
347 | if (sprt->rt6i_idev == NULL || | 352 | if (!sprt->rt6i_idev || |
348 | sprt->rt6i_idev->dev->ifindex != oif) { | 353 | sprt->rt6i_idev->dev->ifindex != oif) { |
349 | if (flags & RT6_LOOKUP_F_IFACE && oif) | 354 | if (flags & RT6_LOOKUP_F_IFACE && oif) |
350 | continue; | 355 | continue; |
@@ -385,7 +390,7 @@ static void rt6_probe(struct rt6_info *rt) | |||
385 | * to no more than one per minute. | 390 | * to no more than one per minute. |
386 | */ | 391 | */ |
387 | rcu_read_lock(); | 392 | rcu_read_lock(); |
388 | neigh = rt ? dst_get_neighbour(&rt->dst) : NULL; | 393 | neigh = rt ? dst_get_neighbour_noref(&rt->dst) : NULL; |
389 | if (!neigh || (neigh->nud_state & NUD_VALID)) | 394 | if (!neigh || (neigh->nud_state & NUD_VALID)) |
390 | goto out; | 395 | goto out; |
391 | read_lock_bh(&neigh->lock); | 396 | read_lock_bh(&neigh->lock); |
@@ -399,7 +404,7 @@ static void rt6_probe(struct rt6_info *rt) | |||
399 | 404 | ||
400 | target = (struct in6_addr *)&neigh->primary_key; | 405 | target = (struct in6_addr *)&neigh->primary_key; |
401 | addrconf_addr_solict_mult(target, &mcaddr); | 406 | addrconf_addr_solict_mult(target, &mcaddr); |
402 | ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); | 407 | ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); |
403 | } else { | 408 | } else { |
404 | read_unlock_bh(&neigh->lock); | 409 | read_unlock_bh(&neigh->lock); |
405 | } | 410 | } |
@@ -417,7 +422,7 @@ static inline void rt6_probe(struct rt6_info *rt) | |||
417 | */ | 422 | */ |
418 | static inline int rt6_check_dev(struct rt6_info *rt, int oif) | 423 | static inline int rt6_check_dev(struct rt6_info *rt, int oif) |
419 | { | 424 | { |
420 | struct net_device *dev = rt->rt6i_dev; | 425 | struct net_device *dev = rt->dst.dev; |
421 | if (!oif || dev->ifindex == oif) | 426 | if (!oif || dev->ifindex == oif) |
422 | return 2; | 427 | return 2; |
423 | if ((dev->flags & IFF_LOOPBACK) && | 428 | if ((dev->flags & IFF_LOOPBACK) && |
@@ -432,7 +437,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt) | |||
432 | int m; | 437 | int m; |
433 | 438 | ||
434 | rcu_read_lock(); | 439 | rcu_read_lock(); |
435 | neigh = dst_get_neighbour(&rt->dst); | 440 | neigh = dst_get_neighbour_noref(&rt->dst); |
436 | if (rt->rt6i_flags & RTF_NONEXTHOP || | 441 | if (rt->rt6i_flags & RTF_NONEXTHOP || |
437 | !(rt->rt6i_flags & RTF_GATEWAY)) | 442 | !(rt->rt6i_flags & RTF_GATEWAY)) |
438 | m = 1; | 443 | m = 1; |
@@ -518,9 +523,6 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
518 | struct rt6_info *match, *rt0; | 523 | struct rt6_info *match, *rt0; |
519 | struct net *net; | 524 | struct net *net; |
520 | 525 | ||
521 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", | ||
522 | __func__, fn->leaf, oif); | ||
523 | |||
524 | rt0 = fn->rr_ptr; | 526 | rt0 = fn->rr_ptr; |
525 | if (!rt0) | 527 | if (!rt0) |
526 | fn->rr_ptr = rt0 = fn->leaf; | 528 | fn->rr_ptr = rt0 = fn->leaf; |
@@ -539,10 +541,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
539 | fn->rr_ptr = next; | 541 | fn->rr_ptr = next; |
540 | } | 542 | } |
541 | 543 | ||
542 | RT6_TRACE("%s() => %p\n", | 544 | net = dev_net(rt0->dst.dev); |
543 | __func__, match); | ||
544 | |||
545 | net = dev_net(rt0->rt6i_dev); | ||
546 | return match ? match : net->ipv6.ip6_null_entry; | 545 | return match ? match : net->ipv6.ip6_null_entry; |
547 | } | 546 | } |
548 | 547 | ||
@@ -611,7 +610,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
611 | if (!addrconf_finite_timeout(lifetime)) { | 610 | if (!addrconf_finite_timeout(lifetime)) { |
612 | rt->rt6i_flags &= ~RTF_EXPIRES; | 611 | rt->rt6i_flags &= ~RTF_EXPIRES; |
613 | } else { | 612 | } else { |
614 | rt->rt6i_expires = jiffies + HZ * lifetime; | 613 | rt->dst.expires = jiffies + HZ * lifetime; |
615 | rt->rt6i_flags |= RTF_EXPIRES; | 614 | rt->rt6i_flags |= RTF_EXPIRES; |
616 | } | 615 | } |
617 | dst_release(&rt->dst); | 616 | dst_release(&rt->dst); |
@@ -636,7 +635,7 @@ do { \ | |||
636 | goto restart; \ | 635 | goto restart; \ |
637 | } \ | 636 | } \ |
638 | } \ | 637 | } \ |
639 | } while(0) | 638 | } while (0) |
640 | 639 | ||
641 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, | 640 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
642 | struct fib6_table *table, | 641 | struct fib6_table *table, |
@@ -658,6 +657,13 @@ out: | |||
658 | 657 | ||
659 | } | 658 | } |
660 | 659 | ||
660 | struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6, | ||
661 | int flags) | ||
662 | { | ||
663 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup); | ||
664 | } | ||
665 | EXPORT_SYMBOL_GPL(ip6_route_lookup); | ||
666 | |||
661 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 667 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
662 | const struct in6_addr *saddr, int oif, int strict) | 668 | const struct in6_addr *saddr, int oif, int strict) |
663 | { | 669 | { |
@@ -706,7 +712,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) | |||
706 | int ip6_ins_rt(struct rt6_info *rt) | 712 | int ip6_ins_rt(struct rt6_info *rt) |
707 | { | 713 | { |
708 | struct nl_info info = { | 714 | struct nl_info info = { |
709 | .nl_net = dev_net(rt->rt6i_dev), | 715 | .nl_net = dev_net(rt->dst.dev), |
710 | }; | 716 | }; |
711 | return __ip6_ins_rt(rt, &info); | 717 | return __ip6_ins_rt(rt, &info); |
712 | } | 718 | } |
@@ -724,29 +730,27 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
724 | rt = ip6_rt_copy(ort, daddr); | 730 | rt = ip6_rt_copy(ort, daddr); |
725 | 731 | ||
726 | if (rt) { | 732 | if (rt) { |
727 | struct neighbour *neigh; | ||
728 | int attempts = !in_softirq(); | 733 | int attempts = !in_softirq(); |
729 | 734 | ||
730 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { | 735 | if (!(rt->rt6i_flags & RTF_GATEWAY)) { |
731 | if (ort->rt6i_dst.plen != 128 && | 736 | if (ort->rt6i_dst.plen != 128 && |
732 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) | 737 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) |
733 | rt->rt6i_flags |= RTF_ANYCAST; | 738 | rt->rt6i_flags |= RTF_ANYCAST; |
734 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 739 | rt->rt6i_gateway = *daddr; |
735 | } | 740 | } |
736 | 741 | ||
737 | rt->rt6i_flags |= RTF_CACHE; | 742 | rt->rt6i_flags |= RTF_CACHE; |
738 | 743 | ||
739 | #ifdef CONFIG_IPV6_SUBTREES | 744 | #ifdef CONFIG_IPV6_SUBTREES |
740 | if (rt->rt6i_src.plen && saddr) { | 745 | if (rt->rt6i_src.plen && saddr) { |
741 | ipv6_addr_copy(&rt->rt6i_src.addr, saddr); | 746 | rt->rt6i_src.addr = *saddr; |
742 | rt->rt6i_src.plen = 128; | 747 | rt->rt6i_src.plen = 128; |
743 | } | 748 | } |
744 | #endif | 749 | #endif |
745 | 750 | ||
746 | retry: | 751 | retry: |
747 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 752 | if (rt6_bind_neighbour(rt, rt->dst.dev)) { |
748 | if (IS_ERR(neigh)) { | 753 | struct net *net = dev_net(rt->dst.dev); |
749 | struct net *net = dev_net(rt->rt6i_dev); | ||
750 | int saved_rt_min_interval = | 754 | int saved_rt_min_interval = |
751 | net->ipv6.sysctl.ip6_rt_gc_min_interval; | 755 | net->ipv6.sysctl.ip6_rt_gc_min_interval; |
752 | int saved_rt_elasticity = | 756 | int saved_rt_elasticity = |
@@ -771,8 +775,6 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
771 | dst_free(&rt->dst); | 775 | dst_free(&rt->dst); |
772 | return NULL; | 776 | return NULL; |
773 | } | 777 | } |
774 | dst_set_neighbour(&rt->dst, neigh); | ||
775 | |||
776 | } | 778 | } |
777 | 779 | ||
778 | return rt; | 780 | return rt; |
@@ -785,7 +787,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, | |||
785 | 787 | ||
786 | if (rt) { | 788 | if (rt) { |
787 | rt->rt6i_flags |= RTF_CACHE; | 789 | rt->rt6i_flags |= RTF_CACHE; |
788 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); | 790 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_noref_raw(&ort->dst))); |
789 | } | 791 | } |
790 | return rt; | 792 | return rt; |
791 | } | 793 | } |
@@ -819,7 +821,7 @@ restart: | |||
819 | dst_hold(&rt->dst); | 821 | dst_hold(&rt->dst); |
820 | read_unlock_bh(&table->tb6_lock); | 822 | read_unlock_bh(&table->tb6_lock); |
821 | 823 | ||
822 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 824 | if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
823 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); | 825 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
824 | else if (!(rt->dst.flags & DST_HOST)) | 826 | else if (!(rt->dst.flags & DST_HOST)) |
825 | nrt = rt6_alloc_clone(rt, &fl6->daddr); | 827 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
@@ -875,7 +877,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
875 | .flowi6_iif = skb->dev->ifindex, | 877 | .flowi6_iif = skb->dev->ifindex, |
876 | .daddr = iph->daddr, | 878 | .daddr = iph->daddr, |
877 | .saddr = iph->saddr, | 879 | .saddr = iph->saddr, |
878 | .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, | 880 | .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, |
879 | .flowi6_mark = skb->mark, | 881 | .flowi6_mark = skb->mark, |
880 | .flowi6_proto = iph->nexthdr, | 882 | .flowi6_proto = iph->nexthdr, |
881 | }; | 883 | }; |
@@ -932,9 +934,9 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
932 | rt->rt6i_idev = ort->rt6i_idev; | 934 | rt->rt6i_idev = ort->rt6i_idev; |
933 | if (rt->rt6i_idev) | 935 | if (rt->rt6i_idev) |
934 | in6_dev_hold(rt->rt6i_idev); | 936 | in6_dev_hold(rt->rt6i_idev); |
935 | rt->rt6i_expires = 0; | 937 | rt->dst.expires = 0; |
936 | 938 | ||
937 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 939 | rt->rt6i_gateway = ort->rt6i_gateway; |
938 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 940 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
939 | rt->rt6i_metric = 0; | 941 | rt->rt6i_metric = 0; |
940 | 942 | ||
@@ -997,7 +999,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
997 | 999 | ||
998 | rt = (struct rt6_info *) skb_dst(skb); | 1000 | rt = (struct rt6_info *) skb_dst(skb); |
999 | if (rt) { | 1001 | if (rt) { |
1000 | if (rt->rt6i_flags&RTF_CACHE) { | 1002 | if (rt->rt6i_flags & RTF_CACHE) { |
1001 | dst_set_expires(&rt->dst, 0); | 1003 | dst_set_expires(&rt->dst, 0); |
1002 | rt->rt6i_flags |= RTF_EXPIRES; | 1004 | rt->rt6i_flags |= RTF_EXPIRES; |
1003 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | 1005 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
@@ -1067,34 +1069,38 @@ static DEFINE_SPINLOCK(icmp6_dst_lock); | |||
1067 | 1069 | ||
1068 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | 1070 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
1069 | struct neighbour *neigh, | 1071 | struct neighbour *neigh, |
1070 | const struct in6_addr *addr) | 1072 | struct flowi6 *fl6) |
1071 | { | 1073 | { |
1074 | struct dst_entry *dst; | ||
1072 | struct rt6_info *rt; | 1075 | struct rt6_info *rt; |
1073 | struct inet6_dev *idev = in6_dev_get(dev); | 1076 | struct inet6_dev *idev = in6_dev_get(dev); |
1074 | struct net *net = dev_net(dev); | 1077 | struct net *net = dev_net(dev); |
1075 | 1078 | ||
1076 | if (unlikely(idev == NULL)) | 1079 | if (unlikely(!idev)) |
1077 | return NULL; | 1080 | return NULL; |
1078 | 1081 | ||
1079 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); | 1082 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); |
1080 | if (unlikely(rt == NULL)) { | 1083 | if (unlikely(!rt)) { |
1081 | in6_dev_put(idev); | 1084 | in6_dev_put(idev); |
1085 | dst = ERR_PTR(-ENOMEM); | ||
1082 | goto out; | 1086 | goto out; |
1083 | } | 1087 | } |
1084 | 1088 | ||
1085 | if (neigh) | 1089 | if (neigh) |
1086 | neigh_hold(neigh); | 1090 | neigh_hold(neigh); |
1087 | else { | 1091 | else { |
1088 | neigh = ndisc_get_neigh(dev, addr); | 1092 | neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr); |
1089 | if (IS_ERR(neigh)) | 1093 | if (IS_ERR(neigh)) { |
1090 | neigh = NULL; | 1094 | dst_free(&rt->dst); |
1095 | return ERR_CAST(neigh); | ||
1096 | } | ||
1091 | } | 1097 | } |
1092 | 1098 | ||
1093 | rt->dst.flags |= DST_HOST; | 1099 | rt->dst.flags |= DST_HOST; |
1094 | rt->dst.output = ip6_output; | 1100 | rt->dst.output = ip6_output; |
1095 | dst_set_neighbour(&rt->dst, neigh); | 1101 | dst_set_neighbour(&rt->dst, neigh); |
1096 | atomic_set(&rt->dst.__refcnt, 1); | 1102 | atomic_set(&rt->dst.__refcnt, 1); |
1097 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1103 | rt->rt6i_dst.addr = fl6->daddr; |
1098 | rt->rt6i_dst.plen = 128; | 1104 | rt->rt6i_dst.plen = 128; |
1099 | rt->rt6i_idev = idev; | 1105 | rt->rt6i_idev = idev; |
1100 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1106 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
@@ -1106,8 +1112,10 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1106 | 1112 | ||
1107 | fib6_force_start_gc(net); | 1113 | fib6_force_start_gc(net); |
1108 | 1114 | ||
1115 | dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); | ||
1116 | |||
1109 | out: | 1117 | out: |
1110 | return &rt->dst; | 1118 | return dst; |
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | int icmp6_dst_gc(void) | 1121 | int icmp6_dst_gc(void) |
@@ -1237,21 +1245,30 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1237 | if (cfg->fc_metric == 0) | 1245 | if (cfg->fc_metric == 0) |
1238 | cfg->fc_metric = IP6_RT_PRIO_USER; | 1246 | cfg->fc_metric = IP6_RT_PRIO_USER; |
1239 | 1247 | ||
1240 | table = fib6_new_table(net, cfg->fc_table); | 1248 | err = -ENOBUFS; |
1241 | if (table == NULL) { | 1249 | if (cfg->fc_nlinfo.nlh && |
1242 | err = -ENOBUFS; | 1250 | !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) { |
1243 | goto out; | 1251 | table = fib6_get_table(net, cfg->fc_table); |
1252 | if (!table) { | ||
1253 | printk(KERN_WARNING "IPv6: NLM_F_CREATE should be specified when creating new route\n"); | ||
1254 | table = fib6_new_table(net, cfg->fc_table); | ||
1255 | } | ||
1256 | } else { | ||
1257 | table = fib6_new_table(net, cfg->fc_table); | ||
1244 | } | 1258 | } |
1245 | 1259 | ||
1260 | if (!table) | ||
1261 | goto out; | ||
1262 | |||
1246 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); | 1263 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); |
1247 | 1264 | ||
1248 | if (rt == NULL) { | 1265 | if (!rt) { |
1249 | err = -ENOMEM; | 1266 | err = -ENOMEM; |
1250 | goto out; | 1267 | goto out; |
1251 | } | 1268 | } |
1252 | 1269 | ||
1253 | rt->dst.obsolete = -1; | 1270 | rt->dst.obsolete = -1; |
1254 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1271 | rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ? |
1255 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1272 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : |
1256 | 0; | 1273 | 0; |
1257 | 1274 | ||
@@ -1294,8 +1311,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1294 | they would result in kernel looping; promote them to reject routes | 1311 | they would result in kernel looping; promote them to reject routes |
1295 | */ | 1312 | */ |
1296 | if ((cfg->fc_flags & RTF_REJECT) || | 1313 | if ((cfg->fc_flags & RTF_REJECT) || |
1297 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK) | 1314 | (dev && (dev->flags & IFF_LOOPBACK) && |
1298 | && !(cfg->fc_flags&RTF_LOCAL))) { | 1315 | !(addr_type & IPV6_ADDR_LOOPBACK) && |
1316 | !(cfg->fc_flags & RTF_LOCAL))) { | ||
1299 | /* hold loopback dev/idev if we haven't done so. */ | 1317 | /* hold loopback dev/idev if we haven't done so. */ |
1300 | if (dev != net->loopback_dev) { | 1318 | if (dev != net->loopback_dev) { |
1301 | if (dev) { | 1319 | if (dev) { |
@@ -1322,7 +1340,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1322 | int gwa_type; | 1340 | int gwa_type; |
1323 | 1341 | ||
1324 | gw_addr = &cfg->fc_gateway; | 1342 | gw_addr = &cfg->fc_gateway; |
1325 | ipv6_addr_copy(&rt->rt6i_gateway, gw_addr); | 1343 | rt->rt6i_gateway = *gw_addr; |
1326 | gwa_type = ipv6_addr_type(gw_addr); | 1344 | gwa_type = ipv6_addr_type(gw_addr); |
1327 | 1345 | ||
1328 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { | 1346 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { |
@@ -1336,26 +1354,26 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1336 | some exceptions. --ANK | 1354 | some exceptions. --ANK |
1337 | */ | 1355 | */ |
1338 | err = -EINVAL; | 1356 | err = -EINVAL; |
1339 | if (!(gwa_type&IPV6_ADDR_UNICAST)) | 1357 | if (!(gwa_type & IPV6_ADDR_UNICAST)) |
1340 | goto out; | 1358 | goto out; |
1341 | 1359 | ||
1342 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); | 1360 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); |
1343 | 1361 | ||
1344 | err = -EHOSTUNREACH; | 1362 | err = -EHOSTUNREACH; |
1345 | if (grt == NULL) | 1363 | if (!grt) |
1346 | goto out; | 1364 | goto out; |
1347 | if (dev) { | 1365 | if (dev) { |
1348 | if (dev != grt->rt6i_dev) { | 1366 | if (dev != grt->dst.dev) { |
1349 | dst_release(&grt->dst); | 1367 | dst_release(&grt->dst); |
1350 | goto out; | 1368 | goto out; |
1351 | } | 1369 | } |
1352 | } else { | 1370 | } else { |
1353 | dev = grt->rt6i_dev; | 1371 | dev = grt->dst.dev; |
1354 | idev = grt->rt6i_idev; | 1372 | idev = grt->rt6i_idev; |
1355 | dev_hold(dev); | 1373 | dev_hold(dev); |
1356 | in6_dev_hold(grt->rt6i_idev); | 1374 | in6_dev_hold(grt->rt6i_idev); |
1357 | } | 1375 | } |
1358 | if (!(grt->rt6i_flags&RTF_GATEWAY)) | 1376 | if (!(grt->rt6i_flags & RTF_GATEWAY)) |
1359 | err = 0; | 1377 | err = 0; |
1360 | dst_release(&grt->dst); | 1378 | dst_release(&grt->dst); |
1361 | 1379 | ||
@@ -1363,12 +1381,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1363 | goto out; | 1381 | goto out; |
1364 | } | 1382 | } |
1365 | err = -EINVAL; | 1383 | err = -EINVAL; |
1366 | if (dev == NULL || (dev->flags&IFF_LOOPBACK)) | 1384 | if (!dev || (dev->flags & IFF_LOOPBACK)) |
1367 | goto out; | 1385 | goto out; |
1368 | } | 1386 | } |
1369 | 1387 | ||
1370 | err = -ENODEV; | 1388 | err = -ENODEV; |
1371 | if (dev == NULL) | 1389 | if (!dev) |
1372 | goto out; | 1390 | goto out; |
1373 | 1391 | ||
1374 | if (!ipv6_addr_any(&cfg->fc_prefsrc)) { | 1392 | if (!ipv6_addr_any(&cfg->fc_prefsrc)) { |
@@ -1376,18 +1394,15 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1376 | err = -EINVAL; | 1394 | err = -EINVAL; |
1377 | goto out; | 1395 | goto out; |
1378 | } | 1396 | } |
1379 | ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc); | 1397 | rt->rt6i_prefsrc.addr = cfg->fc_prefsrc; |
1380 | rt->rt6i_prefsrc.plen = 128; | 1398 | rt->rt6i_prefsrc.plen = 128; |
1381 | } else | 1399 | } else |
1382 | rt->rt6i_prefsrc.plen = 0; | 1400 | rt->rt6i_prefsrc.plen = 0; |
1383 | 1401 | ||
1384 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { | 1402 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { |
1385 | struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); | 1403 | err = rt6_bind_neighbour(rt, dev); |
1386 | if (IS_ERR(n)) { | 1404 | if (err) |
1387 | err = PTR_ERR(n); | ||
1388 | goto out; | 1405 | goto out; |
1389 | } | ||
1390 | dst_set_neighbour(&rt->dst, n); | ||
1391 | } | 1406 | } |
1392 | 1407 | ||
1393 | rt->rt6i_flags = cfg->fc_flags; | 1408 | rt->rt6i_flags = cfg->fc_flags; |
@@ -1433,7 +1448,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1433 | { | 1448 | { |
1434 | int err; | 1449 | int err; |
1435 | struct fib6_table *table; | 1450 | struct fib6_table *table; |
1436 | struct net *net = dev_net(rt->rt6i_dev); | 1451 | struct net *net = dev_net(rt->dst.dev); |
1437 | 1452 | ||
1438 | if (rt == net->ipv6.ip6_null_entry) | 1453 | if (rt == net->ipv6.ip6_null_entry) |
1439 | return -ENOENT; | 1454 | return -ENOENT; |
@@ -1452,7 +1467,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1452 | int ip6_del_rt(struct rt6_info *rt) | 1467 | int ip6_del_rt(struct rt6_info *rt) |
1453 | { | 1468 | { |
1454 | struct nl_info info = { | 1469 | struct nl_info info = { |
1455 | .nl_net = dev_net(rt->rt6i_dev), | 1470 | .nl_net = dev_net(rt->dst.dev), |
1456 | }; | 1471 | }; |
1457 | return __ip6_del_rt(rt, &info); | 1472 | return __ip6_del_rt(rt, &info); |
1458 | } | 1473 | } |
@@ -1465,7 +1480,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1465 | int err = -ESRCH; | 1480 | int err = -ESRCH; |
1466 | 1481 | ||
1467 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); | 1482 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); |
1468 | if (table == NULL) | 1483 | if (!table) |
1469 | return err; | 1484 | return err; |
1470 | 1485 | ||
1471 | read_lock_bh(&table->tb6_lock); | 1486 | read_lock_bh(&table->tb6_lock); |
@@ -1477,8 +1492,8 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1477 | if (fn) { | 1492 | if (fn) { |
1478 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1493 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1479 | if (cfg->fc_ifindex && | 1494 | if (cfg->fc_ifindex && |
1480 | (rt->rt6i_dev == NULL || | 1495 | (!rt->dst.dev || |
1481 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) | 1496 | rt->dst.dev->ifindex != cfg->fc_ifindex)) |
1482 | continue; | 1497 | continue; |
1483 | if (cfg->fc_flags & RTF_GATEWAY && | 1498 | if (cfg->fc_flags & RTF_GATEWAY && |
1484 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) | 1499 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) |
@@ -1540,7 +1555,7 @@ restart: | |||
1540 | continue; | 1555 | continue; |
1541 | if (!(rt->rt6i_flags & RTF_GATEWAY)) | 1556 | if (!(rt->rt6i_flags & RTF_GATEWAY)) |
1542 | continue; | 1557 | continue; |
1543 | if (fl6->flowi6_oif != rt->rt6i_dev->ifindex) | 1558 | if (fl6->flowi6_oif != rt->dst.dev->ifindex) |
1544 | continue; | 1559 | continue; |
1545 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) | 1560 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) |
1546 | continue; | 1561 | continue; |
@@ -1573,7 +1588,7 @@ static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest, | |||
1573 | }, | 1588 | }, |
1574 | }; | 1589 | }; |
1575 | 1590 | ||
1576 | ipv6_addr_copy(&rdfl.gateway, gateway); | 1591 | rdfl.gateway = *gateway; |
1577 | 1592 | ||
1578 | if (rt6_need_strict(dest)) | 1593 | if (rt6_need_strict(dest)) |
1579 | flags |= RT6_LOOKUP_F_IFACE; | 1594 | flags |= RT6_LOOKUP_F_IFACE; |
@@ -1618,18 +1633,18 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1618 | dst_confirm(&rt->dst); | 1633 | dst_confirm(&rt->dst); |
1619 | 1634 | ||
1620 | /* Duplicate redirect: silently ignore. */ | 1635 | /* Duplicate redirect: silently ignore. */ |
1621 | if (neigh == dst_get_neighbour_raw(&rt->dst)) | 1636 | if (neigh == dst_get_neighbour_noref_raw(&rt->dst)) |
1622 | goto out; | 1637 | goto out; |
1623 | 1638 | ||
1624 | nrt = ip6_rt_copy(rt, dest); | 1639 | nrt = ip6_rt_copy(rt, dest); |
1625 | if (nrt == NULL) | 1640 | if (!nrt) |
1626 | goto out; | 1641 | goto out; |
1627 | 1642 | ||
1628 | nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; | 1643 | nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; |
1629 | if (on_link) | 1644 | if (on_link) |
1630 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1645 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1631 | 1646 | ||
1632 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1647 | nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; |
1633 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); | 1648 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1634 | 1649 | ||
1635 | if (ip6_ins_rt(nrt)) | 1650 | if (ip6_ins_rt(nrt)) |
@@ -1639,7 +1654,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1639 | netevent.new = &nrt->dst; | 1654 | netevent.new = &nrt->dst; |
1640 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); | 1655 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); |
1641 | 1656 | ||
1642 | if (rt->rt6i_flags&RTF_CACHE) { | 1657 | if (rt->rt6i_flags & RTF_CACHE) { |
1643 | ip6_del_rt(rt); | 1658 | ip6_del_rt(rt); |
1644 | return; | 1659 | return; |
1645 | } | 1660 | } |
@@ -1660,7 +1675,7 @@ static void rt6_do_pmtu_disc(const struct in6_addr *daddr, const struct in6_addr | |||
1660 | int allfrag = 0; | 1675 | int allfrag = 0; |
1661 | again: | 1676 | again: |
1662 | rt = rt6_lookup(net, daddr, saddr, ifindex, 0); | 1677 | rt = rt6_lookup(net, daddr, saddr, ifindex, 0); |
1663 | if (rt == NULL) | 1678 | if (!rt) |
1664 | return; | 1679 | return; |
1665 | 1680 | ||
1666 | if (rt6_check_expired(rt)) { | 1681 | if (rt6_check_expired(rt)) { |
@@ -1710,7 +1725,7 @@ again: | |||
1710 | 1. It is connected route. Action: COW | 1725 | 1. It is connected route. Action: COW |
1711 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. | 1726 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. |
1712 | */ | 1727 | */ |
1713 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 1728 | if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
1714 | nrt = rt6_alloc_cow(rt, daddr, saddr); | 1729 | nrt = rt6_alloc_cow(rt, daddr, saddr); |
1715 | else | 1730 | else |
1716 | nrt = rt6_alloc_clone(rt, daddr); | 1731 | nrt = rt6_alloc_clone(rt, daddr); |
@@ -1766,7 +1781,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad | |||
1766 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 1781 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
1767 | const struct in6_addr *dest) | 1782 | const struct in6_addr *dest) |
1768 | { | 1783 | { |
1769 | struct net *net = dev_net(ort->rt6i_dev); | 1784 | struct net *net = dev_net(ort->dst.dev); |
1770 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 1785 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
1771 | ort->dst.dev, 0); | 1786 | ort->dst.dev, 0); |
1772 | 1787 | ||
@@ -1775,7 +1790,7 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1775 | rt->dst.output = ort->dst.output; | 1790 | rt->dst.output = ort->dst.output; |
1776 | rt->dst.flags |= DST_HOST; | 1791 | rt->dst.flags |= DST_HOST; |
1777 | 1792 | ||
1778 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | 1793 | rt->rt6i_dst.addr = *dest; |
1779 | rt->rt6i_dst.plen = 128; | 1794 | rt->rt6i_dst.plen = 128; |
1780 | dst_copy_metrics(&rt->dst, &ort->dst); | 1795 | dst_copy_metrics(&rt->dst, &ort->dst); |
1781 | rt->dst.error = ort->dst.error; | 1796 | rt->dst.error = ort->dst.error; |
@@ -1783,9 +1798,9 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1783 | if (rt->rt6i_idev) | 1798 | if (rt->rt6i_idev) |
1784 | in6_dev_hold(rt->rt6i_idev); | 1799 | in6_dev_hold(rt->rt6i_idev); |
1785 | rt->dst.lastuse = jiffies; | 1800 | rt->dst.lastuse = jiffies; |
1786 | rt->rt6i_expires = 0; | 1801 | rt->dst.expires = 0; |
1787 | 1802 | ||
1788 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 1803 | rt->rt6i_gateway = ort->rt6i_gateway; |
1789 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 1804 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
1790 | rt->rt6i_metric = 0; | 1805 | rt->rt6i_metric = 0; |
1791 | 1806 | ||
@@ -1808,7 +1823,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1808 | struct fib6_table *table; | 1823 | struct fib6_table *table; |
1809 | 1824 | ||
1810 | table = fib6_get_table(net, RT6_TABLE_INFO); | 1825 | table = fib6_get_table(net, RT6_TABLE_INFO); |
1811 | if (table == NULL) | 1826 | if (!table) |
1812 | return NULL; | 1827 | return NULL; |
1813 | 1828 | ||
1814 | write_lock_bh(&table->tb6_lock); | 1829 | write_lock_bh(&table->tb6_lock); |
@@ -1817,7 +1832,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1817 | goto out; | 1832 | goto out; |
1818 | 1833 | ||
1819 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1834 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1820 | if (rt->rt6i_dev->ifindex != ifindex) | 1835 | if (rt->dst.dev->ifindex != ifindex) |
1821 | continue; | 1836 | continue; |
1822 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) | 1837 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) |
1823 | continue; | 1838 | continue; |
@@ -1848,8 +1863,8 @@ static struct rt6_info *rt6_add_route_info(struct net *net, | |||
1848 | .fc_nlinfo.nl_net = net, | 1863 | .fc_nlinfo.nl_net = net, |
1849 | }; | 1864 | }; |
1850 | 1865 | ||
1851 | ipv6_addr_copy(&cfg.fc_dst, prefix); | 1866 | cfg.fc_dst = *prefix; |
1852 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1867 | cfg.fc_gateway = *gwaddr; |
1853 | 1868 | ||
1854 | /* We should treat it as a default route if prefix length is 0. */ | 1869 | /* We should treat it as a default route if prefix length is 0. */ |
1855 | if (!prefixlen) | 1870 | if (!prefixlen) |
@@ -1867,12 +1882,12 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev | |||
1867 | struct fib6_table *table; | 1882 | struct fib6_table *table; |
1868 | 1883 | ||
1869 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); | 1884 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); |
1870 | if (table == NULL) | 1885 | if (!table) |
1871 | return NULL; | 1886 | return NULL; |
1872 | 1887 | ||
1873 | write_lock_bh(&table->tb6_lock); | 1888 | write_lock_bh(&table->tb6_lock); |
1874 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { | 1889 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
1875 | if (dev == rt->rt6i_dev && | 1890 | if (dev == rt->dst.dev && |
1876 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1891 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
1877 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) | 1892 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) |
1878 | break; | 1893 | break; |
@@ -1898,7 +1913,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, | |||
1898 | .fc_nlinfo.nl_net = dev_net(dev), | 1913 | .fc_nlinfo.nl_net = dev_net(dev), |
1899 | }; | 1914 | }; |
1900 | 1915 | ||
1901 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1916 | cfg.fc_gateway = *gwaddr; |
1902 | 1917 | ||
1903 | ip6_route_add(&cfg); | 1918 | ip6_route_add(&cfg); |
1904 | 1919 | ||
@@ -1912,7 +1927,7 @@ void rt6_purge_dflt_routers(struct net *net) | |||
1912 | 1927 | ||
1913 | /* NOTE: Keep consistent with rt6_get_dflt_router */ | 1928 | /* NOTE: Keep consistent with rt6_get_dflt_router */ |
1914 | table = fib6_get_table(net, RT6_TABLE_DFLT); | 1929 | table = fib6_get_table(net, RT6_TABLE_DFLT); |
1915 | if (table == NULL) | 1930 | if (!table) |
1916 | return; | 1931 | return; |
1917 | 1932 | ||
1918 | restart: | 1933 | restart: |
@@ -1944,9 +1959,9 @@ static void rtmsg_to_fib6_config(struct net *net, | |||
1944 | 1959 | ||
1945 | cfg->fc_nlinfo.nl_net = net; | 1960 | cfg->fc_nlinfo.nl_net = net; |
1946 | 1961 | ||
1947 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); | 1962 | cfg->fc_dst = rtmsg->rtmsg_dst; |
1948 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); | 1963 | cfg->fc_src = rtmsg->rtmsg_src; |
1949 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); | 1964 | cfg->fc_gateway = rtmsg->rtmsg_gateway; |
1950 | } | 1965 | } |
1951 | 1966 | ||
1952 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) | 1967 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
@@ -2045,14 +2060,14 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb) | |||
2045 | 2060 | ||
2046 | struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | 2061 | struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, |
2047 | const struct in6_addr *addr, | 2062 | const struct in6_addr *addr, |
2048 | int anycast) | 2063 | bool anycast) |
2049 | { | 2064 | { |
2050 | struct net *net = dev_net(idev->dev); | 2065 | struct net *net = dev_net(idev->dev); |
2051 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 2066 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
2052 | net->loopback_dev, 0); | 2067 | net->loopback_dev, 0); |
2053 | struct neighbour *neigh; | 2068 | int err; |
2054 | 2069 | ||
2055 | if (rt == NULL) { | 2070 | if (!rt) { |
2056 | if (net_ratelimit()) | 2071 | if (net_ratelimit()) |
2057 | pr_warning("IPv6: Maximum number of routes reached," | 2072 | pr_warning("IPv6: Maximum number of routes reached," |
2058 | " consider increasing route/max_size.\n"); | 2073 | " consider increasing route/max_size.\n"); |
@@ -2072,15 +2087,13 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2072 | rt->rt6i_flags |= RTF_ANYCAST; | 2087 | rt->rt6i_flags |= RTF_ANYCAST; |
2073 | else | 2088 | else |
2074 | rt->rt6i_flags |= RTF_LOCAL; | 2089 | rt->rt6i_flags |= RTF_LOCAL; |
2075 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 2090 | err = rt6_bind_neighbour(rt, rt->dst.dev); |
2076 | if (IS_ERR(neigh)) { | 2091 | if (err) { |
2077 | dst_free(&rt->dst); | 2092 | dst_free(&rt->dst); |
2078 | 2093 | return ERR_PTR(err); | |
2079 | return ERR_CAST(neigh); | ||
2080 | } | 2094 | } |
2081 | dst_set_neighbour(&rt->dst, neigh); | ||
2082 | 2095 | ||
2083 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 2096 | rt->rt6i_dst.addr = *addr; |
2084 | rt->rt6i_dst.plen = 128; | 2097 | rt->rt6i_dst.plen = 128; |
2085 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 2098 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
2086 | 2099 | ||
@@ -2098,7 +2111,7 @@ int ip6_route_get_saddr(struct net *net, | |||
2098 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); | 2111 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); |
2099 | int err = 0; | 2112 | int err = 0; |
2100 | if (rt->rt6i_prefsrc.plen) | 2113 | if (rt->rt6i_prefsrc.plen) |
2101 | ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr); | 2114 | *saddr = rt->rt6i_prefsrc.addr; |
2102 | else | 2115 | else |
2103 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2116 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
2104 | daddr, prefs, saddr); | 2117 | daddr, prefs, saddr); |
@@ -2118,7 +2131,7 @@ static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) | |||
2118 | struct net *net = ((struct arg_dev_net_ip *)arg)->net; | 2131 | struct net *net = ((struct arg_dev_net_ip *)arg)->net; |
2119 | struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; | 2132 | struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; |
2120 | 2133 | ||
2121 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | 2134 | if (((void *)rt->dst.dev == dev || !dev) && |
2122 | rt != net->ipv6.ip6_null_entry && | 2135 | rt != net->ipv6.ip6_null_entry && |
2123 | ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { | 2136 | ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { |
2124 | /* remove prefsrc entry */ | 2137 | /* remove prefsrc entry */ |
@@ -2148,11 +2161,10 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) | |||
2148 | const struct arg_dev_net *adn = arg; | 2161 | const struct arg_dev_net *adn = arg; |
2149 | const struct net_device *dev = adn->dev; | 2162 | const struct net_device *dev = adn->dev; |
2150 | 2163 | ||
2151 | if ((rt->rt6i_dev == dev || dev == NULL) && | 2164 | if ((rt->dst.dev == dev || !dev) && |
2152 | rt != adn->net->ipv6.ip6_null_entry) { | 2165 | rt != adn->net->ipv6.ip6_null_entry) |
2153 | RT6_TRACE("deleted by ifdown %p\n", rt); | ||
2154 | return -1; | 2166 | return -1; |
2155 | } | 2167 | |
2156 | return 0; | 2168 | return 0; |
2157 | } | 2169 | } |
2158 | 2170 | ||
@@ -2185,7 +2197,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2185 | */ | 2197 | */ |
2186 | 2198 | ||
2187 | idev = __in6_dev_get(arg->dev); | 2199 | idev = __in6_dev_get(arg->dev); |
2188 | if (idev == NULL) | 2200 | if (!idev) |
2189 | return 0; | 2201 | return 0; |
2190 | 2202 | ||
2191 | /* For administrative MTU increase, there is no way to discover | 2203 | /* For administrative MTU increase, there is no way to discover |
@@ -2202,7 +2214,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2202 | also have the lowest MTU, TOO BIG MESSAGE will be lead to | 2214 | also have the lowest MTU, TOO BIG MESSAGE will be lead to |
2203 | PMTU discouvery. | 2215 | PMTU discouvery. |
2204 | */ | 2216 | */ |
2205 | if (rt->rt6i_dev == arg->dev && | 2217 | if (rt->dst.dev == arg->dev && |
2206 | !dst_metric_locked(&rt->dst, RTAX_MTU) && | 2218 | !dst_metric_locked(&rt->dst, RTAX_MTU) && |
2207 | (dst_mtu(&rt->dst) >= arg->mtu || | 2219 | (dst_mtu(&rt->dst) >= arg->mtu || |
2208 | (dst_mtu(&rt->dst) < arg->mtu && | 2220 | (dst_mtu(&rt->dst) < arg->mtu && |
@@ -2351,11 +2363,13 @@ static int rt6_fill_node(struct net *net, | |||
2351 | int iif, int type, u32 pid, u32 seq, | 2363 | int iif, int type, u32 pid, u32 seq, |
2352 | int prefix, int nowait, unsigned int flags) | 2364 | int prefix, int nowait, unsigned int flags) |
2353 | { | 2365 | { |
2366 | const struct inet_peer *peer; | ||
2354 | struct rtmsg *rtm; | 2367 | struct rtmsg *rtm; |
2355 | struct nlmsghdr *nlh; | 2368 | struct nlmsghdr *nlh; |
2356 | long expires; | 2369 | long expires; |
2357 | u32 table; | 2370 | u32 table; |
2358 | struct neighbour *n; | 2371 | struct neighbour *n; |
2372 | u32 ts, tsage; | ||
2359 | 2373 | ||
2360 | if (prefix) { /* user wants prefix routes only */ | 2374 | if (prefix) { /* user wants prefix routes only */ |
2361 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { | 2375 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { |
@@ -2365,7 +2379,7 @@ static int rt6_fill_node(struct net *net, | |||
2365 | } | 2379 | } |
2366 | 2380 | ||
2367 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); | 2381 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); |
2368 | if (nlh == NULL) | 2382 | if (!nlh) |
2369 | return -EMSGSIZE; | 2383 | return -EMSGSIZE; |
2370 | 2384 | ||
2371 | rtm = nlmsg_data(nlh); | 2385 | rtm = nlmsg_data(nlh); |
@@ -2379,25 +2393,25 @@ static int rt6_fill_node(struct net *net, | |||
2379 | table = RT6_TABLE_UNSPEC; | 2393 | table = RT6_TABLE_UNSPEC; |
2380 | rtm->rtm_table = table; | 2394 | rtm->rtm_table = table; |
2381 | NLA_PUT_U32(skb, RTA_TABLE, table); | 2395 | NLA_PUT_U32(skb, RTA_TABLE, table); |
2382 | if (rt->rt6i_flags&RTF_REJECT) | 2396 | if (rt->rt6i_flags & RTF_REJECT) |
2383 | rtm->rtm_type = RTN_UNREACHABLE; | 2397 | rtm->rtm_type = RTN_UNREACHABLE; |
2384 | else if (rt->rt6i_flags&RTF_LOCAL) | 2398 | else if (rt->rt6i_flags & RTF_LOCAL) |
2385 | rtm->rtm_type = RTN_LOCAL; | 2399 | rtm->rtm_type = RTN_LOCAL; |
2386 | else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) | 2400 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) |
2387 | rtm->rtm_type = RTN_LOCAL; | 2401 | rtm->rtm_type = RTN_LOCAL; |
2388 | else | 2402 | else |
2389 | rtm->rtm_type = RTN_UNICAST; | 2403 | rtm->rtm_type = RTN_UNICAST; |
2390 | rtm->rtm_flags = 0; | 2404 | rtm->rtm_flags = 0; |
2391 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | 2405 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; |
2392 | rtm->rtm_protocol = rt->rt6i_protocol; | 2406 | rtm->rtm_protocol = rt->rt6i_protocol; |
2393 | if (rt->rt6i_flags&RTF_DYNAMIC) | 2407 | if (rt->rt6i_flags & RTF_DYNAMIC) |
2394 | rtm->rtm_protocol = RTPROT_REDIRECT; | 2408 | rtm->rtm_protocol = RTPROT_REDIRECT; |
2395 | else if (rt->rt6i_flags & RTF_ADDRCONF) | 2409 | else if (rt->rt6i_flags & RTF_ADDRCONF) |
2396 | rtm->rtm_protocol = RTPROT_KERNEL; | 2410 | rtm->rtm_protocol = RTPROT_KERNEL; |
2397 | else if (rt->rt6i_flags&RTF_DEFAULT) | 2411 | else if (rt->rt6i_flags & RTF_DEFAULT) |
2398 | rtm->rtm_protocol = RTPROT_RA; | 2412 | rtm->rtm_protocol = RTPROT_RA; |
2399 | 2413 | ||
2400 | if (rt->rt6i_flags&RTF_CACHE) | 2414 | if (rt->rt6i_flags & RTF_CACHE) |
2401 | rtm->rtm_flags |= RTM_F_CLONED; | 2415 | rtm->rtm_flags |= RTM_F_CLONED; |
2402 | 2416 | ||
2403 | if (dst) { | 2417 | if (dst) { |
@@ -2437,7 +2451,7 @@ static int rt6_fill_node(struct net *net, | |||
2437 | 2451 | ||
2438 | if (rt->rt6i_prefsrc.plen) { | 2452 | if (rt->rt6i_prefsrc.plen) { |
2439 | struct in6_addr saddr_buf; | 2453 | struct in6_addr saddr_buf; |
2440 | ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr); | 2454 | saddr_buf = rt->rt6i_prefsrc.addr; |
2441 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2455 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2442 | } | 2456 | } |
2443 | 2457 | ||
@@ -2445,24 +2459,31 @@ static int rt6_fill_node(struct net *net, | |||
2445 | goto nla_put_failure; | 2459 | goto nla_put_failure; |
2446 | 2460 | ||
2447 | rcu_read_lock(); | 2461 | rcu_read_lock(); |
2448 | n = dst_get_neighbour(&rt->dst); | 2462 | n = dst_get_neighbour_noref(&rt->dst); |
2449 | if (n) | 2463 | if (n) |
2450 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); | 2464 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); |
2451 | rcu_read_unlock(); | 2465 | rcu_read_unlock(); |
2452 | 2466 | ||
2453 | if (rt->dst.dev) | 2467 | if (rt->dst.dev) |
2454 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2468 | NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); |
2455 | 2469 | ||
2456 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2470 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
2457 | 2471 | ||
2458 | if (!(rt->rt6i_flags & RTF_EXPIRES)) | 2472 | if (!(rt->rt6i_flags & RTF_EXPIRES)) |
2459 | expires = 0; | 2473 | expires = 0; |
2460 | else if (rt->rt6i_expires - jiffies < INT_MAX) | 2474 | else if (rt->dst.expires - jiffies < INT_MAX) |
2461 | expires = rt->rt6i_expires - jiffies; | 2475 | expires = rt->dst.expires - jiffies; |
2462 | else | 2476 | else |
2463 | expires = INT_MAX; | 2477 | expires = INT_MAX; |
2464 | 2478 | ||
2465 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, | 2479 | peer = rt->rt6i_peer; |
2480 | ts = tsage = 0; | ||
2481 | if (peer && peer->tcp_ts_stamp) { | ||
2482 | ts = peer->tcp_ts; | ||
2483 | tsage = get_seconds() - peer->tcp_ts_stamp; | ||
2484 | } | ||
2485 | |||
2486 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, ts, tsage, | ||
2466 | expires, rt->dst.error) < 0) | 2487 | expires, rt->dst.error) < 0) |
2467 | goto nla_put_failure; | 2488 | goto nla_put_failure; |
2468 | 2489 | ||
@@ -2511,14 +2532,14 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2511 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) | 2532 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) |
2512 | goto errout; | 2533 | goto errout; |
2513 | 2534 | ||
2514 | ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC])); | 2535 | fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]); |
2515 | } | 2536 | } |
2516 | 2537 | ||
2517 | if (tb[RTA_DST]) { | 2538 | if (tb[RTA_DST]) { |
2518 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) | 2539 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) |
2519 | goto errout; | 2540 | goto errout; |
2520 | 2541 | ||
2521 | ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST])); | 2542 | fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]); |
2522 | } | 2543 | } |
2523 | 2544 | ||
2524 | if (tb[RTA_IIF]) | 2545 | if (tb[RTA_IIF]) |
@@ -2537,7 +2558,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2537 | } | 2558 | } |
2538 | 2559 | ||
2539 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 2560 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
2540 | if (skb == NULL) { | 2561 | if (!skb) { |
2541 | err = -ENOBUFS; | 2562 | err = -ENOBUFS; |
2542 | goto errout; | 2563 | goto errout; |
2543 | } | 2564 | } |
@@ -2572,10 +2593,10 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2572 | int err; | 2593 | int err; |
2573 | 2594 | ||
2574 | err = -ENOBUFS; | 2595 | err = -ENOBUFS; |
2575 | seq = info->nlh != NULL ? info->nlh->nlmsg_seq : 0; | 2596 | seq = info->nlh ? info->nlh->nlmsg_seq : 0; |
2576 | 2597 | ||
2577 | skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); | 2598 | skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); |
2578 | if (skb == NULL) | 2599 | if (!skb) |
2579 | goto errout; | 2600 | goto errout; |
2580 | 2601 | ||
2581 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, | 2602 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, |
@@ -2642,7 +2663,7 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2642 | seq_puts(m, "00000000000000000000000000000000 00 "); | 2663 | seq_puts(m, "00000000000000000000000000000000 00 "); |
2643 | #endif | 2664 | #endif |
2644 | rcu_read_lock(); | 2665 | rcu_read_lock(); |
2645 | n = dst_get_neighbour(&rt->dst); | 2666 | n = dst_get_neighbour_noref(&rt->dst); |
2646 | if (n) { | 2667 | if (n) { |
2647 | seq_printf(m, "%pi6", n->primary_key); | 2668 | seq_printf(m, "%pi6", n->primary_key); |
2648 | } else { | 2669 | } else { |
@@ -2652,7 +2673,7 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2652 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2673 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
2653 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), | 2674 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
2654 | rt->dst.__use, rt->rt6i_flags, | 2675 | rt->dst.__use, rt->rt6i_flags, |
2655 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); | 2676 | rt->dst.dev ? rt->dst.dev->name : ""); |
2656 | return 0; | 2677 | return 0; |
2657 | } | 2678 | } |
2658 | 2679 | ||