diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 186 |
1 files changed, 113 insertions, 73 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e7db7014e89f..6814c8722fa7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -97,6 +97,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
97 | struct in6_addr *gwaddr, int ifindex); | 97 | struct in6_addr *gwaddr, int ifindex); |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | ||
101 | { | ||
102 | struct rt6_info *rt = (struct rt6_info *) dst; | ||
103 | struct inet_peer *peer; | ||
104 | u32 *p = NULL; | ||
105 | |||
106 | if (!rt->rt6i_peer) | ||
107 | rt6_bind_peer(rt, 1); | ||
108 | |||
109 | peer = rt->rt6i_peer; | ||
110 | if (peer) { | ||
111 | u32 *old_p = __DST_METRICS_PTR(old); | ||
112 | unsigned long prev, new; | ||
113 | |||
114 | p = peer->metrics; | ||
115 | if (inet_metrics_new(peer)) | ||
116 | memcpy(p, old_p, sizeof(u32) * RTAX_MAX); | ||
117 | |||
118 | new = (unsigned long) p; | ||
119 | prev = cmpxchg(&dst->_metrics, old, new); | ||
120 | |||
121 | if (prev != old) { | ||
122 | p = __DST_METRICS_PTR(prev); | ||
123 | if (prev & DST_METRICS_READ_ONLY) | ||
124 | p = NULL; | ||
125 | } | ||
126 | } | ||
127 | return p; | ||
128 | } | ||
129 | |||
100 | static struct dst_ops ip6_dst_ops_template = { | 130 | static struct dst_ops ip6_dst_ops_template = { |
101 | .family = AF_INET6, | 131 | .family = AF_INET6, |
102 | .protocol = cpu_to_be16(ETH_P_IPV6), | 132 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -105,6 +135,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
105 | .check = ip6_dst_check, | 135 | .check = ip6_dst_check, |
106 | .default_advmss = ip6_default_advmss, | 136 | .default_advmss = ip6_default_advmss, |
107 | .default_mtu = ip6_default_mtu, | 137 | .default_mtu = ip6_default_mtu, |
138 | .cow_metrics = ipv6_cow_metrics, | ||
108 | .destroy = ip6_dst_destroy, | 139 | .destroy = ip6_dst_destroy, |
109 | .ifdown = ip6_dst_ifdown, | 140 | .ifdown = ip6_dst_ifdown, |
110 | .negative_advice = ip6_negative_advice, | 141 | .negative_advice = ip6_negative_advice, |
@@ -132,6 +163,10 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
132 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 163 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
133 | }; | 164 | }; |
134 | 165 | ||
166 | static const u32 ip6_template_metrics[RTAX_MAX] = { | ||
167 | [RTAX_HOPLIMIT - 1] = 255, | ||
168 | }; | ||
169 | |||
135 | static struct rt6_info ip6_null_entry_template = { | 170 | static struct rt6_info ip6_null_entry_template = { |
136 | .dst = { | 171 | .dst = { |
137 | .__refcnt = ATOMIC_INIT(1), | 172 | .__refcnt = ATOMIC_INIT(1), |
@@ -187,7 +222,7 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
187 | /* allocate dst with ip6_dst_ops */ | 222 | /* allocate dst with ip6_dst_ops */ |
188 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) | 223 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
189 | { | 224 | { |
190 | return (struct rt6_info *)dst_alloc(ops); | 225 | return (struct rt6_info *)dst_alloc(ops, 0); |
191 | } | 226 | } |
192 | 227 | ||
193 | static void ip6_dst_destroy(struct dst_entry *dst) | 228 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -206,6 +241,13 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
206 | } | 241 | } |
207 | } | 242 | } |
208 | 243 | ||
244 | static atomic_t __rt6_peer_genid = ATOMIC_INIT(0); | ||
245 | |||
246 | static u32 rt6_peer_genid(void) | ||
247 | { | ||
248 | return atomic_read(&__rt6_peer_genid); | ||
249 | } | ||
250 | |||
209 | void rt6_bind_peer(struct rt6_info *rt, int create) | 251 | void rt6_bind_peer(struct rt6_info *rt, int create) |
210 | { | 252 | { |
211 | struct inet_peer *peer; | 253 | struct inet_peer *peer; |
@@ -213,6 +255,8 @@ void rt6_bind_peer(struct rt6_info *rt, int create) | |||
213 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); | 255 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); |
214 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) | 256 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) |
215 | inet_putpeer(peer); | 257 | inet_putpeer(peer); |
258 | else | ||
259 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
216 | } | 260 | } |
217 | 261 | ||
218 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | 262 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, |
@@ -555,17 +599,17 @@ do { \ | |||
555 | 599 | ||
556 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, | 600 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
557 | struct fib6_table *table, | 601 | struct fib6_table *table, |
558 | struct flowi *fl, int flags) | 602 | struct flowi6 *fl6, int flags) |
559 | { | 603 | { |
560 | struct fib6_node *fn; | 604 | struct fib6_node *fn; |
561 | struct rt6_info *rt; | 605 | struct rt6_info *rt; |
562 | 606 | ||
563 | read_lock_bh(&table->tb6_lock); | 607 | read_lock_bh(&table->tb6_lock); |
564 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 608 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
565 | restart: | 609 | restart: |
566 | rt = fn->leaf; | 610 | rt = fn->leaf; |
567 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); | 611 | rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); |
568 | BACKTRACK(net, &fl->fl6_src); | 612 | BACKTRACK(net, &fl6->saddr); |
569 | out: | 613 | out: |
570 | dst_use(&rt->dst, jiffies); | 614 | dst_use(&rt->dst, jiffies); |
571 | read_unlock_bh(&table->tb6_lock); | 615 | read_unlock_bh(&table->tb6_lock); |
@@ -576,19 +620,19 @@ out: | |||
576 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 620 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
577 | const struct in6_addr *saddr, int oif, int strict) | 621 | const struct in6_addr *saddr, int oif, int strict) |
578 | { | 622 | { |
579 | struct flowi fl = { | 623 | struct flowi6 fl6 = { |
580 | .oif = oif, | 624 | .flowi6_oif = oif, |
581 | .fl6_dst = *daddr, | 625 | .daddr = *daddr, |
582 | }; | 626 | }; |
583 | struct dst_entry *dst; | 627 | struct dst_entry *dst; |
584 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; | 628 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; |
585 | 629 | ||
586 | if (saddr) { | 630 | if (saddr) { |
587 | memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); | 631 | memcpy(&fl6.saddr, saddr, sizeof(*saddr)); |
588 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 632 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
589 | } | 633 | } |
590 | 634 | ||
591 | dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup); | 635 | dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup); |
592 | if (dst->error == 0) | 636 | if (dst->error == 0) |
593 | return (struct rt6_info *) dst; | 637 | return (struct rt6_info *) dst; |
594 | 638 | ||
@@ -709,7 +753,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
709 | } | 753 | } |
710 | 754 | ||
711 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, | 755 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, |
712 | struct flowi *fl, int flags) | 756 | struct flowi6 *fl6, int flags) |
713 | { | 757 | { |
714 | struct fib6_node *fn; | 758 | struct fib6_node *fn; |
715 | struct rt6_info *rt, *nrt; | 759 | struct rt6_info *rt, *nrt; |
@@ -724,12 +768,12 @@ relookup: | |||
724 | read_lock_bh(&table->tb6_lock); | 768 | read_lock_bh(&table->tb6_lock); |
725 | 769 | ||
726 | restart_2: | 770 | restart_2: |
727 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 771 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
728 | 772 | ||
729 | restart: | 773 | restart: |
730 | rt = rt6_select(fn, oif, strict | reachable); | 774 | rt = rt6_select(fn, oif, strict | reachable); |
731 | 775 | ||
732 | BACKTRACK(net, &fl->fl6_src); | 776 | BACKTRACK(net, &fl6->saddr); |
733 | if (rt == net->ipv6.ip6_null_entry || | 777 | if (rt == net->ipv6.ip6_null_entry || |
734 | rt->rt6i_flags & RTF_CACHE) | 778 | rt->rt6i_flags & RTF_CACHE) |
735 | goto out; | 779 | goto out; |
@@ -738,9 +782,9 @@ restart: | |||
738 | read_unlock_bh(&table->tb6_lock); | 782 | read_unlock_bh(&table->tb6_lock); |
739 | 783 | ||
740 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 784 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
741 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | 785 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
742 | else if (!(rt->dst.flags & DST_HOST)) | 786 | else if (!(rt->dst.flags & DST_HOST)) |
743 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | 787 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
744 | else | 788 | else |
745 | goto out2; | 789 | goto out2; |
746 | 790 | ||
@@ -779,9 +823,9 @@ out2: | |||
779 | } | 823 | } |
780 | 824 | ||
781 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, | 825 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, |
782 | struct flowi *fl, int flags) | 826 | struct flowi6 *fl6, int flags) |
783 | { | 827 | { |
784 | return ip6_pol_route(net, table, fl->iif, fl, flags); | 828 | return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); |
785 | } | 829 | } |
786 | 830 | ||
787 | void ip6_route_input(struct sk_buff *skb) | 831 | void ip6_route_input(struct sk_buff *skb) |
@@ -789,56 +833,54 @@ void ip6_route_input(struct sk_buff *skb) | |||
789 | struct ipv6hdr *iph = ipv6_hdr(skb); | 833 | struct ipv6hdr *iph = ipv6_hdr(skb); |
790 | struct net *net = dev_net(skb->dev); | 834 | struct net *net = dev_net(skb->dev); |
791 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 835 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
792 | struct flowi fl = { | 836 | struct flowi6 fl6 = { |
793 | .iif = skb->dev->ifindex, | 837 | .flowi6_iif = skb->dev->ifindex, |
794 | .fl6_dst = iph->daddr, | 838 | .daddr = iph->daddr, |
795 | .fl6_src = iph->saddr, | 839 | .saddr = iph->saddr, |
796 | .fl6_flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, | 840 | .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, |
797 | .mark = skb->mark, | 841 | .flowi6_mark = skb->mark, |
798 | .proto = iph->nexthdr, | 842 | .flowi6_proto = iph->nexthdr, |
799 | }; | 843 | }; |
800 | 844 | ||
801 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) | 845 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) |
802 | flags |= RT6_LOOKUP_F_IFACE; | 846 | flags |= RT6_LOOKUP_F_IFACE; |
803 | 847 | ||
804 | skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input)); | 848 | skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input)); |
805 | } | 849 | } |
806 | 850 | ||
807 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, | 851 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
808 | struct flowi *fl, int flags) | 852 | struct flowi6 *fl6, int flags) |
809 | { | 853 | { |
810 | return ip6_pol_route(net, table, fl->oif, fl, flags); | 854 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); |
811 | } | 855 | } |
812 | 856 | ||
813 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | 857 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, |
814 | struct flowi *fl) | 858 | struct flowi6 *fl6) |
815 | { | 859 | { |
816 | int flags = 0; | 860 | int flags = 0; |
817 | 861 | ||
818 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst)) | 862 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) |
819 | flags |= RT6_LOOKUP_F_IFACE; | 863 | flags |= RT6_LOOKUP_F_IFACE; |
820 | 864 | ||
821 | if (!ipv6_addr_any(&fl->fl6_src)) | 865 | if (!ipv6_addr_any(&fl6->saddr)) |
822 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 866 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
823 | else if (sk) | 867 | else if (sk) |
824 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); | 868 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
825 | 869 | ||
826 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); | 870 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); |
827 | } | 871 | } |
828 | 872 | ||
829 | EXPORT_SYMBOL(ip6_route_output); | 873 | EXPORT_SYMBOL(ip6_route_output); |
830 | 874 | ||
831 | int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) | 875 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
832 | { | 876 | { |
833 | struct rt6_info *ort = (struct rt6_info *) *dstp; | 877 | struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); |
834 | struct rt6_info *rt = (struct rt6_info *) | 878 | struct rt6_info *ort = (struct rt6_info *) dst_orig; |
835 | dst_alloc(&ip6_dst_blackhole_ops); | ||
836 | struct dst_entry *new = NULL; | 879 | struct dst_entry *new = NULL; |
837 | 880 | ||
838 | if (rt) { | 881 | if (rt) { |
839 | new = &rt->dst; | 882 | new = &rt->dst; |
840 | 883 | ||
841 | atomic_set(&new->__refcnt, 1); | ||
842 | new->__use = 1; | 884 | new->__use = 1; |
843 | new->input = dst_discard; | 885 | new->input = dst_discard; |
844 | new->output = dst_discard; | 886 | new->output = dst_discard; |
@@ -864,11 +906,9 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
864 | dst_free(new); | 906 | dst_free(new); |
865 | } | 907 | } |
866 | 908 | ||
867 | dst_release(*dstp); | 909 | dst_release(dst_orig); |
868 | *dstp = new; | 910 | return new ? new : ERR_PTR(-ENOMEM); |
869 | return new ? 0 : -ENOMEM; | ||
870 | } | 911 | } |
871 | EXPORT_SYMBOL_GPL(ip6_dst_blackhole); | ||
872 | 912 | ||
873 | /* | 913 | /* |
874 | * Destination cache support functions | 914 | * Destination cache support functions |
@@ -880,9 +920,14 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
880 | 920 | ||
881 | rt = (struct rt6_info *) dst; | 921 | rt = (struct rt6_info *) dst; |
882 | 922 | ||
883 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 923 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { |
924 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { | ||
925 | if (!rt->rt6i_peer) | ||
926 | rt6_bind_peer(rt, 0); | ||
927 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
928 | } | ||
884 | return dst; | 929 | return dst; |
885 | 930 | } | |
886 | return NULL; | 931 | return NULL; |
887 | } | 932 | } |
888 | 933 | ||
@@ -933,7 +978,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
933 | dst_metric_set(dst, RTAX_FEATURES, features); | 978 | dst_metric_set(dst, RTAX_FEATURES, features); |
934 | } | 979 | } |
935 | dst_metric_set(dst, RTAX_MTU, mtu); | 980 | dst_metric_set(dst, RTAX_MTU, mtu); |
936 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); | ||
937 | } | 981 | } |
938 | } | 982 | } |
939 | 983 | ||
@@ -1030,11 +1074,9 @@ out: | |||
1030 | 1074 | ||
1031 | int icmp6_dst_gc(void) | 1075 | int icmp6_dst_gc(void) |
1032 | { | 1076 | { |
1033 | struct dst_entry *dst, *next, **pprev; | 1077 | struct dst_entry *dst, **pprev; |
1034 | int more = 0; | 1078 | int more = 0; |
1035 | 1079 | ||
1036 | next = NULL; | ||
1037 | |||
1038 | spin_lock_bh(&icmp6_dst_lock); | 1080 | spin_lock_bh(&icmp6_dst_lock); |
1039 | pprev = &icmp6_dst_gc_list; | 1081 | pprev = &icmp6_dst_gc_list; |
1040 | 1082 | ||
@@ -1402,16 +1444,16 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1402 | * Handle redirects | 1444 | * Handle redirects |
1403 | */ | 1445 | */ |
1404 | struct ip6rd_flowi { | 1446 | struct ip6rd_flowi { |
1405 | struct flowi fl; | 1447 | struct flowi6 fl6; |
1406 | struct in6_addr gateway; | 1448 | struct in6_addr gateway; |
1407 | }; | 1449 | }; |
1408 | 1450 | ||
1409 | static struct rt6_info *__ip6_route_redirect(struct net *net, | 1451 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1410 | struct fib6_table *table, | 1452 | struct fib6_table *table, |
1411 | struct flowi *fl, | 1453 | struct flowi6 *fl6, |
1412 | int flags) | 1454 | int flags) |
1413 | { | 1455 | { |
1414 | struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl; | 1456 | struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; |
1415 | struct rt6_info *rt; | 1457 | struct rt6_info *rt; |
1416 | struct fib6_node *fn; | 1458 | struct fib6_node *fn; |
1417 | 1459 | ||
@@ -1427,7 +1469,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
1427 | */ | 1469 | */ |
1428 | 1470 | ||
1429 | read_lock_bh(&table->tb6_lock); | 1471 | read_lock_bh(&table->tb6_lock); |
1430 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 1472 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
1431 | restart: | 1473 | restart: |
1432 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1474 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1433 | /* | 1475 | /* |
@@ -1442,7 +1484,7 @@ restart: | |||
1442 | continue; | 1484 | continue; |
1443 | if (!(rt->rt6i_flags & RTF_GATEWAY)) | 1485 | if (!(rt->rt6i_flags & RTF_GATEWAY)) |
1444 | continue; | 1486 | continue; |
1445 | if (fl->oif != rt->rt6i_dev->ifindex) | 1487 | if (fl6->flowi6_oif != rt->rt6i_dev->ifindex) |
1446 | continue; | 1488 | continue; |
1447 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) | 1489 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) |
1448 | continue; | 1490 | continue; |
@@ -1451,7 +1493,7 @@ restart: | |||
1451 | 1493 | ||
1452 | if (!rt) | 1494 | if (!rt) |
1453 | rt = net->ipv6.ip6_null_entry; | 1495 | rt = net->ipv6.ip6_null_entry; |
1454 | BACKTRACK(net, &fl->fl6_src); | 1496 | BACKTRACK(net, &fl6->saddr); |
1455 | out: | 1497 | out: |
1456 | dst_hold(&rt->dst); | 1498 | dst_hold(&rt->dst); |
1457 | 1499 | ||
@@ -1468,10 +1510,10 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1468 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1510 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
1469 | struct net *net = dev_net(dev); | 1511 | struct net *net = dev_net(dev); |
1470 | struct ip6rd_flowi rdfl = { | 1512 | struct ip6rd_flowi rdfl = { |
1471 | .fl = { | 1513 | .fl6 = { |
1472 | .oif = dev->ifindex, | 1514 | .flowi6_oif = dev->ifindex, |
1473 | .fl6_dst = *dest, | 1515 | .daddr = *dest, |
1474 | .fl6_src = *src, | 1516 | .saddr = *src, |
1475 | }, | 1517 | }, |
1476 | }; | 1518 | }; |
1477 | 1519 | ||
@@ -1480,7 +1522,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1480 | if (rt6_need_strict(dest)) | 1522 | if (rt6_need_strict(dest)) |
1481 | flags |= RT6_LOOKUP_F_IFACE; | 1523 | flags |= RT6_LOOKUP_F_IFACE; |
1482 | 1524 | ||
1483 | return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, | 1525 | return (struct rt6_info *)fib6_rule_lookup(net, &rdfl.fl6, |
1484 | flags, __ip6_route_redirect); | 1526 | flags, __ip6_route_redirect); |
1485 | } | 1527 | } |
1486 | 1528 | ||
@@ -1982,12 +2024,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1982 | if (IS_ERR(neigh)) { | 2024 | if (IS_ERR(neigh)) { |
1983 | dst_free(&rt->dst); | 2025 | dst_free(&rt->dst); |
1984 | 2026 | ||
1985 | /* We are casting this because that is the return | 2027 | return ERR_CAST(neigh); |
1986 | * value type. But an errno encoded pointer is the | ||
1987 | * same regardless of the underlying pointer type, | ||
1988 | * and that's what we are returning. So this is OK. | ||
1989 | */ | ||
1990 | return (struct rt6_info *) neigh; | ||
1991 | } | 2028 | } |
1992 | rt->rt6i_nexthop = neigh; | 2029 | rt->rt6i_nexthop = neigh; |
1993 | 2030 | ||
@@ -2348,7 +2385,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2348 | struct rt6_info *rt; | 2385 | struct rt6_info *rt; |
2349 | struct sk_buff *skb; | 2386 | struct sk_buff *skb; |
2350 | struct rtmsg *rtm; | 2387 | struct rtmsg *rtm; |
2351 | struct flowi fl; | 2388 | struct flowi6 fl6; |
2352 | int err, iif = 0; | 2389 | int err, iif = 0; |
2353 | 2390 | ||
2354 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2391 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
@@ -2356,27 +2393,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2356 | goto errout; | 2393 | goto errout; |
2357 | 2394 | ||
2358 | err = -EINVAL; | 2395 | err = -EINVAL; |
2359 | memset(&fl, 0, sizeof(fl)); | 2396 | memset(&fl6, 0, sizeof(fl6)); |
2360 | 2397 | ||
2361 | if (tb[RTA_SRC]) { | 2398 | if (tb[RTA_SRC]) { |
2362 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) | 2399 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) |
2363 | goto errout; | 2400 | goto errout; |
2364 | 2401 | ||
2365 | ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC])); | 2402 | ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC])); |
2366 | } | 2403 | } |
2367 | 2404 | ||
2368 | if (tb[RTA_DST]) { | 2405 | if (tb[RTA_DST]) { |
2369 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) | 2406 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) |
2370 | goto errout; | 2407 | goto errout; |
2371 | 2408 | ||
2372 | ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST])); | 2409 | ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST])); |
2373 | } | 2410 | } |
2374 | 2411 | ||
2375 | if (tb[RTA_IIF]) | 2412 | if (tb[RTA_IIF]) |
2376 | iif = nla_get_u32(tb[RTA_IIF]); | 2413 | iif = nla_get_u32(tb[RTA_IIF]); |
2377 | 2414 | ||
2378 | if (tb[RTA_OIF]) | 2415 | if (tb[RTA_OIF]) |
2379 | fl.oif = nla_get_u32(tb[RTA_OIF]); | 2416 | fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]); |
2380 | 2417 | ||
2381 | if (iif) { | 2418 | if (iif) { |
2382 | struct net_device *dev; | 2419 | struct net_device *dev; |
@@ -2399,10 +2436,10 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2399 | skb_reset_mac_header(skb); | 2436 | skb_reset_mac_header(skb); |
2400 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2437 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2401 | 2438 | ||
2402 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); | 2439 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6); |
2403 | skb_dst_set(skb, &rt->dst); | 2440 | skb_dst_set(skb, &rt->dst); |
2404 | 2441 | ||
2405 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2442 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, |
2406 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2443 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
2407 | nlh->nlmsg_seq, 0, 0, 0); | 2444 | nlh->nlmsg_seq, 0, 0, 0); |
2408 | if (err < 0) { | 2445 | if (err < 0) { |
@@ -2689,7 +2726,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2689 | net->ipv6.ip6_null_entry->dst.path = | 2726 | net->ipv6.ip6_null_entry->dst.path = |
2690 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2727 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2691 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2728 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2692 | dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255); | 2729 | dst_init_metrics(&net->ipv6.ip6_null_entry->dst, |
2730 | ip6_template_metrics, true); | ||
2693 | 2731 | ||
2694 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2732 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2695 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2733 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2700,7 +2738,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2700 | net->ipv6.ip6_prohibit_entry->dst.path = | 2738 | net->ipv6.ip6_prohibit_entry->dst.path = |
2701 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2739 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2702 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2740 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2703 | dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255); | 2741 | dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst, |
2742 | ip6_template_metrics, true); | ||
2704 | 2743 | ||
2705 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2744 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2706 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2745 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
@@ -2710,7 +2749,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2710 | net->ipv6.ip6_blk_hole_entry->dst.path = | 2749 | net->ipv6.ip6_blk_hole_entry->dst.path = |
2711 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2750 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2712 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2751 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2713 | dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255); | 2752 | dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, |
2753 | ip6_template_metrics, true); | ||
2714 | #endif | 2754 | #endif |
2715 | 2755 | ||
2716 | net->ipv6.sysctl.flush_delay = 0; | 2756 | net->ipv6.sysctl.flush_delay = 0; |