diff options
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 396 |
1 files changed, 205 insertions, 191 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2bd74c5f8d9..a275c6e1e25c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
| 41 | #include <linux/seq_file.h> | 41 | #include <linux/seq_file.h> |
| 42 | #include <linux/nsproxy.h> | 42 | #include <linux/nsproxy.h> |
| 43 | #include <linux/slab.h> | ||
| 43 | #include <net/net_namespace.h> | 44 | #include <net/net_namespace.h> |
| 44 | #include <net/snmp.h> | 45 | #include <net/snmp.h> |
| 45 | #include <net/ipv6.h> | 46 | #include <net/ipv6.h> |
| @@ -125,16 +126,14 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
| 125 | }; | 126 | }; |
| 126 | 127 | ||
| 127 | static struct rt6_info ip6_null_entry_template = { | 128 | static struct rt6_info ip6_null_entry_template = { |
| 128 | .u = { | 129 | .dst = { |
| 129 | .dst = { | 130 | .__refcnt = ATOMIC_INIT(1), |
| 130 | .__refcnt = ATOMIC_INIT(1), | 131 | .__use = 1, |
| 131 | .__use = 1, | 132 | .obsolete = -1, |
| 132 | .obsolete = -1, | 133 | .error = -ENETUNREACH, |
| 133 | .error = -ENETUNREACH, | 134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 135 | .input = ip6_pkt_discard, |
| 135 | .input = ip6_pkt_discard, | 136 | .output = ip6_pkt_discard_out, |
| 136 | .output = ip6_pkt_discard_out, | ||
| 137 | } | ||
| 138 | }, | 137 | }, |
| 139 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 138 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 140 | .rt6i_protocol = RTPROT_KERNEL, | 139 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -148,16 +147,14 @@ static int ip6_pkt_prohibit(struct sk_buff *skb); | |||
| 148 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 147 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
| 149 | 148 | ||
| 150 | static struct rt6_info ip6_prohibit_entry_template = { | 149 | static struct rt6_info ip6_prohibit_entry_template = { |
| 151 | .u = { | 150 | .dst = { |
| 152 | .dst = { | 151 | .__refcnt = ATOMIC_INIT(1), |
| 153 | .__refcnt = ATOMIC_INIT(1), | 152 | .__use = 1, |
| 154 | .__use = 1, | 153 | .obsolete = -1, |
| 155 | .obsolete = -1, | 154 | .error = -EACCES, |
| 156 | .error = -EACCES, | 155 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 157 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 156 | .input = ip6_pkt_prohibit, |
| 158 | .input = ip6_pkt_prohibit, | 157 | .output = ip6_pkt_prohibit_out, |
| 159 | .output = ip6_pkt_prohibit_out, | ||
| 160 | } | ||
| 161 | }, | 158 | }, |
| 162 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 159 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 163 | .rt6i_protocol = RTPROT_KERNEL, | 160 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -166,16 +163,14 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
| 166 | }; | 163 | }; |
| 167 | 164 | ||
| 168 | static struct rt6_info ip6_blk_hole_entry_template = { | 165 | static struct rt6_info ip6_blk_hole_entry_template = { |
| 169 | .u = { | 166 | .dst = { |
| 170 | .dst = { | 167 | .__refcnt = ATOMIC_INIT(1), |
| 171 | .__refcnt = ATOMIC_INIT(1), | 168 | .__use = 1, |
| 172 | .__use = 1, | 169 | .obsolete = -1, |
| 173 | .obsolete = -1, | 170 | .error = -EINVAL, |
| 174 | .error = -EINVAL, | 171 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 175 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 172 | .input = dst_discard, |
| 176 | .input = dst_discard, | 173 | .output = dst_discard, |
| 177 | .output = dst_discard, | ||
| 178 | } | ||
| 179 | }, | 174 | }, |
| 180 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 175 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 181 | .rt6i_protocol = RTPROT_KERNEL, | 176 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -248,7 +243,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
| 248 | if (!oif && ipv6_addr_any(saddr)) | 243 | if (!oif && ipv6_addr_any(saddr)) |
| 249 | goto out; | 244 | goto out; |
| 250 | 245 | ||
| 251 | for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { | 246 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { |
| 252 | struct net_device *dev = sprt->rt6i_dev; | 247 | struct net_device *dev = sprt->rt6i_dev; |
| 253 | 248 | ||
| 254 | if (oif) { | 249 | if (oif) { |
| @@ -315,7 +310,6 @@ static void rt6_probe(struct rt6_info *rt) | |||
| 315 | #else | 310 | #else |
| 316 | static inline void rt6_probe(struct rt6_info *rt) | 311 | static inline void rt6_probe(struct rt6_info *rt) |
| 317 | { | 312 | { |
| 318 | return; | ||
| 319 | } | 313 | } |
| 320 | #endif | 314 | #endif |
| 321 | 315 | ||
| @@ -407,10 +401,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, | |||
| 407 | 401 | ||
| 408 | match = NULL; | 402 | match = NULL; |
| 409 | for (rt = rr_head; rt && rt->rt6i_metric == metric; | 403 | for (rt = rr_head; rt && rt->rt6i_metric == metric; |
| 410 | rt = rt->u.dst.rt6_next) | 404 | rt = rt->dst.rt6_next) |
| 411 | match = find_match(rt, oif, strict, &mpri, match); | 405 | match = find_match(rt, oif, strict, &mpri, match); |
| 412 | for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; | 406 | for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; |
| 413 | rt = rt->u.dst.rt6_next) | 407 | rt = rt->dst.rt6_next) |
| 414 | match = find_match(rt, oif, strict, &mpri, match); | 408 | match = find_match(rt, oif, strict, &mpri, match); |
| 415 | 409 | ||
| 416 | return match; | 410 | return match; |
| @@ -432,7 +426,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
| 432 | 426 | ||
| 433 | if (!match && | 427 | if (!match && |
| 434 | (strict & RT6_LOOKUP_F_REACHABLE)) { | 428 | (strict & RT6_LOOKUP_F_REACHABLE)) { |
| 435 | struct rt6_info *next = rt0->u.dst.rt6_next; | 429 | struct rt6_info *next = rt0->dst.rt6_next; |
| 436 | 430 | ||
| 437 | /* no entries matched; do round-robin */ | 431 | /* no entries matched; do round-robin */ |
| 438 | if (!next || next->rt6i_metric != rt0->rt6i_metric) | 432 | if (!next || next->rt6i_metric != rt0->rt6i_metric) |
| @@ -517,7 +511,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
| 517 | rt->rt6i_expires = jiffies + HZ * lifetime; | 511 | rt->rt6i_expires = jiffies + HZ * lifetime; |
| 518 | rt->rt6i_flags |= RTF_EXPIRES; | 512 | rt->rt6i_flags |= RTF_EXPIRES; |
| 519 | } | 513 | } |
| 520 | dst_release(&rt->u.dst); | 514 | dst_release(&rt->dst); |
| 521 | } | 515 | } |
| 522 | return 0; | 516 | return 0; |
| 523 | } | 517 | } |
| @@ -555,7 +549,7 @@ restart: | |||
| 555 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); | 549 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); |
| 556 | BACKTRACK(net, &fl->fl6_src); | 550 | BACKTRACK(net, &fl->fl6_src); |
| 557 | out: | 551 | out: |
| 558 | dst_use(&rt->u.dst, jiffies); | 552 | dst_use(&rt->dst, jiffies); |
| 559 | read_unlock_bh(&table->tb6_lock); | 553 | read_unlock_bh(&table->tb6_lock); |
| 560 | return rt; | 554 | return rt; |
| 561 | 555 | ||
| @@ -643,7 +637,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
| 643 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 637 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); |
| 644 | rt->rt6i_dst.plen = 128; | 638 | rt->rt6i_dst.plen = 128; |
| 645 | rt->rt6i_flags |= RTF_CACHE; | 639 | rt->rt6i_flags |= RTF_CACHE; |
| 646 | rt->u.dst.flags |= DST_HOST; | 640 | rt->dst.flags |= DST_HOST; |
| 647 | 641 | ||
| 648 | #ifdef CONFIG_IPV6_SUBTREES | 642 | #ifdef CONFIG_IPV6_SUBTREES |
| 649 | if (rt->rt6i_src.plen && saddr) { | 643 | if (rt->rt6i_src.plen && saddr) { |
| @@ -676,8 +670,8 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
| 676 | 670 | ||
| 677 | if (net_ratelimit()) | 671 | if (net_ratelimit()) |
| 678 | printk(KERN_WARNING | 672 | printk(KERN_WARNING |
| 679 | "Neighbour table overflow.\n"); | 673 | "ipv6: Neighbour table overflow.\n"); |
| 680 | dst_free(&rt->u.dst); | 674 | dst_free(&rt->dst); |
| 681 | return NULL; | 675 | return NULL; |
| 682 | } | 676 | } |
| 683 | rt->rt6i_nexthop = neigh; | 677 | rt->rt6i_nexthop = neigh; |
| @@ -694,7 +688,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
| 694 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 688 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); |
| 695 | rt->rt6i_dst.plen = 128; | 689 | rt->rt6i_dst.plen = 128; |
| 696 | rt->rt6i_flags |= RTF_CACHE; | 690 | rt->rt6i_flags |= RTF_CACHE; |
| 697 | rt->u.dst.flags |= DST_HOST; | 691 | rt->dst.flags |= DST_HOST; |
| 698 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); | 692 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); |
| 699 | } | 693 | } |
| 700 | return rt; | 694 | return rt; |
| @@ -726,7 +720,7 @@ restart: | |||
| 726 | rt->rt6i_flags & RTF_CACHE) | 720 | rt->rt6i_flags & RTF_CACHE) |
| 727 | goto out; | 721 | goto out; |
| 728 | 722 | ||
| 729 | dst_hold(&rt->u.dst); | 723 | dst_hold(&rt->dst); |
| 730 | read_unlock_bh(&table->tb6_lock); | 724 | read_unlock_bh(&table->tb6_lock); |
| 731 | 725 | ||
| 732 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 726 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
| @@ -739,10 +733,10 @@ restart: | |||
| 739 | #endif | 733 | #endif |
| 740 | } | 734 | } |
| 741 | 735 | ||
| 742 | dst_release(&rt->u.dst); | 736 | dst_release(&rt->dst); |
| 743 | rt = nrt ? : net->ipv6.ip6_null_entry; | 737 | rt = nrt ? : net->ipv6.ip6_null_entry; |
| 744 | 738 | ||
| 745 | dst_hold(&rt->u.dst); | 739 | dst_hold(&rt->dst); |
| 746 | if (nrt) { | 740 | if (nrt) { |
| 747 | err = ip6_ins_rt(nrt); | 741 | err = ip6_ins_rt(nrt); |
| 748 | if (!err) | 742 | if (!err) |
| @@ -756,7 +750,7 @@ restart: | |||
| 756 | * Race condition! In the gap, when table->tb6_lock was | 750 | * Race condition! In the gap, when table->tb6_lock was |
| 757 | * released someone could insert this route. Relookup. | 751 | * released someone could insert this route. Relookup. |
| 758 | */ | 752 | */ |
| 759 | dst_release(&rt->u.dst); | 753 | dst_release(&rt->dst); |
| 760 | goto relookup; | 754 | goto relookup; |
| 761 | 755 | ||
| 762 | out: | 756 | out: |
| @@ -764,11 +758,11 @@ out: | |||
| 764 | reachable = 0; | 758 | reachable = 0; |
| 765 | goto restart_2; | 759 | goto restart_2; |
| 766 | } | 760 | } |
| 767 | dst_hold(&rt->u.dst); | 761 | dst_hold(&rt->dst); |
| 768 | read_unlock_bh(&table->tb6_lock); | 762 | read_unlock_bh(&table->tb6_lock); |
| 769 | out2: | 763 | out2: |
| 770 | rt->u.dst.lastuse = jiffies; | 764 | rt->dst.lastuse = jiffies; |
| 771 | rt->u.dst.__use++; | 765 | rt->dst.__use++; |
| 772 | 766 | ||
| 773 | return rt; | 767 | return rt; |
| 774 | } | 768 | } |
| @@ -814,20 +808,13 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
| 814 | { | 808 | { |
| 815 | int flags = 0; | 809 | int flags = 0; |
| 816 | 810 | ||
| 817 | if (rt6_need_strict(&fl->fl6_dst)) | 811 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst)) |
| 818 | flags |= RT6_LOOKUP_F_IFACE; | 812 | flags |= RT6_LOOKUP_F_IFACE; |
| 819 | 813 | ||
| 820 | if (!ipv6_addr_any(&fl->fl6_src)) | 814 | if (!ipv6_addr_any(&fl->fl6_src)) |
| 821 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 815 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
| 822 | else if (sk) { | 816 | else if (sk) |
| 823 | unsigned int prefs = inet6_sk(sk)->srcprefs; | 817 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
| 824 | if (prefs & IPV6_PREFER_SRC_TMP) | ||
| 825 | flags |= RT6_LOOKUP_F_SRCPREF_TMP; | ||
| 826 | if (prefs & IPV6_PREFER_SRC_PUBLIC) | ||
| 827 | flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; | ||
| 828 | if (prefs & IPV6_PREFER_SRC_COA) | ||
| 829 | flags |= RT6_LOOKUP_F_SRCPREF_COA; | ||
| 830 | } | ||
| 831 | 818 | ||
| 832 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); | 819 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
| 833 | } | 820 | } |
| @@ -842,15 +829,15 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
| 842 | struct dst_entry *new = NULL; | 829 | struct dst_entry *new = NULL; |
| 843 | 830 | ||
| 844 | if (rt) { | 831 | if (rt) { |
| 845 | new = &rt->u.dst; | 832 | new = &rt->dst; |
| 846 | 833 | ||
| 847 | atomic_set(&new->__refcnt, 1); | 834 | atomic_set(&new->__refcnt, 1); |
| 848 | new->__use = 1; | 835 | new->__use = 1; |
| 849 | new->input = dst_discard; | 836 | new->input = dst_discard; |
| 850 | new->output = dst_discard; | 837 | new->output = dst_discard; |
| 851 | 838 | ||
| 852 | memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 839 | memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
| 853 | new->dev = ort->u.dst.dev; | 840 | new->dev = ort->dst.dev; |
| 854 | if (new->dev) | 841 | if (new->dev) |
| 855 | dev_hold(new->dev); | 842 | dev_hold(new->dev); |
| 856 | rt->rt6i_idev = ort->rt6i_idev; | 843 | rt->rt6i_idev = ort->rt6i_idev; |
| @@ -886,7 +873,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
| 886 | 873 | ||
| 887 | rt = (struct rt6_info *) dst; | 874 | rt = (struct rt6_info *) dst; |
| 888 | 875 | ||
| 889 | if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 876 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) |
| 890 | return dst; | 877 | return dst; |
| 891 | 878 | ||
| 892 | return NULL; | 879 | return NULL; |
| @@ -897,24 +884,29 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) | |||
| 897 | struct rt6_info *rt = (struct rt6_info *) dst; | 884 | struct rt6_info *rt = (struct rt6_info *) dst; |
| 898 | 885 | ||
| 899 | if (rt) { | 886 | if (rt) { |
| 900 | if (rt->rt6i_flags & RTF_CACHE) | 887 | if (rt->rt6i_flags & RTF_CACHE) { |
| 901 | ip6_del_rt(rt); | 888 | if (rt6_check_expired(rt)) { |
| 902 | else | 889 | ip6_del_rt(rt); |
| 890 | dst = NULL; | ||
| 891 | } | ||
| 892 | } else { | ||
| 903 | dst_release(dst); | 893 | dst_release(dst); |
| 894 | dst = NULL; | ||
| 895 | } | ||
| 904 | } | 896 | } |
| 905 | return NULL; | 897 | return dst; |
| 906 | } | 898 | } |
| 907 | 899 | ||
| 908 | static void ip6_link_failure(struct sk_buff *skb) | 900 | static void ip6_link_failure(struct sk_buff *skb) |
| 909 | { | 901 | { |
| 910 | struct rt6_info *rt; | 902 | struct rt6_info *rt; |
| 911 | 903 | ||
| 912 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); | 904 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); |
| 913 | 905 | ||
| 914 | rt = (struct rt6_info *) skb_dst(skb); | 906 | rt = (struct rt6_info *) skb_dst(skb); |
| 915 | if (rt) { | 907 | if (rt) { |
| 916 | if (rt->rt6i_flags&RTF_CACHE) { | 908 | if (rt->rt6i_flags&RTF_CACHE) { |
| 917 | dst_set_expires(&rt->u.dst, 0); | 909 | dst_set_expires(&rt->dst, 0); |
| 918 | rt->rt6i_flags |= RTF_EXPIRES; | 910 | rt->rt6i_flags |= RTF_EXPIRES; |
| 919 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | 911 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
| 920 | rt->rt6i_node->fn_sernum = -1; | 912 | rt->rt6i_node->fn_sernum = -1; |
| @@ -988,14 +980,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
| 988 | rt->rt6i_dev = dev; | 980 | rt->rt6i_dev = dev; |
| 989 | rt->rt6i_idev = idev; | 981 | rt->rt6i_idev = idev; |
| 990 | rt->rt6i_nexthop = neigh; | 982 | rt->rt6i_nexthop = neigh; |
| 991 | atomic_set(&rt->u.dst.__refcnt, 1); | 983 | atomic_set(&rt->dst.__refcnt, 1); |
| 992 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 984 | rt->dst.metrics[RTAX_HOPLIMIT-1] = 255; |
| 993 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 985 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
| 994 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 986 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 995 | rt->u.dst.output = ip6_output; | 987 | rt->dst.output = ip6_output; |
| 996 | 988 | ||
| 997 | #if 0 /* there's no chance to use these for ndisc */ | 989 | #if 0 /* there's no chance to use these for ndisc */ |
| 998 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 990 | rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
| 999 | ? DST_HOST | 991 | ? DST_HOST |
| 1000 | : 0; | 992 | : 0; |
| 1001 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 993 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
| @@ -1003,14 +995,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
| 1003 | #endif | 995 | #endif |
| 1004 | 996 | ||
| 1005 | spin_lock_bh(&icmp6_dst_lock); | 997 | spin_lock_bh(&icmp6_dst_lock); |
| 1006 | rt->u.dst.next = icmp6_dst_gc_list; | 998 | rt->dst.next = icmp6_dst_gc_list; |
| 1007 | icmp6_dst_gc_list = &rt->u.dst; | 999 | icmp6_dst_gc_list = &rt->dst; |
| 1008 | spin_unlock_bh(&icmp6_dst_lock); | 1000 | spin_unlock_bh(&icmp6_dst_lock); |
| 1009 | 1001 | ||
| 1010 | fib6_force_start_gc(net); | 1002 | fib6_force_start_gc(net); |
| 1011 | 1003 | ||
| 1012 | out: | 1004 | out: |
| 1013 | return &rt->u.dst; | 1005 | return &rt->dst; |
| 1014 | } | 1006 | } |
| 1015 | 1007 | ||
| 1016 | int icmp6_dst_gc(void) | 1008 | int icmp6_dst_gc(void) |
| @@ -1092,11 +1084,11 @@ static int ipv6_get_mtu(struct net_device *dev) | |||
| 1092 | int mtu = IPV6_MIN_MTU; | 1084 | int mtu = IPV6_MIN_MTU; |
| 1093 | struct inet6_dev *idev; | 1085 | struct inet6_dev *idev; |
| 1094 | 1086 | ||
| 1095 | idev = in6_dev_get(dev); | 1087 | rcu_read_lock(); |
| 1096 | if (idev) { | 1088 | idev = __in6_dev_get(dev); |
| 1089 | if (idev) | ||
| 1097 | mtu = idev->cnf.mtu6; | 1090 | mtu = idev->cnf.mtu6; |
| 1098 | in6_dev_put(idev); | 1091 | rcu_read_unlock(); |
| 1099 | } | ||
| 1100 | return mtu; | 1092 | return mtu; |
| 1101 | } | 1093 | } |
| 1102 | 1094 | ||
| @@ -1105,12 +1097,15 @@ int ip6_dst_hoplimit(struct dst_entry *dst) | |||
| 1105 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); | 1097 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); |
| 1106 | if (hoplimit < 0) { | 1098 | if (hoplimit < 0) { |
| 1107 | struct net_device *dev = dst->dev; | 1099 | struct net_device *dev = dst->dev; |
| 1108 | struct inet6_dev *idev = in6_dev_get(dev); | 1100 | struct inet6_dev *idev; |
| 1109 | if (idev) { | 1101 | |
| 1102 | rcu_read_lock(); | ||
| 1103 | idev = __in6_dev_get(dev); | ||
| 1104 | if (idev) | ||
| 1110 | hoplimit = idev->cnf.hop_limit; | 1105 | hoplimit = idev->cnf.hop_limit; |
| 1111 | in6_dev_put(idev); | 1106 | else |
| 1112 | } else | ||
| 1113 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; | 1107 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; |
| 1108 | rcu_read_unlock(); | ||
| 1114 | } | 1109 | } |
| 1115 | return hoplimit; | 1110 | return hoplimit; |
| 1116 | } | 1111 | } |
| @@ -1161,7 +1156,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1161 | goto out; | 1156 | goto out; |
| 1162 | } | 1157 | } |
| 1163 | 1158 | ||
| 1164 | rt->u.dst.obsolete = -1; | 1159 | rt->dst.obsolete = -1; |
| 1165 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1160 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? |
| 1166 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1161 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : |
| 1167 | 0; | 1162 | 0; |
| @@ -1173,16 +1168,16 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1173 | addr_type = ipv6_addr_type(&cfg->fc_dst); | 1168 | addr_type = ipv6_addr_type(&cfg->fc_dst); |
| 1174 | 1169 | ||
| 1175 | if (addr_type & IPV6_ADDR_MULTICAST) | 1170 | if (addr_type & IPV6_ADDR_MULTICAST) |
| 1176 | rt->u.dst.input = ip6_mc_input; | 1171 | rt->dst.input = ip6_mc_input; |
| 1177 | else | 1172 | else |
| 1178 | rt->u.dst.input = ip6_forward; | 1173 | rt->dst.input = ip6_forward; |
| 1179 | 1174 | ||
| 1180 | rt->u.dst.output = ip6_output; | 1175 | rt->dst.output = ip6_output; |
| 1181 | 1176 | ||
| 1182 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); | 1177 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); |
| 1183 | rt->rt6i_dst.plen = cfg->fc_dst_len; | 1178 | rt->rt6i_dst.plen = cfg->fc_dst_len; |
| 1184 | if (rt->rt6i_dst.plen == 128) | 1179 | if (rt->rt6i_dst.plen == 128) |
| 1185 | rt->u.dst.flags = DST_HOST; | 1180 | rt->dst.flags = DST_HOST; |
| 1186 | 1181 | ||
| 1187 | #ifdef CONFIG_IPV6_SUBTREES | 1182 | #ifdef CONFIG_IPV6_SUBTREES |
| 1188 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1183 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
| @@ -1210,9 +1205,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1210 | goto out; | 1205 | goto out; |
| 1211 | } | 1206 | } |
| 1212 | } | 1207 | } |
| 1213 | rt->u.dst.output = ip6_pkt_discard_out; | 1208 | rt->dst.output = ip6_pkt_discard_out; |
| 1214 | rt->u.dst.input = ip6_pkt_discard; | 1209 | rt->dst.input = ip6_pkt_discard; |
| 1215 | rt->u.dst.error = -ENETUNREACH; | 1210 | rt->dst.error = -ENETUNREACH; |
| 1216 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; | 1211 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; |
| 1217 | goto install_route; | 1212 | goto install_route; |
| 1218 | } | 1213 | } |
| @@ -1246,7 +1241,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1246 | goto out; | 1241 | goto out; |
| 1247 | if (dev) { | 1242 | if (dev) { |
| 1248 | if (dev != grt->rt6i_dev) { | 1243 | if (dev != grt->rt6i_dev) { |
| 1249 | dst_release(&grt->u.dst); | 1244 | dst_release(&grt->dst); |
| 1250 | goto out; | 1245 | goto out; |
| 1251 | } | 1246 | } |
| 1252 | } else { | 1247 | } else { |
| @@ -1257,7 +1252,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1257 | } | 1252 | } |
| 1258 | if (!(grt->rt6i_flags&RTF_GATEWAY)) | 1253 | if (!(grt->rt6i_flags&RTF_GATEWAY)) |
| 1259 | err = 0; | 1254 | err = 0; |
| 1260 | dst_release(&grt->u.dst); | 1255 | dst_release(&grt->dst); |
| 1261 | 1256 | ||
| 1262 | if (err) | 1257 | if (err) |
| 1263 | goto out; | 1258 | goto out; |
| @@ -1296,18 +1291,18 @@ install_route: | |||
| 1296 | goto out; | 1291 | goto out; |
| 1297 | } | 1292 | } |
| 1298 | 1293 | ||
| 1299 | rt->u.dst.metrics[type - 1] = nla_get_u32(nla); | 1294 | rt->dst.metrics[type - 1] = nla_get_u32(nla); |
| 1300 | } | 1295 | } |
| 1301 | } | 1296 | } |
| 1302 | } | 1297 | } |
| 1303 | 1298 | ||
| 1304 | if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0) | 1299 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) |
| 1305 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1300 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
| 1306 | if (!dst_mtu(&rt->u.dst)) | 1301 | if (!dst_mtu(&rt->dst)) |
| 1307 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1302 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
| 1308 | if (!dst_metric(&rt->u.dst, RTAX_ADVMSS)) | 1303 | if (!dst_metric(&rt->dst, RTAX_ADVMSS)) |
| 1309 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 1304 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 1310 | rt->u.dst.dev = dev; | 1305 | rt->dst.dev = dev; |
| 1311 | rt->rt6i_idev = idev; | 1306 | rt->rt6i_idev = idev; |
| 1312 | rt->rt6i_table = table; | 1307 | rt->rt6i_table = table; |
| 1313 | 1308 | ||
| @@ -1321,7 +1316,7 @@ out: | |||
| 1321 | if (idev) | 1316 | if (idev) |
| 1322 | in6_dev_put(idev); | 1317 | in6_dev_put(idev); |
| 1323 | if (rt) | 1318 | if (rt) |
| 1324 | dst_free(&rt->u.dst); | 1319 | dst_free(&rt->dst); |
| 1325 | return err; | 1320 | return err; |
| 1326 | } | 1321 | } |
| 1327 | 1322 | ||
| @@ -1338,7 +1333,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
| 1338 | write_lock_bh(&table->tb6_lock); | 1333 | write_lock_bh(&table->tb6_lock); |
| 1339 | 1334 | ||
| 1340 | err = fib6_del(rt, info); | 1335 | err = fib6_del(rt, info); |
| 1341 | dst_release(&rt->u.dst); | 1336 | dst_release(&rt->dst); |
| 1342 | 1337 | ||
| 1343 | write_unlock_bh(&table->tb6_lock); | 1338 | write_unlock_bh(&table->tb6_lock); |
| 1344 | 1339 | ||
| @@ -1371,7 +1366,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
| 1371 | &cfg->fc_src, cfg->fc_src_len); | 1366 | &cfg->fc_src, cfg->fc_src_len); |
| 1372 | 1367 | ||
| 1373 | if (fn) { | 1368 | if (fn) { |
| 1374 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1369 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1375 | if (cfg->fc_ifindex && | 1370 | if (cfg->fc_ifindex && |
| 1376 | (rt->rt6i_dev == NULL || | 1371 | (rt->rt6i_dev == NULL || |
| 1377 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) | 1372 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) |
| @@ -1381,7 +1376,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
| 1381 | continue; | 1376 | continue; |
| 1382 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) | 1377 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) |
| 1383 | continue; | 1378 | continue; |
| 1384 | dst_hold(&rt->u.dst); | 1379 | dst_hold(&rt->dst); |
| 1385 | read_unlock_bh(&table->tb6_lock); | 1380 | read_unlock_bh(&table->tb6_lock); |
| 1386 | 1381 | ||
| 1387 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); | 1382 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); |
| @@ -1423,7 +1418,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
| 1423 | read_lock_bh(&table->tb6_lock); | 1418 | read_lock_bh(&table->tb6_lock); |
| 1424 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 1419 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
| 1425 | restart: | 1420 | restart: |
| 1426 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1421 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1427 | /* | 1422 | /* |
| 1428 | * Current route is on-link; redirect is always invalid. | 1423 | * Current route is on-link; redirect is always invalid. |
| 1429 | * | 1424 | * |
| @@ -1447,7 +1442,7 @@ restart: | |||
| 1447 | rt = net->ipv6.ip6_null_entry; | 1442 | rt = net->ipv6.ip6_null_entry; |
| 1448 | BACKTRACK(net, &fl->fl6_src); | 1443 | BACKTRACK(net, &fl->fl6_src); |
| 1449 | out: | 1444 | out: |
| 1450 | dst_hold(&rt->u.dst); | 1445 | dst_hold(&rt->dst); |
| 1451 | 1446 | ||
| 1452 | read_unlock_bh(&table->tb6_lock); | 1447 | read_unlock_bh(&table->tb6_lock); |
| 1453 | 1448 | ||
| @@ -1515,10 +1510,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1515 | * Look, redirects are sent only in response to data packets, | 1510 | * Look, redirects are sent only in response to data packets, |
| 1516 | * so that this nexthop apparently is reachable. --ANK | 1511 | * so that this nexthop apparently is reachable. --ANK |
| 1517 | */ | 1512 | */ |
| 1518 | dst_confirm(&rt->u.dst); | 1513 | dst_confirm(&rt->dst); |
| 1519 | 1514 | ||
| 1520 | /* Duplicate redirect: silently ignore. */ | 1515 | /* Duplicate redirect: silently ignore. */ |
| 1521 | if (neigh == rt->u.dst.neighbour) | 1516 | if (neigh == rt->dst.neighbour) |
| 1522 | goto out; | 1517 | goto out; |
| 1523 | 1518 | ||
| 1524 | nrt = ip6_rt_copy(rt); | 1519 | nrt = ip6_rt_copy(rt); |
| @@ -1531,20 +1526,20 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1531 | 1526 | ||
| 1532 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); | 1527 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); |
| 1533 | nrt->rt6i_dst.plen = 128; | 1528 | nrt->rt6i_dst.plen = 128; |
| 1534 | nrt->u.dst.flags |= DST_HOST; | 1529 | nrt->dst.flags |= DST_HOST; |
| 1535 | 1530 | ||
| 1536 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1531 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
| 1537 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1532 | nrt->rt6i_nexthop = neigh_clone(neigh); |
| 1538 | /* Reset pmtu, it may be better */ | 1533 | /* Reset pmtu, it may be better */ |
| 1539 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1534 | nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); |
| 1540 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), | 1535 | nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), |
| 1541 | dst_mtu(&nrt->u.dst)); | 1536 | dst_mtu(&nrt->dst)); |
| 1542 | 1537 | ||
| 1543 | if (ip6_ins_rt(nrt)) | 1538 | if (ip6_ins_rt(nrt)) |
| 1544 | goto out; | 1539 | goto out; |
| 1545 | 1540 | ||
| 1546 | netevent.old = &rt->u.dst; | 1541 | netevent.old = &rt->dst; |
| 1547 | netevent.new = &nrt->u.dst; | 1542 | netevent.new = &nrt->dst; |
| 1548 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); | 1543 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); |
| 1549 | 1544 | ||
| 1550 | if (rt->rt6i_flags&RTF_CACHE) { | 1545 | if (rt->rt6i_flags&RTF_CACHE) { |
| @@ -1553,8 +1548,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1553 | } | 1548 | } |
| 1554 | 1549 | ||
| 1555 | out: | 1550 | out: |
| 1556 | dst_release(&rt->u.dst); | 1551 | dst_release(&rt->dst); |
| 1557 | return; | ||
| 1558 | } | 1552 | } |
| 1559 | 1553 | ||
| 1560 | /* | 1554 | /* |
| @@ -1562,18 +1556,17 @@ out: | |||
| 1562 | * i.e. Path MTU discovery | 1556 | * i.e. Path MTU discovery |
| 1563 | */ | 1557 | */ |
| 1564 | 1558 | ||
| 1565 | void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | 1559 | static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, |
| 1566 | struct net_device *dev, u32 pmtu) | 1560 | struct net *net, u32 pmtu, int ifindex) |
| 1567 | { | 1561 | { |
| 1568 | struct rt6_info *rt, *nrt; | 1562 | struct rt6_info *rt, *nrt; |
| 1569 | struct net *net = dev_net(dev); | ||
| 1570 | int allfrag = 0; | 1563 | int allfrag = 0; |
| 1571 | 1564 | ||
| 1572 | rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); | 1565 | rt = rt6_lookup(net, daddr, saddr, ifindex, 0); |
| 1573 | if (rt == NULL) | 1566 | if (rt == NULL) |
| 1574 | return; | 1567 | return; |
| 1575 | 1568 | ||
| 1576 | if (pmtu >= dst_mtu(&rt->u.dst)) | 1569 | if (pmtu >= dst_mtu(&rt->dst)) |
| 1577 | goto out; | 1570 | goto out; |
| 1578 | 1571 | ||
| 1579 | if (pmtu < IPV6_MIN_MTU) { | 1572 | if (pmtu < IPV6_MIN_MTU) { |
| @@ -1591,7 +1584,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1591 | They are sent only in response to data packets, | 1584 | They are sent only in response to data packets, |
| 1592 | so that this nexthop apparently is reachable. --ANK | 1585 | so that this nexthop apparently is reachable. --ANK |
| 1593 | */ | 1586 | */ |
| 1594 | dst_confirm(&rt->u.dst); | 1587 | dst_confirm(&rt->dst); |
| 1595 | 1588 | ||
| 1596 | /* Host route. If it is static, it would be better | 1589 | /* Host route. If it is static, it would be better |
| 1597 | not to override it, but add new one, so that | 1590 | not to override it, but add new one, so that |
| @@ -1599,10 +1592,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1599 | would return automatically. | 1592 | would return automatically. |
| 1600 | */ | 1593 | */ |
| 1601 | if (rt->rt6i_flags & RTF_CACHE) { | 1594 | if (rt->rt6i_flags & RTF_CACHE) { |
| 1602 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1595 | rt->dst.metrics[RTAX_MTU-1] = pmtu; |
| 1603 | if (allfrag) | 1596 | if (allfrag) |
| 1604 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1597 | rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
| 1605 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1598 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1606 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1599 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
| 1607 | goto out; | 1600 | goto out; |
| 1608 | } | 1601 | } |
| @@ -1618,9 +1611,9 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1618 | nrt = rt6_alloc_clone(rt, daddr); | 1611 | nrt = rt6_alloc_clone(rt, daddr); |
| 1619 | 1612 | ||
| 1620 | if (nrt) { | 1613 | if (nrt) { |
| 1621 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1614 | nrt->dst.metrics[RTAX_MTU-1] = pmtu; |
| 1622 | if (allfrag) | 1615 | if (allfrag) |
| 1623 | nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1616 | nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
| 1624 | 1617 | ||
| 1625 | /* According to RFC 1981, detecting PMTU increase shouldn't be | 1618 | /* According to RFC 1981, detecting PMTU increase shouldn't be |
| 1626 | * happened within 5 mins, the recommended timer is 10 mins. | 1619 | * happened within 5 mins, the recommended timer is 10 mins. |
| @@ -1628,13 +1621,34 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1628 | * which is 10 mins. After 10 mins the decreased pmtu is expired | 1621 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
| 1629 | * and detecting PMTU increase will be automatically happened. | 1622 | * and detecting PMTU increase will be automatically happened. |
| 1630 | */ | 1623 | */ |
| 1631 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1624 | dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1632 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1625 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
| 1633 | 1626 | ||
| 1634 | ip6_ins_rt(nrt); | 1627 | ip6_ins_rt(nrt); |
| 1635 | } | 1628 | } |
| 1636 | out: | 1629 | out: |
| 1637 | dst_release(&rt->u.dst); | 1630 | dst_release(&rt->dst); |
| 1631 | } | ||
| 1632 | |||
| 1633 | void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | ||
| 1634 | struct net_device *dev, u32 pmtu) | ||
| 1635 | { | ||
| 1636 | struct net *net = dev_net(dev); | ||
| 1637 | |||
| 1638 | /* | ||
| 1639 | * RFC 1981 states that a node "MUST reduce the size of the packets it | ||
| 1640 | * is sending along the path" that caused the Packet Too Big message. | ||
| 1641 | * Since it's not possible in the general case to determine which | ||
| 1642 | * interface was used to send the original packet, we update the MTU | ||
| 1643 | * on the interface that will be used to send future packets. We also | ||
| 1644 | * update the MTU on the interface that received the Packet Too Big in | ||
| 1645 | * case the original packet was forced out that interface with | ||
| 1646 | * SO_BINDTODEVICE or similar. This is the next best thing to the | ||
| 1647 | * correct behaviour, which would be to update the MTU on all | ||
| 1648 | * interfaces. | ||
| 1649 | */ | ||
| 1650 | rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0); | ||
| 1651 | rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex); | ||
| 1638 | } | 1652 | } |
| 1639 | 1653 | ||
| 1640 | /* | 1654 | /* |
| @@ -1647,18 +1661,18 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
| 1647 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1661 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); |
| 1648 | 1662 | ||
| 1649 | if (rt) { | 1663 | if (rt) { |
| 1650 | rt->u.dst.input = ort->u.dst.input; | 1664 | rt->dst.input = ort->dst.input; |
| 1651 | rt->u.dst.output = ort->u.dst.output; | 1665 | rt->dst.output = ort->dst.output; |
| 1652 | 1666 | ||
| 1653 | memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 1667 | memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
| 1654 | rt->u.dst.error = ort->u.dst.error; | 1668 | rt->dst.error = ort->dst.error; |
| 1655 | rt->u.dst.dev = ort->u.dst.dev; | 1669 | rt->dst.dev = ort->dst.dev; |
| 1656 | if (rt->u.dst.dev) | 1670 | if (rt->dst.dev) |
| 1657 | dev_hold(rt->u.dst.dev); | 1671 | dev_hold(rt->dst.dev); |
| 1658 | rt->rt6i_idev = ort->rt6i_idev; | 1672 | rt->rt6i_idev = ort->rt6i_idev; |
| 1659 | if (rt->rt6i_idev) | 1673 | if (rt->rt6i_idev) |
| 1660 | in6_dev_hold(rt->rt6i_idev); | 1674 | in6_dev_hold(rt->rt6i_idev); |
| 1661 | rt->u.dst.lastuse = jiffies; | 1675 | rt->dst.lastuse = jiffies; |
| 1662 | rt->rt6i_expires = 0; | 1676 | rt->rt6i_expires = 0; |
| 1663 | 1677 | ||
| 1664 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 1678 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); |
| @@ -1692,14 +1706,14 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
| 1692 | if (!fn) | 1706 | if (!fn) |
| 1693 | goto out; | 1707 | goto out; |
| 1694 | 1708 | ||
| 1695 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1709 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1696 | if (rt->rt6i_dev->ifindex != ifindex) | 1710 | if (rt->rt6i_dev->ifindex != ifindex) |
| 1697 | continue; | 1711 | continue; |
| 1698 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) | 1712 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) |
| 1699 | continue; | 1713 | continue; |
| 1700 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) | 1714 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) |
| 1701 | continue; | 1715 | continue; |
| 1702 | dst_hold(&rt->u.dst); | 1716 | dst_hold(&rt->dst); |
| 1703 | break; | 1717 | break; |
| 1704 | } | 1718 | } |
| 1705 | out: | 1719 | out: |
| @@ -1747,14 +1761,14 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
| 1747 | return NULL; | 1761 | return NULL; |
| 1748 | 1762 | ||
| 1749 | write_lock_bh(&table->tb6_lock); | 1763 | write_lock_bh(&table->tb6_lock); |
| 1750 | for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) { | 1764 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
| 1751 | if (dev == rt->rt6i_dev && | 1765 | if (dev == rt->rt6i_dev && |
| 1752 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1766 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
| 1753 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) | 1767 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) |
| 1754 | break; | 1768 | break; |
| 1755 | } | 1769 | } |
| 1756 | if (rt) | 1770 | if (rt) |
| 1757 | dst_hold(&rt->u.dst); | 1771 | dst_hold(&rt->dst); |
| 1758 | write_unlock_bh(&table->tb6_lock); | 1772 | write_unlock_bh(&table->tb6_lock); |
| 1759 | return rt; | 1773 | return rt; |
| 1760 | } | 1774 | } |
| @@ -1793,9 +1807,9 @@ void rt6_purge_dflt_routers(struct net *net) | |||
| 1793 | 1807 | ||
| 1794 | restart: | 1808 | restart: |
| 1795 | read_lock_bh(&table->tb6_lock); | 1809 | read_lock_bh(&table->tb6_lock); |
| 1796 | for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) { | 1810 | for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { |
| 1797 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { | 1811 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { |
| 1798 | dst_hold(&rt->u.dst); | 1812 | dst_hold(&rt->dst); |
| 1799 | read_unlock_bh(&table->tb6_lock); | 1813 | read_unlock_bh(&table->tb6_lock); |
| 1800 | ip6_del_rt(rt); | 1814 | ip6_del_rt(rt); |
| 1801 | goto restart; | 1815 | goto restart; |
| @@ -1873,7 +1887,7 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) | |||
| 1873 | switch (ipstats_mib_noroutes) { | 1887 | switch (ipstats_mib_noroutes) { |
| 1874 | case IPSTATS_MIB_INNOROUTES: | 1888 | case IPSTATS_MIB_INNOROUTES: |
| 1875 | type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); | 1889 | type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); |
| 1876 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { | 1890 | if (type == IPV6_ADDR_ANY) { |
| 1877 | IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst), | 1891 | IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst), |
| 1878 | IPSTATS_MIB_INADDRERRORS); | 1892 | IPSTATS_MIB_INADDRERRORS); |
| 1879 | break; | 1893 | break; |
| @@ -1884,7 +1898,7 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) | |||
| 1884 | ipstats_mib_noroutes); | 1898 | ipstats_mib_noroutes); |
| 1885 | break; | 1899 | break; |
| 1886 | } | 1900 | } |
| 1887 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); | 1901 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0); |
| 1888 | kfree_skb(skb); | 1902 | kfree_skb(skb); |
| 1889 | return 0; | 1903 | return 0; |
| 1890 | } | 1904 | } |
| @@ -1933,15 +1947,15 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1933 | dev_hold(net->loopback_dev); | 1947 | dev_hold(net->loopback_dev); |
| 1934 | in6_dev_hold(idev); | 1948 | in6_dev_hold(idev); |
| 1935 | 1949 | ||
| 1936 | rt->u.dst.flags = DST_HOST; | 1950 | rt->dst.flags = DST_HOST; |
| 1937 | rt->u.dst.input = ip6_input; | 1951 | rt->dst.input = ip6_input; |
| 1938 | rt->u.dst.output = ip6_output; | 1952 | rt->dst.output = ip6_output; |
| 1939 | rt->rt6i_dev = net->loopback_dev; | 1953 | rt->rt6i_dev = net->loopback_dev; |
| 1940 | rt->rt6i_idev = idev; | 1954 | rt->rt6i_idev = idev; |
| 1941 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1955 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
| 1942 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 1956 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 1943 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1957 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
| 1944 | rt->u.dst.obsolete = -1; | 1958 | rt->dst.obsolete = -1; |
| 1945 | 1959 | ||
| 1946 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 1960 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
| 1947 | if (anycast) | 1961 | if (anycast) |
| @@ -1950,7 +1964,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1950 | rt->rt6i_flags |= RTF_LOCAL; | 1964 | rt->rt6i_flags |= RTF_LOCAL; |
| 1951 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1965 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
| 1952 | if (IS_ERR(neigh)) { | 1966 | if (IS_ERR(neigh)) { |
| 1953 | dst_free(&rt->u.dst); | 1967 | dst_free(&rt->dst); |
| 1954 | 1968 | ||
| 1955 | /* We are casting this because that is the return | 1969 | /* We are casting this because that is the return |
| 1956 | * value type. But an errno encoded pointer is the | 1970 | * value type. But an errno encoded pointer is the |
| @@ -1965,7 +1979,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1965 | rt->rt6i_dst.plen = 128; | 1979 | rt->rt6i_dst.plen = 128; |
| 1966 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 1980 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
| 1967 | 1981 | ||
| 1968 | atomic_set(&rt->u.dst.__refcnt, 1); | 1982 | atomic_set(&rt->dst.__refcnt, 1); |
| 1969 | 1983 | ||
| 1970 | return rt; | 1984 | return rt; |
| 1971 | } | 1985 | } |
| @@ -2036,12 +2050,12 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
| 2036 | PMTU discouvery. | 2050 | PMTU discouvery. |
| 2037 | */ | 2051 | */ |
| 2038 | if (rt->rt6i_dev == arg->dev && | 2052 | if (rt->rt6i_dev == arg->dev && |
| 2039 | !dst_metric_locked(&rt->u.dst, RTAX_MTU) && | 2053 | !dst_metric_locked(&rt->dst, RTAX_MTU) && |
| 2040 | (dst_mtu(&rt->u.dst) >= arg->mtu || | 2054 | (dst_mtu(&rt->dst) >= arg->mtu || |
| 2041 | (dst_mtu(&rt->u.dst) < arg->mtu && | 2055 | (dst_mtu(&rt->dst) < arg->mtu && |
| 2042 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 2056 | dst_mtu(&rt->dst) == idev->cnf.mtu6))) { |
| 2043 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 2057 | rt->dst.metrics[RTAX_MTU-1] = arg->mtu; |
| 2044 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); | 2058 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
| 2045 | } | 2059 | } |
| 2046 | return 0; | 2060 | return 0; |
| 2047 | } | 2061 | } |
| @@ -2255,20 +2269,20 @@ static int rt6_fill_node(struct net *net, | |||
| 2255 | #endif | 2269 | #endif |
| 2256 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2270 | NLA_PUT_U32(skb, RTA_IIF, iif); |
| 2257 | } else if (dst) { | 2271 | } else if (dst) { |
| 2258 | struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst); | 2272 | struct inet6_dev *idev = ip6_dst_idev(&rt->dst); |
| 2259 | struct in6_addr saddr_buf; | 2273 | struct in6_addr saddr_buf; |
| 2260 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2274 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
| 2261 | dst, 0, &saddr_buf) == 0) | 2275 | dst, 0, &saddr_buf) == 0) |
| 2262 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2276 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
| 2263 | } | 2277 | } |
| 2264 | 2278 | ||
| 2265 | if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) | 2279 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) |
| 2266 | goto nla_put_failure; | 2280 | goto nla_put_failure; |
| 2267 | 2281 | ||
| 2268 | if (rt->u.dst.neighbour) | 2282 | if (rt->dst.neighbour) |
| 2269 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); | 2283 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); |
| 2270 | 2284 | ||
| 2271 | if (rt->u.dst.dev) | 2285 | if (rt->dst.dev) |
| 2272 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2286 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
| 2273 | 2287 | ||
| 2274 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2288 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
| @@ -2280,8 +2294,8 @@ static int rt6_fill_node(struct net *net, | |||
| 2280 | else | 2294 | else |
| 2281 | expires = INT_MAX; | 2295 | expires = INT_MAX; |
| 2282 | 2296 | ||
| 2283 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, | 2297 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, |
| 2284 | expires, rt->u.dst.error) < 0) | 2298 | expires, rt->dst.error) < 0) |
| 2285 | goto nla_put_failure; | 2299 | goto nla_put_failure; |
| 2286 | 2300 | ||
| 2287 | return nlmsg_end(skb, nlh); | 2301 | return nlmsg_end(skb, nlh); |
| @@ -2367,7 +2381,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
| 2367 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2381 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
| 2368 | 2382 | ||
| 2369 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); | 2383 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
| 2370 | skb_dst_set(skb, &rt->u.dst); | 2384 | skb_dst_set(skb, &rt->dst); |
| 2371 | 2385 | ||
| 2372 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2386 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
| 2373 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2387 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
| @@ -2419,12 +2433,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
| 2419 | struct net *net = dev_net(dev); | 2433 | struct net *net = dev_net(dev); |
| 2420 | 2434 | ||
| 2421 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | 2435 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { |
| 2422 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | 2436 | net->ipv6.ip6_null_entry->dst.dev = dev; |
| 2423 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | 2437 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); |
| 2424 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2438 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2425 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | 2439 | net->ipv6.ip6_prohibit_entry->dst.dev = dev; |
| 2426 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | 2440 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); |
| 2427 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | 2441 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; |
| 2428 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | 2442 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); |
| 2429 | #endif | 2443 | #endif |
| 2430 | } | 2444 | } |
| @@ -2467,8 +2481,8 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
| 2467 | seq_puts(m, "00000000000000000000000000000000"); | 2481 | seq_puts(m, "00000000000000000000000000000000"); |
| 2468 | } | 2482 | } |
| 2469 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2483 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
| 2470 | rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), | 2484 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
| 2471 | rt->u.dst.__use, rt->rt6i_flags, | 2485 | rt->dst.__use, rt->rt6i_flags, |
| 2472 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); | 2486 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); |
| 2473 | return 0; | 2487 | return 0; |
| 2474 | } | 2488 | } |
| @@ -2586,7 +2600,7 @@ ctl_table ipv6_route_table_template[] = { | |||
| 2586 | .data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity, | 2600 | .data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity, |
| 2587 | .maxlen = sizeof(int), | 2601 | .maxlen = sizeof(int), |
| 2588 | .mode = 0644, | 2602 | .mode = 0644, |
| 2589 | .proc_handler = proc_dointvec_jiffies, | 2603 | .proc_handler = proc_dointvec, |
| 2590 | }, | 2604 | }, |
| 2591 | { | 2605 | { |
| 2592 | .procname = "mtu_expires", | 2606 | .procname = "mtu_expires", |
| @@ -2600,7 +2614,7 @@ ctl_table ipv6_route_table_template[] = { | |||
| 2600 | .data = &init_net.ipv6.sysctl.ip6_rt_min_advmss, | 2614 | .data = &init_net.ipv6.sysctl.ip6_rt_min_advmss, |
| 2601 | .maxlen = sizeof(int), | 2615 | .maxlen = sizeof(int), |
| 2602 | .mode = 0644, | 2616 | .mode = 0644, |
| 2603 | .proc_handler = proc_dointvec_jiffies, | 2617 | .proc_handler = proc_dointvec, |
| 2604 | }, | 2618 | }, |
| 2605 | { | 2619 | { |
| 2606 | .procname = "gc_min_interval_ms", | 2620 | .procname = "gc_min_interval_ms", |
| @@ -2612,7 +2626,7 @@ ctl_table ipv6_route_table_template[] = { | |||
| 2612 | { } | 2626 | { } |
| 2613 | }; | 2627 | }; |
| 2614 | 2628 | ||
| 2615 | struct ctl_table *ipv6_route_sysctl_init(struct net *net) | 2629 | struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) |
| 2616 | { | 2630 | { |
| 2617 | struct ctl_table *table; | 2631 | struct ctl_table *table; |
| 2618 | 2632 | ||
| @@ -2637,7 +2651,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) | |||
| 2637 | } | 2651 | } |
| 2638 | #endif | 2652 | #endif |
| 2639 | 2653 | ||
| 2640 | static int ip6_route_net_init(struct net *net) | 2654 | static int __net_init ip6_route_net_init(struct net *net) |
| 2641 | { | 2655 | { |
| 2642 | int ret = -ENOMEM; | 2656 | int ret = -ENOMEM; |
| 2643 | 2657 | ||
| @@ -2649,9 +2663,9 @@ static int ip6_route_net_init(struct net *net) | |||
| 2649 | GFP_KERNEL); | 2663 | GFP_KERNEL); |
| 2650 | if (!net->ipv6.ip6_null_entry) | 2664 | if (!net->ipv6.ip6_null_entry) |
| 2651 | goto out_ip6_dst_ops; | 2665 | goto out_ip6_dst_ops; |
| 2652 | net->ipv6.ip6_null_entry->u.dst.path = | 2666 | net->ipv6.ip6_null_entry->dst.path = |
| 2653 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2667 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
| 2654 | net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2668 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2655 | 2669 | ||
| 2656 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2670 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2657 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2671 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
| @@ -2659,18 +2673,18 @@ static int ip6_route_net_init(struct net *net) | |||
| 2659 | GFP_KERNEL); | 2673 | GFP_KERNEL); |
| 2660 | if (!net->ipv6.ip6_prohibit_entry) | 2674 | if (!net->ipv6.ip6_prohibit_entry) |
| 2661 | goto out_ip6_null_entry; | 2675 | goto out_ip6_null_entry; |
| 2662 | net->ipv6.ip6_prohibit_entry->u.dst.path = | 2676 | net->ipv6.ip6_prohibit_entry->dst.path = |
| 2663 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2677 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
| 2664 | net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2678 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2665 | 2679 | ||
| 2666 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2680 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
| 2667 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2681 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
| 2668 | GFP_KERNEL); | 2682 | GFP_KERNEL); |
| 2669 | if (!net->ipv6.ip6_blk_hole_entry) | 2683 | if (!net->ipv6.ip6_blk_hole_entry) |
| 2670 | goto out_ip6_prohibit_entry; | 2684 | goto out_ip6_prohibit_entry; |
| 2671 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | 2685 | net->ipv6.ip6_blk_hole_entry->dst.path = |
| 2672 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2686 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
| 2673 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2687 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2674 | #endif | 2688 | #endif |
| 2675 | 2689 | ||
| 2676 | net->ipv6.sysctl.flush_delay = 0; | 2690 | net->ipv6.sysctl.flush_delay = 0; |
| @@ -2702,7 +2716,7 @@ out_ip6_dst_ops: | |||
| 2702 | goto out; | 2716 | goto out; |
| 2703 | } | 2717 | } |
| 2704 | 2718 | ||
| 2705 | static void ip6_route_net_exit(struct net *net) | 2719 | static void __net_exit ip6_route_net_exit(struct net *net) |
| 2706 | { | 2720 | { |
| 2707 | #ifdef CONFIG_PROC_FS | 2721 | #ifdef CONFIG_PROC_FS |
| 2708 | proc_net_remove(net, "ipv6_route"); | 2722 | proc_net_remove(net, "ipv6_route"); |
| @@ -2745,12 +2759,12 @@ int __init ip6_route_init(void) | |||
| 2745 | /* Registering of the loopback is done before this portion of code, | 2759 | /* Registering of the loopback is done before this portion of code, |
| 2746 | * the loopback reference in rt6_info will not be taken, do it | 2760 | * the loopback reference in rt6_info will not be taken, do it |
| 2747 | * manually for init_net */ | 2761 | * manually for init_net */ |
| 2748 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | 2762 | init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; |
| 2749 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2763 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2750 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2764 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2751 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | 2765 | init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; |
| 2752 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2766 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2753 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | 2767 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; |
| 2754 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2768 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2755 | #endif | 2769 | #endif |
| 2756 | ret = fib6_init(); | 2770 | ret = fib6_init(); |
