aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c215
1 files changed, 133 insertions, 82 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a998db6e7895..fd0eec6f88c6 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
100static 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
100static struct dst_ops ip6_dst_ops_template = { 130static 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,
@@ -122,6 +153,12 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
122{ 153{
123} 154}
124 155
156static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
157 unsigned long old)
158{
159 return NULL;
160}
161
125static struct dst_ops ip6_dst_blackhole_ops = { 162static struct dst_ops ip6_dst_blackhole_ops = {
126 .family = AF_INET6, 163 .family = AF_INET6,
127 .protocol = cpu_to_be16(ETH_P_IPV6), 164 .protocol = cpu_to_be16(ETH_P_IPV6),
@@ -130,6 +167,11 @@ static struct dst_ops ip6_dst_blackhole_ops = {
130 .default_mtu = ip6_blackhole_default_mtu, 167 .default_mtu = ip6_blackhole_default_mtu,
131 .default_advmss = ip6_default_advmss, 168 .default_advmss = ip6_default_advmss,
132 .update_pmtu = ip6_rt_blackhole_update_pmtu, 169 .update_pmtu = ip6_rt_blackhole_update_pmtu,
170 .cow_metrics = ip6_rt_blackhole_cow_metrics,
171};
172
173static const u32 ip6_template_metrics[RTAX_MAX] = {
174 [RTAX_HOPLIMIT - 1] = 255,
133}; 175};
134 176
135static struct rt6_info ip6_null_entry_template = { 177static struct rt6_info ip6_null_entry_template = {
@@ -187,7 +229,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
187/* allocate dst with ip6_dst_ops */ 229/* allocate dst with ip6_dst_ops */
188static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) 230static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops)
189{ 231{
190 return (struct rt6_info *)dst_alloc(ops); 232 return (struct rt6_info *)dst_alloc(ops, 0);
191} 233}
192 234
193static void ip6_dst_destroy(struct dst_entry *dst) 235static void ip6_dst_destroy(struct dst_entry *dst)
@@ -206,6 +248,13 @@ static void ip6_dst_destroy(struct dst_entry *dst)
206 } 248 }
207} 249}
208 250
251static atomic_t __rt6_peer_genid = ATOMIC_INIT(0);
252
253static u32 rt6_peer_genid(void)
254{
255 return atomic_read(&__rt6_peer_genid);
256}
257
209void rt6_bind_peer(struct rt6_info *rt, int create) 258void rt6_bind_peer(struct rt6_info *rt, int create)
210{ 259{
211 struct inet_peer *peer; 260 struct inet_peer *peer;
@@ -213,6 +262,8 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
213 peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); 262 peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create);
214 if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) 263 if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL)
215 inet_putpeer(peer); 264 inet_putpeer(peer);
265 else
266 rt->rt6i_peer_genid = rt6_peer_genid();
216} 267}
217 268
218static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, 269static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
@@ -555,17 +606,17 @@ do { \
555 606
556static struct rt6_info *ip6_pol_route_lookup(struct net *net, 607static struct rt6_info *ip6_pol_route_lookup(struct net *net,
557 struct fib6_table *table, 608 struct fib6_table *table,
558 struct flowi *fl, int flags) 609 struct flowi6 *fl6, int flags)
559{ 610{
560 struct fib6_node *fn; 611 struct fib6_node *fn;
561 struct rt6_info *rt; 612 struct rt6_info *rt;
562 613
563 read_lock_bh(&table->tb6_lock); 614 read_lock_bh(&table->tb6_lock);
564 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); 615 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
565restart: 616restart:
566 rt = fn->leaf; 617 rt = fn->leaf;
567 rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); 618 rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
568 BACKTRACK(net, &fl->fl6_src); 619 BACKTRACK(net, &fl6->saddr);
569out: 620out:
570 dst_use(&rt->dst, jiffies); 621 dst_use(&rt->dst, jiffies);
571 read_unlock_bh(&table->tb6_lock); 622 read_unlock_bh(&table->tb6_lock);
@@ -576,19 +627,19 @@ out:
576struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, 627struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
577 const struct in6_addr *saddr, int oif, int strict) 628 const struct in6_addr *saddr, int oif, int strict)
578{ 629{
579 struct flowi fl = { 630 struct flowi6 fl6 = {
580 .oif = oif, 631 .flowi6_oif = oif,
581 .fl6_dst = *daddr, 632 .daddr = *daddr,
582 }; 633 };
583 struct dst_entry *dst; 634 struct dst_entry *dst;
584 int flags = strict ? RT6_LOOKUP_F_IFACE : 0; 635 int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
585 636
586 if (saddr) { 637 if (saddr) {
587 memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); 638 memcpy(&fl6.saddr, saddr, sizeof(*saddr));
588 flags |= RT6_LOOKUP_F_HAS_SADDR; 639 flags |= RT6_LOOKUP_F_HAS_SADDR;
589 } 640 }
590 641
591 dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup); 642 dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
592 if (dst->error == 0) 643 if (dst->error == 0)
593 return (struct rt6_info *) dst; 644 return (struct rt6_info *) dst;
594 645
@@ -709,7 +760,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
709} 760}
710 761
711static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, 762static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
712 struct flowi *fl, int flags) 763 struct flowi6 *fl6, int flags)
713{ 764{
714 struct fib6_node *fn; 765 struct fib6_node *fn;
715 struct rt6_info *rt, *nrt; 766 struct rt6_info *rt, *nrt;
@@ -724,12 +775,12 @@ relookup:
724 read_lock_bh(&table->tb6_lock); 775 read_lock_bh(&table->tb6_lock);
725 776
726restart_2: 777restart_2:
727 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); 778 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
728 779
729restart: 780restart:
730 rt = rt6_select(fn, oif, strict | reachable); 781 rt = rt6_select(fn, oif, strict | reachable);
731 782
732 BACKTRACK(net, &fl->fl6_src); 783 BACKTRACK(net, &fl6->saddr);
733 if (rt == net->ipv6.ip6_null_entry || 784 if (rt == net->ipv6.ip6_null_entry ||
734 rt->rt6i_flags & RTF_CACHE) 785 rt->rt6i_flags & RTF_CACHE)
735 goto out; 786 goto out;
@@ -738,9 +789,11 @@ restart:
738 read_unlock_bh(&table->tb6_lock); 789 read_unlock_bh(&table->tb6_lock);
739 790
740 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 791 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
741 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); 792 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
793 else if (!(rt->dst.flags & DST_HOST))
794 nrt = rt6_alloc_clone(rt, &fl6->daddr);
742 else 795 else
743 nrt = rt6_alloc_clone(rt, &fl->fl6_dst); 796 goto out2;
744 797
745 dst_release(&rt->dst); 798 dst_release(&rt->dst);
746 rt = nrt ? : net->ipv6.ip6_null_entry; 799 rt = nrt ? : net->ipv6.ip6_null_entry;
@@ -777,9 +830,9 @@ out2:
777} 830}
778 831
779static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, 832static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
780 struct flowi *fl, int flags) 833 struct flowi6 *fl6, int flags)
781{ 834{
782 return ip6_pol_route(net, table, fl->iif, fl, flags); 835 return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
783} 836}
784 837
785void ip6_route_input(struct sk_buff *skb) 838void ip6_route_input(struct sk_buff *skb)
@@ -787,56 +840,54 @@ void ip6_route_input(struct sk_buff *skb)
787 struct ipv6hdr *iph = ipv6_hdr(skb); 840 struct ipv6hdr *iph = ipv6_hdr(skb);
788 struct net *net = dev_net(skb->dev); 841 struct net *net = dev_net(skb->dev);
789 int flags = RT6_LOOKUP_F_HAS_SADDR; 842 int flags = RT6_LOOKUP_F_HAS_SADDR;
790 struct flowi fl = { 843 struct flowi6 fl6 = {
791 .iif = skb->dev->ifindex, 844 .flowi6_iif = skb->dev->ifindex,
792 .fl6_dst = iph->daddr, 845 .daddr = iph->daddr,
793 .fl6_src = iph->saddr, 846 .saddr = iph->saddr,
794 .fl6_flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, 847 .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
795 .mark = skb->mark, 848 .flowi6_mark = skb->mark,
796 .proto = iph->nexthdr, 849 .flowi6_proto = iph->nexthdr,
797 }; 850 };
798 851
799 if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) 852 if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
800 flags |= RT6_LOOKUP_F_IFACE; 853 flags |= RT6_LOOKUP_F_IFACE;
801 854
802 skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input)); 855 skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input));
803} 856}
804 857
805static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, 858static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
806 struct flowi *fl, int flags) 859 struct flowi6 *fl6, int flags)
807{ 860{
808 return ip6_pol_route(net, table, fl->oif, fl, flags); 861 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
809} 862}
810 863
811struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, 864struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk,
812 struct flowi *fl) 865 struct flowi6 *fl6)
813{ 866{
814 int flags = 0; 867 int flags = 0;
815 868
816 if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst)) 869 if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
817 flags |= RT6_LOOKUP_F_IFACE; 870 flags |= RT6_LOOKUP_F_IFACE;
818 871
819 if (!ipv6_addr_any(&fl->fl6_src)) 872 if (!ipv6_addr_any(&fl6->saddr))
820 flags |= RT6_LOOKUP_F_HAS_SADDR; 873 flags |= RT6_LOOKUP_F_HAS_SADDR;
821 else if (sk) 874 else if (sk)
822 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); 875 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
823 876
824 return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); 877 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
825} 878}
826 879
827EXPORT_SYMBOL(ip6_route_output); 880EXPORT_SYMBOL(ip6_route_output);
828 881
829int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) 882struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
830{ 883{
831 struct rt6_info *ort = (struct rt6_info *) *dstp; 884 struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1);
832 struct rt6_info *rt = (struct rt6_info *) 885 struct rt6_info *ort = (struct rt6_info *) dst_orig;
833 dst_alloc(&ip6_dst_blackhole_ops);
834 struct dst_entry *new = NULL; 886 struct dst_entry *new = NULL;
835 887
836 if (rt) { 888 if (rt) {
837 new = &rt->dst; 889 new = &rt->dst;
838 890
839 atomic_set(&new->__refcnt, 1);
840 new->__use = 1; 891 new->__use = 1;
841 new->input = dst_discard; 892 new->input = dst_discard;
842 new->output = dst_discard; 893 new->output = dst_discard;
@@ -862,11 +913,9 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
862 dst_free(new); 913 dst_free(new);
863 } 914 }
864 915
865 dst_release(*dstp); 916 dst_release(dst_orig);
866 *dstp = new; 917 return new ? new : ERR_PTR(-ENOMEM);
867 return new ? 0 : -ENOMEM;
868} 918}
869EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
870 919
871/* 920/*
872 * Destination cache support functions 921 * Destination cache support functions
@@ -878,9 +927,14 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
878 927
879 rt = (struct rt6_info *) dst; 928 rt = (struct rt6_info *) dst;
880 929
881 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) 930 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
931 if (rt->rt6i_peer_genid != rt6_peer_genid()) {
932 if (!rt->rt6i_peer)
933 rt6_bind_peer(rt, 0);
934 rt->rt6i_peer_genid = rt6_peer_genid();
935 }
882 return dst; 936 return dst;
883 937 }
884 return NULL; 938 return NULL;
885} 939}
886 940
@@ -931,7 +985,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
931 dst_metric_set(dst, RTAX_FEATURES, features); 985 dst_metric_set(dst, RTAX_FEATURES, features);
932 } 986 }
933 dst_metric_set(dst, RTAX_MTU, mtu); 987 dst_metric_set(dst, RTAX_MTU, mtu);
934 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
935 } 988 }
936} 989}
937 990
@@ -1028,11 +1081,9 @@ out:
1028 1081
1029int icmp6_dst_gc(void) 1082int icmp6_dst_gc(void)
1030{ 1083{
1031 struct dst_entry *dst, *next, **pprev; 1084 struct dst_entry *dst, **pprev;
1032 int more = 0; 1085 int more = 0;
1033 1086
1034 next = NULL;
1035
1036 spin_lock_bh(&icmp6_dst_lock); 1087 spin_lock_bh(&icmp6_dst_lock);
1037 pprev = &icmp6_dst_gc_list; 1088 pprev = &icmp6_dst_gc_list;
1038 1089
@@ -1400,16 +1451,16 @@ static int ip6_route_del(struct fib6_config *cfg)
1400 * Handle redirects 1451 * Handle redirects
1401 */ 1452 */
1402struct ip6rd_flowi { 1453struct ip6rd_flowi {
1403 struct flowi fl; 1454 struct flowi6 fl6;
1404 struct in6_addr gateway; 1455 struct in6_addr gateway;
1405}; 1456};
1406 1457
1407static struct rt6_info *__ip6_route_redirect(struct net *net, 1458static struct rt6_info *__ip6_route_redirect(struct net *net,
1408 struct fib6_table *table, 1459 struct fib6_table *table,
1409 struct flowi *fl, 1460 struct flowi6 *fl6,
1410 int flags) 1461 int flags)
1411{ 1462{
1412 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl; 1463 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
1413 struct rt6_info *rt; 1464 struct rt6_info *rt;
1414 struct fib6_node *fn; 1465 struct fib6_node *fn;
1415 1466
@@ -1425,7 +1476,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
1425 */ 1476 */
1426 1477
1427 read_lock_bh(&table->tb6_lock); 1478 read_lock_bh(&table->tb6_lock);
1428 fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); 1479 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
1429restart: 1480restart:
1430 for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { 1481 for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
1431 /* 1482 /*
@@ -1440,7 +1491,7 @@ restart:
1440 continue; 1491 continue;
1441 if (!(rt->rt6i_flags & RTF_GATEWAY)) 1492 if (!(rt->rt6i_flags & RTF_GATEWAY))
1442 continue; 1493 continue;
1443 if (fl->oif != rt->rt6i_dev->ifindex) 1494 if (fl6->flowi6_oif != rt->rt6i_dev->ifindex)
1444 continue; 1495 continue;
1445 if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) 1496 if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
1446 continue; 1497 continue;
@@ -1449,7 +1500,7 @@ restart:
1449 1500
1450 if (!rt) 1501 if (!rt)
1451 rt = net->ipv6.ip6_null_entry; 1502 rt = net->ipv6.ip6_null_entry;
1452 BACKTRACK(net, &fl->fl6_src); 1503 BACKTRACK(net, &fl6->saddr);
1453out: 1504out:
1454 dst_hold(&rt->dst); 1505 dst_hold(&rt->dst);
1455 1506
@@ -1466,10 +1517,10 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1466 int flags = RT6_LOOKUP_F_HAS_SADDR; 1517 int flags = RT6_LOOKUP_F_HAS_SADDR;
1467 struct net *net = dev_net(dev); 1518 struct net *net = dev_net(dev);
1468 struct ip6rd_flowi rdfl = { 1519 struct ip6rd_flowi rdfl = {
1469 .fl = { 1520 .fl6 = {
1470 .oif = dev->ifindex, 1521 .flowi6_oif = dev->ifindex,
1471 .fl6_dst = *dest, 1522 .daddr = *dest,
1472 .fl6_src = *src, 1523 .saddr = *src,
1473 }, 1524 },
1474 }; 1525 };
1475 1526
@@ -1478,7 +1529,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
1478 if (rt6_need_strict(dest)) 1529 if (rt6_need_strict(dest))
1479 flags |= RT6_LOOKUP_F_IFACE; 1530 flags |= RT6_LOOKUP_F_IFACE;
1480 1531
1481 return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, 1532 return (struct rt6_info *)fib6_rule_lookup(net, &rdfl.fl6,
1482 flags, __ip6_route_redirect); 1533 flags, __ip6_route_redirect);
1483} 1534}
1484 1535
@@ -1968,7 +2019,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1968 rt->dst.output = ip6_output; 2019 rt->dst.output = ip6_output;
1969 rt->rt6i_dev = net->loopback_dev; 2020 rt->rt6i_dev = net->loopback_dev;
1970 rt->rt6i_idev = idev; 2021 rt->rt6i_idev = idev;
1971 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
1972 rt->dst.obsolete = -1; 2022 rt->dst.obsolete = -1;
1973 2023
1974 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; 2024 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
@@ -1980,12 +2030,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1980 if (IS_ERR(neigh)) { 2030 if (IS_ERR(neigh)) {
1981 dst_free(&rt->dst); 2031 dst_free(&rt->dst);
1982 2032
1983 /* We are casting this because that is the return 2033 return ERR_CAST(neigh);
1984 * value type. But an errno encoded pointer is the
1985 * same regardless of the underlying pointer type,
1986 * and that's what we are returning. So this is OK.
1987 */
1988 return (struct rt6_info *) neigh;
1989 } 2034 }
1990 rt->rt6i_nexthop = neigh; 2035 rt->rt6i_nexthop = neigh;
1991 2036
@@ -2346,7 +2391,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2346 struct rt6_info *rt; 2391 struct rt6_info *rt;
2347 struct sk_buff *skb; 2392 struct sk_buff *skb;
2348 struct rtmsg *rtm; 2393 struct rtmsg *rtm;
2349 struct flowi fl; 2394 struct flowi6 fl6;
2350 int err, iif = 0; 2395 int err, iif = 0;
2351 2396
2352 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); 2397 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
@@ -2354,27 +2399,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2354 goto errout; 2399 goto errout;
2355 2400
2356 err = -EINVAL; 2401 err = -EINVAL;
2357 memset(&fl, 0, sizeof(fl)); 2402 memset(&fl6, 0, sizeof(fl6));
2358 2403
2359 if (tb[RTA_SRC]) { 2404 if (tb[RTA_SRC]) {
2360 if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) 2405 if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
2361 goto errout; 2406 goto errout;
2362 2407
2363 ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC])); 2408 ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC]));
2364 } 2409 }
2365 2410
2366 if (tb[RTA_DST]) { 2411 if (tb[RTA_DST]) {
2367 if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) 2412 if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
2368 goto errout; 2413 goto errout;
2369 2414
2370 ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST])); 2415 ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST]));
2371 } 2416 }
2372 2417
2373 if (tb[RTA_IIF]) 2418 if (tb[RTA_IIF])
2374 iif = nla_get_u32(tb[RTA_IIF]); 2419 iif = nla_get_u32(tb[RTA_IIF]);
2375 2420
2376 if (tb[RTA_OIF]) 2421 if (tb[RTA_OIF])
2377 fl.oif = nla_get_u32(tb[RTA_OIF]); 2422 fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]);
2378 2423
2379 if (iif) { 2424 if (iif) {
2380 struct net_device *dev; 2425 struct net_device *dev;
@@ -2397,10 +2442,10 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2397 skb_reset_mac_header(skb); 2442 skb_reset_mac_header(skb);
2398 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); 2443 skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
2399 2444
2400 rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); 2445 rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6);
2401 skb_dst_set(skb, &rt->dst); 2446 skb_dst_set(skb, &rt->dst);
2402 2447
2403 err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, 2448 err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
2404 RTM_NEWROUTE, NETLINK_CB(in_skb).pid, 2449 RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
2405 nlh->nlmsg_seq, 0, 0, 0); 2450 nlh->nlmsg_seq, 0, 0, 0);
2406 if (err < 0) { 2451 if (err < 0) {
@@ -2557,14 +2602,16 @@ static
2557int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, 2602int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
2558 void __user *buffer, size_t *lenp, loff_t *ppos) 2603 void __user *buffer, size_t *lenp, loff_t *ppos)
2559{ 2604{
2560 struct net *net = current->nsproxy->net_ns; 2605 struct net *net;
2561 int delay = net->ipv6.sysctl.flush_delay; 2606 int delay;
2562 if (write) { 2607 if (!write)
2563 proc_dointvec(ctl, write, buffer, lenp, ppos);
2564 fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
2565 return 0;
2566 } else
2567 return -EINVAL; 2608 return -EINVAL;
2609
2610 net = (struct net *)ctl->extra1;
2611 delay = net->ipv6.sysctl.flush_delay;
2612 proc_dointvec(ctl, write, buffer, lenp, ppos);
2613 fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
2614 return 0;
2568} 2615}
2569 2616
2570ctl_table ipv6_route_table_template[] = { 2617ctl_table ipv6_route_table_template[] = {
@@ -2651,6 +2698,7 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
2651 2698
2652 if (table) { 2699 if (table) {
2653 table[0].data = &net->ipv6.sysctl.flush_delay; 2700 table[0].data = &net->ipv6.sysctl.flush_delay;
2701 table[0].extra1 = net;
2654 table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh; 2702 table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh;
2655 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; 2703 table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
2656 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; 2704 table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
@@ -2684,7 +2732,8 @@ static int __net_init ip6_route_net_init(struct net *net)
2684 net->ipv6.ip6_null_entry->dst.path = 2732 net->ipv6.ip6_null_entry->dst.path =
2685 (struct dst_entry *)net->ipv6.ip6_null_entry; 2733 (struct dst_entry *)net->ipv6.ip6_null_entry;
2686 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2734 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2687 dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255); 2735 dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
2736 ip6_template_metrics, true);
2688 2737
2689#ifdef CONFIG_IPV6_MULTIPLE_TABLES 2738#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2690 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, 2739 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2695,7 +2744,8 @@ static int __net_init ip6_route_net_init(struct net *net)
2695 net->ipv6.ip6_prohibit_entry->dst.path = 2744 net->ipv6.ip6_prohibit_entry->dst.path =
2696 (struct dst_entry *)net->ipv6.ip6_prohibit_entry; 2745 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
2697 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2746 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2698 dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255); 2747 dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
2748 ip6_template_metrics, true);
2699 2749
2700 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, 2750 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
2701 sizeof(*net->ipv6.ip6_blk_hole_entry), 2751 sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2705,7 +2755,8 @@ static int __net_init ip6_route_net_init(struct net *net)
2705 net->ipv6.ip6_blk_hole_entry->dst.path = 2755 net->ipv6.ip6_blk_hole_entry->dst.path =
2706 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; 2756 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
2707 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2757 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2708 dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255); 2758 dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
2759 ip6_template_metrics, true);
2709#endif 2760#endif
2710 2761
2711 net->ipv6.sysctl.flush_delay = 0; 2762 net->ipv6.sysctl.flush_delay = 0;