diff options
Diffstat (limited to 'net/ipv6')
33 files changed, 632 insertions, 624 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e1a698df5706..e81155d2f251 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -121,8 +121,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); |
122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | 122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); |
123 | static void ipv6_regen_rndid(unsigned long data); | 123 | static void ipv6_regen_rndid(unsigned long data); |
124 | |||
125 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | ||
126 | #endif | 124 | #endif |
127 | 125 | ||
128 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); | 126 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); |
@@ -284,13 +282,16 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
284 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 282 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
285 | { | 283 | { |
286 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, | 284 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
287 | sizeof(struct ipstats_mib)) < 0) | 285 | sizeof(struct ipstats_mib), |
286 | __alignof__(struct ipstats_mib)) < 0) | ||
288 | goto err_ip; | 287 | goto err_ip; |
289 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, | 288 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
290 | sizeof(struct icmpv6_mib)) < 0) | 289 | sizeof(struct icmpv6_mib), |
290 | __alignof__(struct icmpv6_mib)) < 0) | ||
291 | goto err_icmp; | 291 | goto err_icmp; |
292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, | 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
293 | sizeof(struct icmpv6msg_mib)) < 0) | 293 | sizeof(struct icmpv6msg_mib), |
294 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
294 | goto err_icmpmsg; | 295 | goto err_icmpmsg; |
295 | 296 | ||
296 | return 0; | 297 | return 0; |
@@ -557,7 +558,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
557 | pr_warning("Freeing alive inet6 address %p\n", ifp); | 558 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
558 | return; | 559 | return; |
559 | } | 560 | } |
560 | dst_release(&ifp->rt->u.dst); | 561 | dst_release(&ifp->rt->dst); |
561 | 562 | ||
562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); | 563 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
563 | } | 564 | } |
@@ -823,7 +824,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
823 | rt->rt6i_flags |= RTF_EXPIRES; | 824 | rt->rt6i_flags |= RTF_EXPIRES; |
824 | } | 825 | } |
825 | } | 826 | } |
826 | dst_release(&rt->u.dst); | 827 | dst_release(&rt->dst); |
827 | } | 828 | } |
828 | 829 | ||
829 | out: | 830 | out: |
@@ -890,7 +891,8 @@ retry: | |||
890 | idev->cnf.temp_valid_lft); | 891 | idev->cnf.temp_valid_lft); |
891 | tmp_prefered_lft = min_t(__u32, | 892 | tmp_prefered_lft = min_t(__u32, |
892 | ifp->prefered_lft, | 893 | ifp->prefered_lft, |
893 | idev->cnf.temp_prefered_lft - desync_factor / HZ); | 894 | idev->cnf.temp_prefered_lft - |
895 | idev->cnf.max_desync_factor); | ||
894 | tmp_plen = ifp->prefix_len; | 896 | tmp_plen = ifp->prefix_len; |
895 | max_addresses = idev->cnf.max_addresses; | 897 | max_addresses = idev->cnf.max_addresses; |
896 | tmp_cstamp = ifp->cstamp; | 898 | tmp_cstamp = ifp->cstamp; |
@@ -1650,7 +1652,8 @@ static void ipv6_regen_rndid(unsigned long data) | |||
1650 | 1652 | ||
1651 | expires = jiffies + | 1653 | expires = jiffies + |
1652 | idev->cnf.temp_prefered_lft * HZ - | 1654 | idev->cnf.temp_prefered_lft * HZ - |
1653 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor; | 1655 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - |
1656 | idev->cnf.max_desync_factor * HZ; | ||
1654 | if (time_before(expires, jiffies)) { | 1657 | if (time_before(expires, jiffies)) { |
1655 | printk(KERN_WARNING | 1658 | printk(KERN_WARNING |
1656 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", | 1659 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", |
@@ -1863,7 +1866,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1863 | dev, expires, flags); | 1866 | dev, expires, flags); |
1864 | } | 1867 | } |
1865 | if (rt) | 1868 | if (rt) |
1866 | dst_release(&rt->u.dst); | 1869 | dst_release(&rt->dst); |
1867 | } | 1870 | } |
1868 | 1871 | ||
1869 | /* Try to figure out our local address for this prefix */ | 1872 | /* Try to figure out our local address for this prefix */ |
@@ -3492,8 +3495,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3492 | preferred -= tval; | 3495 | preferred -= tval; |
3493 | else | 3496 | else |
3494 | preferred = 0; | 3497 | preferred = 0; |
3495 | if (valid != INFINITY_LIFE_TIME) | 3498 | if (valid != INFINITY_LIFE_TIME) { |
3496 | valid -= tval; | 3499 | if (valid > tval) |
3500 | valid -= tval; | ||
3501 | else | ||
3502 | valid = 0; | ||
3503 | } | ||
3497 | } | 3504 | } |
3498 | } else { | 3505 | } else { |
3499 | preferred = INFINITY_LIFE_TIME; | 3506 | preferred = INFINITY_LIFE_TIME; |
@@ -3855,12 +3862,28 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3855 | memset(&stats[items], 0, pad); | 3862 | memset(&stats[items], 0, pad); |
3856 | } | 3863 | } |
3857 | 3864 | ||
3865 | static inline void __snmp6_fill_stats64(u64 *stats, void __percpu **mib, | ||
3866 | int items, int bytes, size_t syncpoff) | ||
3867 | { | ||
3868 | int i; | ||
3869 | int pad = bytes - sizeof(u64) * items; | ||
3870 | BUG_ON(pad < 0); | ||
3871 | |||
3872 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
3873 | put_unaligned(items, &stats[0]); | ||
3874 | for (i = 1; i < items; i++) | ||
3875 | put_unaligned(snmp_fold_field64(mib, i, syncpoff), &stats[i]); | ||
3876 | |||
3877 | memset(&stats[items], 0, pad); | ||
3878 | } | ||
3879 | |||
3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3880 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
3859 | int bytes) | 3881 | int bytes) |
3860 | { | 3882 | { |
3861 | switch (attrtype) { | 3883 | switch (attrtype) { |
3862 | case IFLA_INET6_STATS: | 3884 | case IFLA_INET6_STATS: |
3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3885 | __snmp6_fill_stats64(stats, (void __percpu **)idev->stats.ipv6, |
3886 | IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); | ||
3864 | break; | 3887 | break; |
3865 | case IFLA_INET6_ICMP6STATS: | 3888 | case IFLA_INET6_ICMP6STATS: |
3866 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3889 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
@@ -4093,11 +4116,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4093 | if (ifp->idev->cnf.forwarding) | 4116 | if (ifp->idev->cnf.forwarding) |
4094 | addrconf_leave_anycast(ifp); | 4117 | addrconf_leave_anycast(ifp); |
4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4118 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4096 | dst_hold(&ifp->rt->u.dst); | 4119 | dst_hold(&ifp->rt->dst); |
4097 | 4120 | ||
4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | 4121 | if (ifp->state == INET6_IFADDR_STATE_DEAD && |
4099 | ip6_del_rt(ifp->rt)) | 4122 | ip6_del_rt(ifp->rt)) |
4100 | dst_free(&ifp->rt->u.dst); | 4123 | dst_free(&ifp->rt->dst); |
4101 | break; | 4124 | break; |
4102 | } | 4125 | } |
4103 | } | 4126 | } |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 8c4348cb1950..f0e774cea386 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -53,11 +53,7 @@ static struct ip6addrlbl_table | |||
53 | static inline | 53 | static inline |
54 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) | 54 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) |
55 | { | 55 | { |
56 | #ifdef CONFIG_NET_NS | 56 | return read_pnet(&lbl->lbl_net); |
57 | return lbl->lbl_net; | ||
58 | #else | ||
59 | return &init_net; | ||
60 | #endif | ||
61 | } | 57 | } |
62 | 58 | ||
63 | /* | 59 | /* |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e733942dafe1..56b9bf2516f4 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -522,10 +522,10 @@ const struct proto_ops inet6_stream_ops = { | |||
522 | .shutdown = inet_shutdown, /* ok */ | 522 | .shutdown = inet_shutdown, /* ok */ |
523 | .setsockopt = sock_common_setsockopt, /* ok */ | 523 | .setsockopt = sock_common_setsockopt, /* ok */ |
524 | .getsockopt = sock_common_getsockopt, /* ok */ | 524 | .getsockopt = sock_common_getsockopt, /* ok */ |
525 | .sendmsg = tcp_sendmsg, /* ok */ | 525 | .sendmsg = inet_sendmsg, /* ok */ |
526 | .recvmsg = sock_common_recvmsg, /* ok */ | 526 | .recvmsg = inet_recvmsg, /* ok */ |
527 | .mmap = sock_no_mmap, | 527 | .mmap = sock_no_mmap, |
528 | .sendpage = tcp_sendpage, | 528 | .sendpage = inet_sendpage, |
529 | .splice_read = tcp_splice_read, | 529 | .splice_read = tcp_splice_read, |
530 | #ifdef CONFIG_COMPAT | 530 | #ifdef CONFIG_COMPAT |
531 | .compat_setsockopt = compat_sock_common_setsockopt, | 531 | .compat_setsockopt = compat_sock_common_setsockopt, |
@@ -549,7 +549,7 @@ const struct proto_ops inet6_dgram_ops = { | |||
549 | .setsockopt = sock_common_setsockopt, /* ok */ | 549 | .setsockopt = sock_common_setsockopt, /* ok */ |
550 | .getsockopt = sock_common_getsockopt, /* ok */ | 550 | .getsockopt = sock_common_getsockopt, /* ok */ |
551 | .sendmsg = inet_sendmsg, /* ok */ | 551 | .sendmsg = inet_sendmsg, /* ok */ |
552 | .recvmsg = sock_common_recvmsg, /* ok */ | 552 | .recvmsg = inet_recvmsg, /* ok */ |
553 | .mmap = sock_no_mmap, | 553 | .mmap = sock_no_mmap, |
554 | .sendpage = sock_no_sendpage, | 554 | .sendpage = sock_no_sendpage, |
555 | #ifdef CONFIG_COMPAT | 555 | #ifdef CONFIG_COMPAT |
@@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
651 | 651 | ||
652 | if (dst == NULL) { | 652 | if (dst == NULL) { |
653 | struct inet_sock *inet = inet_sk(sk); | 653 | struct inet_sock *inet = inet_sk(sk); |
654 | struct in6_addr *final_p = NULL, final; | 654 | struct in6_addr *final_p, final; |
655 | struct flowi fl; | 655 | struct flowi fl; |
656 | 656 | ||
657 | memset(&fl, 0, sizeof(fl)); | 657 | memset(&fl, 0, sizeof(fl)); |
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
665 | fl.fl_ip_sport = inet->inet_sport; | 665 | fl.fl_ip_sport = inet->inet_sport; |
666 | security_sk_classify_flow(sk, &fl); | 666 | security_sk_classify_flow(sk, &fl); |
667 | 667 | ||
668 | if (np->opt && np->opt->srcrt) { | 668 | final_p = fl6_update_dst(&fl, np->opt, &final); |
669 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
670 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
671 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
672 | final_p = &final; | ||
673 | } | ||
674 | 669 | ||
675 | err = ip6_dst_lookup(sk, &dst, &fl); | 670 | err = ip6_dst_lookup(sk, &dst, &fl); |
676 | if (err) { | 671 | if (err) { |
@@ -976,19 +971,24 @@ static void ipv6_packet_cleanup(void) | |||
976 | static int __net_init ipv6_init_mibs(struct net *net) | 971 | static int __net_init ipv6_init_mibs(struct net *net) |
977 | { | 972 | { |
978 | if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, | 973 | if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, |
979 | sizeof (struct udp_mib)) < 0) | 974 | sizeof(struct udp_mib), |
975 | __alignof__(struct udp_mib)) < 0) | ||
980 | return -ENOMEM; | 976 | return -ENOMEM; |
981 | if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, | 977 | if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, |
982 | sizeof (struct udp_mib)) < 0) | 978 | sizeof(struct udp_mib), |
979 | __alignof__(struct udp_mib)) < 0) | ||
983 | goto err_udplite_mib; | 980 | goto err_udplite_mib; |
984 | if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, | 981 | if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, |
985 | sizeof(struct ipstats_mib)) < 0) | 982 | sizeof(struct ipstats_mib), |
983 | __alignof__(struct ipstats_mib)) < 0) | ||
986 | goto err_ip_mib; | 984 | goto err_ip_mib; |
987 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, | 985 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, |
988 | sizeof(struct icmpv6_mib)) < 0) | 986 | sizeof(struct icmpv6_mib), |
987 | __alignof__(struct icmpv6_mib)) < 0) | ||
989 | goto err_icmp_mib; | 988 | goto err_icmp_mib; |
990 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, | 989 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, |
991 | sizeof(struct icmpv6msg_mib)) < 0) | 990 | sizeof(struct icmpv6msg_mib), |
991 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
992 | goto err_icmpmsg_mib; | 992 | goto err_icmpmsg_mib; |
993 | return 0; | 993 | return 0; |
994 | 994 | ||
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index b5b07054508a..0e5e943446f0 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -77,41 +77,40 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
77 | pac->acl_next = NULL; | 77 | pac->acl_next = NULL; |
78 | ipv6_addr_copy(&pac->acl_addr, addr); | 78 | ipv6_addr_copy(&pac->acl_addr, addr); |
79 | 79 | ||
80 | rcu_read_lock(); | ||
80 | if (ifindex == 0) { | 81 | if (ifindex == 0) { |
81 | struct rt6_info *rt; | 82 | struct rt6_info *rt; |
82 | 83 | ||
83 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 84 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
84 | if (rt) { | 85 | if (rt) { |
85 | dev = rt->rt6i_dev; | 86 | dev = rt->rt6i_dev; |
86 | dev_hold(dev); | 87 | dst_release(&rt->dst); |
87 | dst_release(&rt->u.dst); | ||
88 | } else if (ishost) { | 88 | } else if (ishost) { |
89 | err = -EADDRNOTAVAIL; | 89 | err = -EADDRNOTAVAIL; |
90 | goto out_free_pac; | 90 | goto error; |
91 | } else { | 91 | } else { |
92 | /* router, no matching interface: just pick one */ | 92 | /* router, no matching interface: just pick one */ |
93 | 93 | dev = dev_get_by_flags_rcu(net, IFF_UP, | |
94 | dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK); | 94 | IFF_UP | IFF_LOOPBACK); |
95 | } | 95 | } |
96 | } else | 96 | } else |
97 | dev = dev_get_by_index(net, ifindex); | 97 | dev = dev_get_by_index_rcu(net, ifindex); |
98 | 98 | ||
99 | if (dev == NULL) { | 99 | if (dev == NULL) { |
100 | err = -ENODEV; | 100 | err = -ENODEV; |
101 | goto out_free_pac; | 101 | goto error; |
102 | } | 102 | } |
103 | 103 | ||
104 | idev = in6_dev_get(dev); | 104 | idev = __in6_dev_get(dev); |
105 | if (!idev) { | 105 | if (!idev) { |
106 | if (ifindex) | 106 | if (ifindex) |
107 | err = -ENODEV; | 107 | err = -ENODEV; |
108 | else | 108 | else |
109 | err = -EADDRNOTAVAIL; | 109 | err = -EADDRNOTAVAIL; |
110 | goto out_dev_put; | 110 | goto error; |
111 | } | 111 | } |
112 | /* reset ishost, now that we have a specific device */ | 112 | /* reset ishost, now that we have a specific device */ |
113 | ishost = !idev->cnf.forwarding; | 113 | ishost = !idev->cnf.forwarding; |
114 | in6_dev_put(idev); | ||
115 | 114 | ||
116 | pac->acl_ifindex = dev->ifindex; | 115 | pac->acl_ifindex = dev->ifindex; |
117 | 116 | ||
@@ -124,26 +123,22 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
124 | if (ishost) | 123 | if (ishost) |
125 | err = -EADDRNOTAVAIL; | 124 | err = -EADDRNOTAVAIL; |
126 | if (err) | 125 | if (err) |
127 | goto out_dev_put; | 126 | goto error; |
128 | } | 127 | } |
129 | 128 | ||
130 | err = ipv6_dev_ac_inc(dev, addr); | 129 | err = ipv6_dev_ac_inc(dev, addr); |
131 | if (err) | 130 | if (!err) { |
132 | goto out_dev_put; | 131 | write_lock_bh(&ipv6_sk_ac_lock); |
133 | 132 | pac->acl_next = np->ipv6_ac_list; | |
134 | write_lock_bh(&ipv6_sk_ac_lock); | 133 | np->ipv6_ac_list = pac; |
135 | pac->acl_next = np->ipv6_ac_list; | 134 | write_unlock_bh(&ipv6_sk_ac_lock); |
136 | np->ipv6_ac_list = pac; | 135 | pac = NULL; |
137 | write_unlock_bh(&ipv6_sk_ac_lock); | 136 | } |
138 | |||
139 | dev_put(dev); | ||
140 | |||
141 | return 0; | ||
142 | 137 | ||
143 | out_dev_put: | 138 | error: |
144 | dev_put(dev); | 139 | rcu_read_unlock(); |
145 | out_free_pac: | 140 | if (pac) |
146 | sock_kfree_s(sk, pac, sizeof(*pac)); | 141 | sock_kfree_s(sk, pac, sizeof(*pac)); |
147 | return err; | 142 | return err; |
148 | } | 143 | } |
149 | 144 | ||
@@ -176,11 +171,12 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
176 | 171 | ||
177 | write_unlock_bh(&ipv6_sk_ac_lock); | 172 | write_unlock_bh(&ipv6_sk_ac_lock); |
178 | 173 | ||
179 | dev = dev_get_by_index(net, pac->acl_ifindex); | 174 | rcu_read_lock(); |
180 | if (dev) { | 175 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
176 | if (dev) | ||
181 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 177 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
182 | dev_put(dev); | 178 | rcu_read_unlock(); |
183 | } | 179 | |
184 | sock_kfree_s(sk, pac, sizeof(*pac)); | 180 | sock_kfree_s(sk, pac, sizeof(*pac)); |
185 | return 0; | 181 | return 0; |
186 | } | 182 | } |
@@ -199,13 +195,12 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
199 | write_unlock_bh(&ipv6_sk_ac_lock); | 195 | write_unlock_bh(&ipv6_sk_ac_lock); |
200 | 196 | ||
201 | prev_index = 0; | 197 | prev_index = 0; |
198 | rcu_read_lock(); | ||
202 | while (pac) { | 199 | while (pac) { |
203 | struct ipv6_ac_socklist *next = pac->acl_next; | 200 | struct ipv6_ac_socklist *next = pac->acl_next; |
204 | 201 | ||
205 | if (pac->acl_ifindex != prev_index) { | 202 | if (pac->acl_ifindex != prev_index) { |
206 | if (dev) | 203 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
207 | dev_put(dev); | ||
208 | dev = dev_get_by_index(net, pac->acl_ifindex); | ||
209 | prev_index = pac->acl_ifindex; | 204 | prev_index = pac->acl_ifindex; |
210 | } | 205 | } |
211 | if (dev) | 206 | if (dev) |
@@ -213,8 +208,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
213 | sock_kfree_s(sk, pac, sizeof(*pac)); | 208 | sock_kfree_s(sk, pac, sizeof(*pac)); |
214 | pac = next; | 209 | pac = next; |
215 | } | 210 | } |
216 | if (dev) | 211 | rcu_read_unlock(); |
217 | dev_put(dev); | ||
218 | } | 212 | } |
219 | 213 | ||
220 | #if 0 | 214 | #if 0 |
@@ -250,7 +244,7 @@ static void aca_put(struct ifacaddr6 *ac) | |||
250 | { | 244 | { |
251 | if (atomic_dec_and_test(&ac->aca_refcnt)) { | 245 | if (atomic_dec_and_test(&ac->aca_refcnt)) { |
252 | in6_dev_put(ac->aca_idev); | 246 | in6_dev_put(ac->aca_idev); |
253 | dst_release(&ac->aca_rt->u.dst); | 247 | dst_release(&ac->aca_rt->dst); |
254 | kfree(ac); | 248 | kfree(ac); |
255 | } | 249 | } |
256 | } | 250 | } |
@@ -356,40 +350,39 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) | |||
356 | write_unlock_bh(&idev->lock); | 350 | write_unlock_bh(&idev->lock); |
357 | addrconf_leave_solict(idev, &aca->aca_addr); | 351 | addrconf_leave_solict(idev, &aca->aca_addr); |
358 | 352 | ||
359 | dst_hold(&aca->aca_rt->u.dst); | 353 | dst_hold(&aca->aca_rt->dst); |
360 | ip6_del_rt(aca->aca_rt); | 354 | ip6_del_rt(aca->aca_rt); |
361 | 355 | ||
362 | aca_put(aca); | 356 | aca_put(aca); |
363 | return 0; | 357 | return 0; |
364 | } | 358 | } |
365 | 359 | ||
360 | /* called with rcu_read_lock() */ | ||
366 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) | 361 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) |
367 | { | 362 | { |
368 | int ret; | 363 | struct inet6_dev *idev = __in6_dev_get(dev); |
369 | struct inet6_dev *idev = in6_dev_get(dev); | 364 | |
370 | if (idev == NULL) | 365 | if (idev == NULL) |
371 | return -ENODEV; | 366 | return -ENODEV; |
372 | ret = __ipv6_dev_ac_dec(idev, addr); | 367 | return __ipv6_dev_ac_dec(idev, addr); |
373 | in6_dev_put(idev); | ||
374 | return ret; | ||
375 | } | 368 | } |
376 | 369 | ||
377 | /* | 370 | /* |
378 | * check if the interface has this anycast address | 371 | * check if the interface has this anycast address |
372 | * called with rcu_read_lock() | ||
379 | */ | 373 | */ |
380 | static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | 374 | static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) |
381 | { | 375 | { |
382 | struct inet6_dev *idev; | 376 | struct inet6_dev *idev; |
383 | struct ifacaddr6 *aca; | 377 | struct ifacaddr6 *aca; |
384 | 378 | ||
385 | idev = in6_dev_get(dev); | 379 | idev = __in6_dev_get(dev); |
386 | if (idev) { | 380 | if (idev) { |
387 | read_lock_bh(&idev->lock); | 381 | read_lock_bh(&idev->lock); |
388 | for (aca = idev->ac_list; aca; aca = aca->aca_next) | 382 | for (aca = idev->ac_list; aca; aca = aca->aca_next) |
389 | if (ipv6_addr_equal(&aca->aca_addr, addr)) | 383 | if (ipv6_addr_equal(&aca->aca_addr, addr)) |
390 | break; | 384 | break; |
391 | read_unlock_bh(&idev->lock); | 385 | read_unlock_bh(&idev->lock); |
392 | in6_dev_put(idev); | ||
393 | return aca != NULL; | 386 | return aca != NULL; |
394 | } | 387 | } |
395 | return 0; | 388 | return 0; |
@@ -403,14 +396,15 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | |||
403 | { | 396 | { |
404 | int found = 0; | 397 | int found = 0; |
405 | 398 | ||
406 | if (dev) | ||
407 | return ipv6_chk_acast_dev(dev, addr); | ||
408 | rcu_read_lock(); | 399 | rcu_read_lock(); |
409 | for_each_netdev_rcu(net, dev) | 400 | if (dev) |
410 | if (ipv6_chk_acast_dev(dev, addr)) { | 401 | found = ipv6_chk_acast_dev(dev, addr); |
411 | found = 1; | 402 | else |
412 | break; | 403 | for_each_netdev_rcu(net, dev) |
413 | } | 404 | if (ipv6_chk_acast_dev(dev, addr)) { |
405 | found = 1; | ||
406 | break; | ||
407 | } | ||
414 | rcu_read_unlock(); | 408 | rcu_read_unlock(); |
415 | return found; | 409 | return found; |
416 | } | 410 | } |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 712684687c9a..7d929a22cbc2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
39 | struct inet_sock *inet = inet_sk(sk); | 39 | struct inet_sock *inet = inet_sk(sk); |
40 | struct ipv6_pinfo *np = inet6_sk(sk); | 40 | struct ipv6_pinfo *np = inet6_sk(sk); |
41 | struct in6_addr *daddr, *final_p = NULL, final; | 41 | struct in6_addr *daddr, *final_p, final; |
42 | struct dst_entry *dst; | 42 | struct dst_entry *dst; |
43 | struct flowi fl; | 43 | struct flowi fl; |
44 | struct ip6_flowlabel *flowlabel = NULL; | 44 | struct ip6_flowlabel *flowlabel = NULL; |
45 | struct ipv6_txoptions *opt; | ||
45 | int addr_type; | 46 | int addr_type; |
46 | int err; | 47 | int err; |
47 | 48 | ||
@@ -155,19 +156,8 @@ ipv4_connected: | |||
155 | 156 | ||
156 | security_sk_classify_flow(sk, &fl); | 157 | security_sk_classify_flow(sk, &fl); |
157 | 158 | ||
158 | if (flowlabel) { | 159 | opt = flowlabel ? flowlabel->opt : np->opt; |
159 | if (flowlabel->opt && flowlabel->opt->srcrt) { | 160 | final_p = fl6_update_dst(&fl, opt, &final); |
160 | struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; | ||
161 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
162 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
163 | final_p = &final; | ||
164 | } | ||
165 | } else if (np->opt && np->opt->srcrt) { | ||
166 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
167 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
168 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
169 | final_p = &final; | ||
170 | } | ||
171 | 161 | ||
172 | err = ip6_dst_lookup(sk, &dst, &fl); | 162 | err = ip6_dst_lookup(sk, &dst, &fl); |
173 | if (err) | 163 | if (err) |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 8a659f92d17a..262f105d23b9 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -312,6 +312,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) | |||
312 | Routing header. | 312 | Routing header. |
313 | ********************************/ | 313 | ********************************/ |
314 | 314 | ||
315 | /* called with rcu_read_lock() */ | ||
315 | static int ipv6_rthdr_rcv(struct sk_buff *skb) | 316 | static int ipv6_rthdr_rcv(struct sk_buff *skb) |
316 | { | 317 | { |
317 | struct inet6_skb_parm *opt = IP6CB(skb); | 318 | struct inet6_skb_parm *opt = IP6CB(skb); |
@@ -324,12 +325,9 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) | |||
324 | struct net *net = dev_net(skb->dev); | 325 | struct net *net = dev_net(skb->dev); |
325 | int accept_source_route = net->ipv6.devconf_all->accept_source_route; | 326 | int accept_source_route = net->ipv6.devconf_all->accept_source_route; |
326 | 327 | ||
327 | idev = in6_dev_get(skb->dev); | 328 | idev = __in6_dev_get(skb->dev); |
328 | if (idev) { | 329 | if (idev && accept_source_route > idev->cnf.accept_source_route) |
329 | if (accept_source_route > idev->cnf.accept_source_route) | 330 | accept_source_route = idev->cnf.accept_source_route; |
330 | accept_source_route = idev->cnf.accept_source_route; | ||
331 | in6_dev_put(idev); | ||
332 | } | ||
333 | 331 | ||
334 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || | 332 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
335 | !pskb_may_pull(skb, (skb_transport_offset(skb) + | 333 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
@@ -874,3 +872,27 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, | |||
874 | return opt; | 872 | return opt; |
875 | } | 873 | } |
876 | 874 | ||
875 | /** | ||
876 | * fl6_update_dst - update flowi destination address with info given | ||
877 | * by srcrt option, if any. | ||
878 | * | ||
879 | * @fl: flowi for which fl6_dst is to be updated | ||
880 | * @opt: struct ipv6_txoptions in which to look for srcrt opt | ||
881 | * @orig: copy of original fl6_dst address if modified | ||
882 | * | ||
883 | * Returns NULL if no txoptions or no srcrt, otherwise returns orig | ||
884 | * and initial value of fl->fl6_dst set in orig | ||
885 | */ | ||
886 | struct in6_addr *fl6_update_dst(struct flowi *fl, | ||
887 | const struct ipv6_txoptions *opt, | ||
888 | struct in6_addr *orig) | ||
889 | { | ||
890 | if (!opt || !opt->srcrt) | ||
891 | return NULL; | ||
892 | |||
893 | ipv6_addr_copy(orig, &fl->fl6_dst); | ||
894 | ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr); | ||
895 | return orig; | ||
896 | } | ||
897 | |||
898 | EXPORT_SYMBOL_GPL(fl6_update_dst); | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 8e44f8f9c188..b1108ede18e1 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | |||
43 | if (arg.result) | 43 | if (arg.result) |
44 | return arg.result; | 44 | return arg.result; |
45 | 45 | ||
46 | dst_hold(&net->ipv6.ip6_null_entry->u.dst); | 46 | dst_hold(&net->ipv6.ip6_null_entry->dst); |
47 | return &net->ipv6.ip6_null_entry->u.dst; | 47 | return &net->ipv6.ip6_null_entry->dst; |
48 | } | 48 | } |
49 | 49 | ||
50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
@@ -86,7 +86,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
86 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
87 | 87 | ||
88 | if (ipv6_dev_get_saddr(net, | 88 | if (ipv6_dev_get_saddr(net, |
89 | ip6_dst_idev(&rt->u.dst)->dev, | 89 | ip6_dst_idev(&rt->dst)->dev, |
90 | &flp->fl6_dst, | 90 | &flp->fl6_dst, |
91 | rt6_flags2srcprefs(flags), | 91 | rt6_flags2srcprefs(flags), |
92 | &saddr)) | 92 | &saddr)) |
@@ -99,12 +99,12 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
99 | goto out; | 99 | goto out; |
100 | } | 100 | } |
101 | again: | 101 | again: |
102 | dst_release(&rt->u.dst); | 102 | dst_release(&rt->dst); |
103 | rt = NULL; | 103 | rt = NULL; |
104 | goto out; | 104 | goto out; |
105 | 105 | ||
106 | discard_pkt: | 106 | discard_pkt: |
107 | dst_hold(&rt->u.dst); | 107 | dst_hold(&rt->dst); |
108 | out: | 108 | out: |
109 | arg->result = rt; | 109 | arg->result = rt; |
110 | return rt == NULL ? -EAGAIN : 0; | 110 | return rt == NULL ? -EAGAIN : 0; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index ce7992982557..03e62f94ff8e 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -483,7 +483,7 @@ route_done: | |||
483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, | 483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, |
484 | MSG_DONTWAIT, np->dontfrag); | 484 | MSG_DONTWAIT, np->dontfrag); |
485 | if (err) { | 485 | if (err) { |
486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
487 | ip6_flush_pending_frames(sk); | 487 | ip6_flush_pending_frames(sk); |
488 | goto out_put; | 488 | goto out_put; |
489 | } | 489 | } |
@@ -565,7 +565,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
565 | np->dontfrag); | 565 | np->dontfrag); |
566 | 566 | ||
567 | if (err) { | 567 | if (err) { |
568 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 568 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
569 | ip6_flush_pending_frames(sk); | 569 | ip6_flush_pending_frames(sk); |
570 | goto out_put; | 570 | goto out_put; |
571 | } | 571 | } |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 0c5e3c3b7fd5..8a1628023bd1 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
185 | struct ipv6_pinfo *np = inet6_sk(sk); | 185 | struct ipv6_pinfo *np = inet6_sk(sk); |
186 | struct flowi fl; | 186 | struct flowi fl; |
187 | struct dst_entry *dst; | 187 | struct dst_entry *dst; |
188 | struct in6_addr *final_p = NULL, final; | 188 | struct in6_addr *final_p, final; |
189 | 189 | ||
190 | memset(&fl, 0, sizeof(fl)); | 190 | memset(&fl, 0, sizeof(fl)); |
191 | fl.proto = sk->sk_protocol; | 191 | fl.proto = sk->sk_protocol; |
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
199 | fl.fl_ip_dport = inet->inet_dport; | 199 | fl.fl_ip_dport = inet->inet_dport; |
200 | security_sk_classify_flow(sk, &fl); | 200 | security_sk_classify_flow(sk, &fl); |
201 | 201 | ||
202 | if (np->opt && np->opt->srcrt) { | 202 | final_p = fl6_update_dst(&fl, np->opt, &final); |
203 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
204 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
205 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
206 | final_p = &final; | ||
207 | } | ||
208 | 203 | ||
209 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 204 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
210 | 205 | ||
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 92a122b7795d..b6a585909d35 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -165,7 +165,7 @@ static __inline__ void node_free(struct fib6_node * fn) | |||
165 | static __inline__ void rt6_release(struct rt6_info *rt) | 165 | static __inline__ void rt6_release(struct rt6_info *rt) |
166 | { | 166 | { |
167 | if (atomic_dec_and_test(&rt->rt6i_ref)) | 167 | if (atomic_dec_and_test(&rt->rt6i_ref)) |
168 | dst_free(&rt->u.dst); | 168 | dst_free(&rt->dst); |
169 | } | 169 | } |
170 | 170 | ||
171 | static void fib6_link_table(struct net *net, struct fib6_table *tb) | 171 | static void fib6_link_table(struct net *net, struct fib6_table *tb) |
@@ -278,7 +278,7 @@ static int fib6_dump_node(struct fib6_walker_t *w) | |||
278 | int res; | 278 | int res; |
279 | struct rt6_info *rt; | 279 | struct rt6_info *rt; |
280 | 280 | ||
281 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 281 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { |
282 | res = rt6_dump_route(rt, w->args); | 282 | res = rt6_dump_route(rt, w->args); |
283 | if (res < 0) { | 283 | if (res < 0) { |
284 | /* Frame is full, suspend walking */ | 284 | /* Frame is full, suspend walking */ |
@@ -619,7 +619,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
619 | 619 | ||
620 | ins = &fn->leaf; | 620 | ins = &fn->leaf; |
621 | 621 | ||
622 | for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) { | 622 | for (iter = fn->leaf; iter; iter=iter->dst.rt6_next) { |
623 | /* | 623 | /* |
624 | * Search for duplicates | 624 | * Search for duplicates |
625 | */ | 625 | */ |
@@ -647,7 +647,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
647 | if (iter->rt6i_metric > rt->rt6i_metric) | 647 | if (iter->rt6i_metric > rt->rt6i_metric) |
648 | break; | 648 | break; |
649 | 649 | ||
650 | ins = &iter->u.dst.rt6_next; | 650 | ins = &iter->dst.rt6_next; |
651 | } | 651 | } |
652 | 652 | ||
653 | /* Reset round-robin state, if necessary */ | 653 | /* Reset round-robin state, if necessary */ |
@@ -658,7 +658,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
658 | * insert node | 658 | * insert node |
659 | */ | 659 | */ |
660 | 660 | ||
661 | rt->u.dst.rt6_next = iter; | 661 | rt->dst.rt6_next = iter; |
662 | *ins = rt; | 662 | *ins = rt; |
663 | rt->rt6i_node = fn; | 663 | rt->rt6i_node = fn; |
664 | atomic_inc(&rt->rt6i_ref); | 664 | atomic_inc(&rt->rt6i_ref); |
@@ -799,7 +799,7 @@ out: | |||
799 | atomic_inc(&pn->leaf->rt6i_ref); | 799 | atomic_inc(&pn->leaf->rt6i_ref); |
800 | } | 800 | } |
801 | #endif | 801 | #endif |
802 | dst_free(&rt->u.dst); | 802 | dst_free(&rt->dst); |
803 | } | 803 | } |
804 | return err; | 804 | return err; |
805 | 805 | ||
@@ -810,7 +810,7 @@ out: | |||
810 | st_failure: | 810 | st_failure: |
811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) | 811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
812 | fib6_repair_tree(info->nl_net, fn); | 812 | fib6_repair_tree(info->nl_net, fn); |
813 | dst_free(&rt->u.dst); | 813 | dst_free(&rt->dst); |
814 | return err; | 814 | return err; |
815 | #endif | 815 | #endif |
816 | } | 816 | } |
@@ -1108,7 +1108,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1108 | RT6_TRACE("fib6_del_route\n"); | 1108 | RT6_TRACE("fib6_del_route\n"); |
1109 | 1109 | ||
1110 | /* Unlink it */ | 1110 | /* Unlink it */ |
1111 | *rtp = rt->u.dst.rt6_next; | 1111 | *rtp = rt->dst.rt6_next; |
1112 | rt->rt6i_node = NULL; | 1112 | rt->rt6i_node = NULL; |
1113 | net->ipv6.rt6_stats->fib_rt_entries--; | 1113 | net->ipv6.rt6_stats->fib_rt_entries--; |
1114 | net->ipv6.rt6_stats->fib_discarded_routes++; | 1114 | net->ipv6.rt6_stats->fib_discarded_routes++; |
@@ -1122,14 +1122,14 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1122 | FOR_WALKERS(w) { | 1122 | FOR_WALKERS(w) { |
1123 | if (w->state == FWS_C && w->leaf == rt) { | 1123 | if (w->state == FWS_C && w->leaf == rt) { |
1124 | RT6_TRACE("walker %p adjusted by delroute\n", w); | 1124 | RT6_TRACE("walker %p adjusted by delroute\n", w); |
1125 | w->leaf = rt->u.dst.rt6_next; | 1125 | w->leaf = rt->dst.rt6_next; |
1126 | if (w->leaf == NULL) | 1126 | if (w->leaf == NULL) |
1127 | w->state = FWS_U; | 1127 | w->state = FWS_U; |
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | read_unlock(&fib6_walker_lock); | 1130 | read_unlock(&fib6_walker_lock); |
1131 | 1131 | ||
1132 | rt->u.dst.rt6_next = NULL; | 1132 | rt->dst.rt6_next = NULL; |
1133 | 1133 | ||
1134 | /* If it was last route, expunge its radix tree node */ | 1134 | /* If it was last route, expunge its radix tree node */ |
1135 | if (fn->leaf == NULL) { | 1135 | if (fn->leaf == NULL) { |
@@ -1168,7 +1168,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1168 | struct rt6_info **rtp; | 1168 | struct rt6_info **rtp; |
1169 | 1169 | ||
1170 | #if RT6_DEBUG >= 2 | 1170 | #if RT6_DEBUG >= 2 |
1171 | if (rt->u.dst.obsolete>0) { | 1171 | if (rt->dst.obsolete>0) { |
1172 | WARN_ON(fn != NULL); | 1172 | WARN_ON(fn != NULL); |
1173 | return -ENOENT; | 1173 | return -ENOENT; |
1174 | } | 1174 | } |
@@ -1195,7 +1195,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1195 | * Walk the leaf entries looking for ourself | 1195 | * Walk the leaf entries looking for ourself |
1196 | */ | 1196 | */ |
1197 | 1197 | ||
1198 | for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.dst.rt6_next) { | 1198 | for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) { |
1199 | if (*rtp == rt) { | 1199 | if (*rtp == rt) { |
1200 | fib6_del_route(fn, rtp, info); | 1200 | fib6_del_route(fn, rtp, info); |
1201 | return 0; | 1201 | return 0; |
@@ -1334,7 +1334,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) | |||
1334 | .nl_net = c->net, | 1334 | .nl_net = c->net, |
1335 | }; | 1335 | }; |
1336 | 1336 | ||
1337 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 1337 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { |
1338 | res = c->func(rt, c->arg); | 1338 | res = c->func(rt, c->arg); |
1339 | if (res < 0) { | 1339 | if (res < 0) { |
1340 | w->leaf = rt; | 1340 | w->leaf = rt; |
@@ -1448,8 +1448,8 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1448 | } | 1448 | } |
1449 | gc_args.more++; | 1449 | gc_args.more++; |
1450 | } else if (rt->rt6i_flags & RTF_CACHE) { | 1450 | } else if (rt->rt6i_flags & RTF_CACHE) { |
1451 | if (atomic_read(&rt->u.dst.__refcnt) == 0 && | 1451 | if (atomic_read(&rt->dst.__refcnt) == 0 && |
1452 | time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) { | 1452 | time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) { |
1453 | RT6_TRACE("aging clone %p\n", rt); | 1453 | RT6_TRACE("aging clone %p\n", rt); |
1454 | return -1; | 1454 | return -1; |
1455 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1455 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index cd963f64e27c..d40b330c0ee6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -507,7 +507,7 @@ int ip6_forward(struct sk_buff *skb) | |||
507 | if (mtu < IPV6_MIN_MTU) | 507 | if (mtu < IPV6_MIN_MTU) |
508 | mtu = IPV6_MIN_MTU; | 508 | mtu = IPV6_MIN_MTU; |
509 | 509 | ||
510 | if (skb->len > mtu) { | 510 | if (skb->len > mtu && !skb_is_gso(skb)) { |
511 | /* Again, force OUTPUT device used as source address */ | 511 | /* Again, force OUTPUT device used as source address */ |
512 | skb->dev = dst->dev; | 512 | skb->dev = dst->dev; |
513 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 513 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
@@ -698,7 +698,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
698 | ipv6_hdr(skb)->payload_len = htons(first_len - | 698 | ipv6_hdr(skb)->payload_len = htons(first_len - |
699 | sizeof(struct ipv6hdr)); | 699 | sizeof(struct ipv6hdr)); |
700 | 700 | ||
701 | dst_hold(&rt->u.dst); | 701 | dst_hold(&rt->dst); |
702 | 702 | ||
703 | for (;;) { | 703 | for (;;) { |
704 | /* Prepare header of the next frame, | 704 | /* Prepare header of the next frame, |
@@ -726,7 +726,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
726 | 726 | ||
727 | err = output(skb); | 727 | err = output(skb); |
728 | if(!err) | 728 | if(!err) |
729 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 729 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
730 | IPSTATS_MIB_FRAGCREATES); | 730 | IPSTATS_MIB_FRAGCREATES); |
731 | 731 | ||
732 | if (err || !frag) | 732 | if (err || !frag) |
@@ -740,9 +740,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
740 | kfree(tmp_hdr); | 740 | kfree(tmp_hdr); |
741 | 741 | ||
742 | if (err == 0) { | 742 | if (err == 0) { |
743 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 743 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
744 | IPSTATS_MIB_FRAGOKS); | 744 | IPSTATS_MIB_FRAGOKS); |
745 | dst_release(&rt->u.dst); | 745 | dst_release(&rt->dst); |
746 | return 0; | 746 | return 0; |
747 | } | 747 | } |
748 | 748 | ||
@@ -752,9 +752,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
752 | frag = skb; | 752 | frag = skb; |
753 | } | 753 | } |
754 | 754 | ||
755 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 755 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
756 | IPSTATS_MIB_FRAGFAILS); | 756 | IPSTATS_MIB_FRAGFAILS); |
757 | dst_release(&rt->u.dst); | 757 | dst_release(&rt->dst); |
758 | return err; | 758 | return err; |
759 | } | 759 | } |
760 | 760 | ||
@@ -785,7 +785,7 @@ slow_path: | |||
785 | * Allocate buffer. | 785 | * Allocate buffer. |
786 | */ | 786 | */ |
787 | 787 | ||
788 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { | 788 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { |
789 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 789 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
790 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 790 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
791 | IPSTATS_MIB_FRAGFAILS); | 791 | IPSTATS_MIB_FRAGFAILS); |
@@ -798,7 +798,7 @@ slow_path: | |||
798 | */ | 798 | */ |
799 | 799 | ||
800 | ip6_copy_metadata(frag, skb); | 800 | ip6_copy_metadata(frag, skb); |
801 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); | 801 | skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); |
802 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 802 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
803 | skb_reset_network_header(frag); | 803 | skb_reset_network_header(frag); |
804 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); | 804 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
@@ -1156,24 +1156,24 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1156 | 1156 | ||
1157 | /* need source address above miyazawa*/ | 1157 | /* need source address above miyazawa*/ |
1158 | } | 1158 | } |
1159 | dst_hold(&rt->u.dst); | 1159 | dst_hold(&rt->dst); |
1160 | inet->cork.dst = &rt->u.dst; | 1160 | inet->cork.dst = &rt->dst; |
1161 | inet->cork.fl = *fl; | 1161 | inet->cork.fl = *fl; |
1162 | np->cork.hop_limit = hlimit; | 1162 | np->cork.hop_limit = hlimit; |
1163 | np->cork.tclass = tclass; | 1163 | np->cork.tclass = tclass; |
1164 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1164 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
1165 | rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); | 1165 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); |
1166 | if (np->frag_size < mtu) { | 1166 | if (np->frag_size < mtu) { |
1167 | if (np->frag_size) | 1167 | if (np->frag_size) |
1168 | mtu = np->frag_size; | 1168 | mtu = np->frag_size; |
1169 | } | 1169 | } |
1170 | inet->cork.fragsize = mtu; | 1170 | inet->cork.fragsize = mtu; |
1171 | if (dst_allfrag(rt->u.dst.path)) | 1171 | if (dst_allfrag(rt->dst.path)) |
1172 | inet->cork.flags |= IPCORK_ALLFRAG; | 1172 | inet->cork.flags |= IPCORK_ALLFRAG; |
1173 | inet->cork.length = 0; | 1173 | inet->cork.length = 0; |
1174 | sk->sk_sndmsg_page = NULL; | 1174 | sk->sk_sndmsg_page = NULL; |
1175 | sk->sk_sndmsg_off = 0; | 1175 | sk->sk_sndmsg_off = 0; |
1176 | exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0) - | 1176 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - |
1177 | rt->rt6i_nfheader_len; | 1177 | rt->rt6i_nfheader_len; |
1178 | length += exthdrlen; | 1178 | length += exthdrlen; |
1179 | transhdrlen += exthdrlen; | 1179 | transhdrlen += exthdrlen; |
@@ -1186,7 +1186,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1186 | mtu = inet->cork.fragsize; | 1186 | mtu = inet->cork.fragsize; |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); | 1189 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
1190 | 1190 | ||
1191 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + | 1191 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + |
1192 | (opt ? opt->opt_nflen : 0); | 1192 | (opt ? opt->opt_nflen : 0); |
@@ -1224,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | if (proto == IPPROTO_UDP && | 1226 | if (proto == IPPROTO_UDP && |
1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1227 | (rt->dst.dev->features & NETIF_F_UFO)) { |
1228 | 1228 | ||
1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1230 | hh_len, fragheaderlen, | 1230 | hh_len, fragheaderlen, |
@@ -1270,7 +1270,7 @@ alloc_new_skb: | |||
1270 | 1270 | ||
1271 | fraglen = datalen + fragheaderlen; | 1271 | fraglen = datalen + fragheaderlen; |
1272 | if ((flags & MSG_MORE) && | 1272 | if ((flags & MSG_MORE) && |
1273 | !(rt->u.dst.dev->features&NETIF_F_SG)) | 1273 | !(rt->dst.dev->features&NETIF_F_SG)) |
1274 | alloclen = mtu; | 1274 | alloclen = mtu; |
1275 | else | 1275 | else |
1276 | alloclen = datalen + fragheaderlen; | 1276 | alloclen = datalen + fragheaderlen; |
@@ -1281,7 +1281,7 @@ alloc_new_skb: | |||
1281 | * because we have no idea if we're the last one. | 1281 | * because we have no idea if we're the last one. |
1282 | */ | 1282 | */ |
1283 | if (datalen == length + fraggap) | 1283 | if (datalen == length + fraggap) |
1284 | alloclen += rt->u.dst.trailer_len; | 1284 | alloclen += rt->dst.trailer_len; |
1285 | 1285 | ||
1286 | /* | 1286 | /* |
1287 | * We just reserve space for fragment header. | 1287 | * We just reserve space for fragment header. |
@@ -1358,7 +1358,7 @@ alloc_new_skb: | |||
1358 | if (copy > length) | 1358 | if (copy > length) |
1359 | copy = length; | 1359 | copy = length; |
1360 | 1360 | ||
1361 | if (!(rt->u.dst.dev->features&NETIF_F_SG)) { | 1361 | if (!(rt->dst.dev->features&NETIF_F_SG)) { |
1362 | unsigned int off; | 1362 | unsigned int off; |
1363 | 1363 | ||
1364 | off = skb->len; | 1364 | off = skb->len; |
@@ -1503,7 +1503,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1503 | skb->priority = sk->sk_priority; | 1503 | skb->priority = sk->sk_priority; |
1504 | skb->mark = sk->sk_mark; | 1504 | skb->mark = sk->sk_mark; |
1505 | 1505 | ||
1506 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 1506 | skb_dst_set(skb, dst_clone(&rt->dst)); |
1507 | IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 1507 | IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
1508 | if (proto == IPPROTO_ICMPV6) { | 1508 | if (proto == IPPROTO_ICMPV6) { |
1509 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 1509 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 8f39893d8081..0fd027f3f47e 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -552,7 +552,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
552 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) | 552 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) |
553 | goto out; | 553 | goto out; |
554 | 554 | ||
555 | skb2->dev = rt->u.dst.dev; | 555 | skb2->dev = rt->dst.dev; |
556 | 556 | ||
557 | /* route "incoming" packet */ | 557 | /* route "incoming" packet */ |
558 | if (rt->rt_flags & RTCF_LOCAL) { | 558 | if (rt->rt_flags & RTCF_LOCAL) { |
@@ -562,7 +562,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
562 | fl.fl4_src = eiph->saddr; | 562 | fl.fl4_src = eiph->saddr; |
563 | fl.fl4_tos = eiph->tos; | 563 | fl.fl4_tos = eiph->tos; |
564 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | 564 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || |
565 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | 565 | rt->dst.dev->type != ARPHRD_TUNNEL) { |
566 | ip_rt_put(rt); | 566 | ip_rt_put(rt); |
567 | goto out; | 567 | goto out; |
568 | } | 568 | } |
@@ -626,7 +626,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
626 | icmpv6_send(skb2, rel_type, rel_code, rel_info); | 626 | icmpv6_send(skb2, rel_type, rel_code, rel_info); |
627 | 627 | ||
628 | if (rt) | 628 | if (rt) |
629 | dst_release(&rt->u.dst); | 629 | dst_release(&rt->dst); |
630 | 630 | ||
631 | kfree_skb(skb2); | 631 | kfree_skb(skb2); |
632 | } | 632 | } |
@@ -1135,7 +1135,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1135 | if (dev->mtu < IPV6_MIN_MTU) | 1135 | if (dev->mtu < IPV6_MIN_MTU) |
1136 | dev->mtu = IPV6_MIN_MTU; | 1136 | dev->mtu = IPV6_MIN_MTU; |
1137 | } | 1137 | } |
1138 | dst_release(&rt->u.dst); | 1138 | dst_release(&rt->dst); |
1139 | } | 1139 | } |
1140 | } | 1140 | } |
1141 | 1141 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index bd9e7d3e9c8e..66078dad7fe8 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt); | |||
120 | static void ipmr_expire_process(unsigned long arg); | 120 | static void ipmr_expire_process(unsigned long arg); |
121 | 121 | ||
122 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | 122 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES |
123 | #define ip6mr_for_each_table(mrt, met) \ | 123 | #define ip6mr_for_each_table(mrt, net) \ |
124 | list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) | 124 | list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) |
125 | 125 | ||
126 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | 126 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) |
@@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net) | |||
254 | { | 254 | { |
255 | struct mr6_table *mrt, *next; | 255 | struct mr6_table *mrt, *next; |
256 | 256 | ||
257 | list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) | 257 | list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { |
258 | list_del(&mrt->list); | ||
258 | ip6mr_free_table(mrt); | 259 | ip6mr_free_table(mrt); |
260 | } | ||
259 | fib_rules_unregister(net->ipv6.mr6_rules_ops); | 261 | fib_rules_unregister(net->ipv6.mr6_rules_ops); |
260 | } | 262 | } |
261 | #else | 263 | #else |
@@ -2017,7 +2019,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | |||
2017 | struct rtattr *mp_head; | 2019 | struct rtattr *mp_head; |
2018 | 2020 | ||
2019 | /* If cache is unresolved, don't try to parse IIF and OIF */ | 2021 | /* If cache is unresolved, don't try to parse IIF and OIF */ |
2020 | if (c->mf6c_parent > MAXMIFS) | 2022 | if (c->mf6c_parent >= MAXMIFS) |
2021 | return -ENOENT; | 2023 | return -ENOENT; |
2022 | 2024 | ||
2023 | if (MIF_EXISTS(mrt, c->mf6c_parent)) | 2025 | if (MIF_EXISTS(mrt, c->mf6c_parent)) |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index bd43f0152c21..a7f66bc8f0b0 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -55,8 +55,6 @@ | |||
55 | 55 | ||
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
57 | 57 | ||
58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; | ||
59 | |||
60 | struct ip6_ra_chain *ip6_ra_chain; | 58 | struct ip6_ra_chain *ip6_ra_chain; |
61 | DEFINE_RWLOCK(ip6_ra_lock); | 59 | DEFINE_RWLOCK(ip6_ra_lock); |
62 | 60 | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 59f1881968c7..d1444b95ad7e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -152,18 +152,19 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
152 | mc_lst->next = NULL; | 152 | mc_lst->next = NULL; |
153 | ipv6_addr_copy(&mc_lst->addr, addr); | 153 | ipv6_addr_copy(&mc_lst->addr, addr); |
154 | 154 | ||
155 | rcu_read_lock(); | ||
155 | if (ifindex == 0) { | 156 | if (ifindex == 0) { |
156 | struct rt6_info *rt; | 157 | struct rt6_info *rt; |
157 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 158 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
158 | if (rt) { | 159 | if (rt) { |
159 | dev = rt->rt6i_dev; | 160 | dev = rt->rt6i_dev; |
160 | dev_hold(dev); | 161 | dst_release(&rt->dst); |
161 | dst_release(&rt->u.dst); | ||
162 | } | 162 | } |
163 | } else | 163 | } else |
164 | dev = dev_get_by_index(net, ifindex); | 164 | dev = dev_get_by_index_rcu(net, ifindex); |
165 | 165 | ||
166 | if (dev == NULL) { | 166 | if (dev == NULL) { |
167 | rcu_read_unlock(); | ||
167 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 168 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
168 | return -ENODEV; | 169 | return -ENODEV; |
169 | } | 170 | } |
@@ -180,8 +181,8 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
180 | err = ipv6_dev_mc_inc(dev, addr); | 181 | err = ipv6_dev_mc_inc(dev, addr); |
181 | 182 | ||
182 | if (err) { | 183 | if (err) { |
184 | rcu_read_unlock(); | ||
183 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 185 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
184 | dev_put(dev); | ||
185 | return err; | 186 | return err; |
186 | } | 187 | } |
187 | 188 | ||
@@ -190,7 +191,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
190 | np->ipv6_mc_list = mc_lst; | 191 | np->ipv6_mc_list = mc_lst; |
191 | write_unlock_bh(&ipv6_sk_mc_lock); | 192 | write_unlock_bh(&ipv6_sk_mc_lock); |
192 | 193 | ||
193 | dev_put(dev); | 194 | rcu_read_unlock(); |
194 | 195 | ||
195 | return 0; | 196 | return 0; |
196 | } | 197 | } |
@@ -213,18 +214,17 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
213 | *lnk = mc_lst->next; | 214 | *lnk = mc_lst->next; |
214 | write_unlock_bh(&ipv6_sk_mc_lock); | 215 | write_unlock_bh(&ipv6_sk_mc_lock); |
215 | 216 | ||
216 | dev = dev_get_by_index(net, mc_lst->ifindex); | 217 | rcu_read_lock(); |
218 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | ||
217 | if (dev != NULL) { | 219 | if (dev != NULL) { |
218 | struct inet6_dev *idev = in6_dev_get(dev); | 220 | struct inet6_dev *idev = __in6_dev_get(dev); |
219 | 221 | ||
220 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 222 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
221 | if (idev) { | 223 | if (idev) |
222 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 224 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
223 | in6_dev_put(idev); | ||
224 | } | ||
225 | dev_put(dev); | ||
226 | } else | 225 | } else |
227 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 226 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
227 | rcu_read_unlock(); | ||
228 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 228 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
229 | return 0; | 229 | return 0; |
230 | } | 230 | } |
@@ -234,43 +234,36 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
234 | return -EADDRNOTAVAIL; | 234 | return -EADDRNOTAVAIL; |
235 | } | 235 | } |
236 | 236 | ||
237 | static struct inet6_dev *ip6_mc_find_dev(struct net *net, | 237 | /* called with rcu_read_lock() */ |
238 | struct in6_addr *group, | 238 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, |
239 | int ifindex) | 239 | struct in6_addr *group, |
240 | int ifindex) | ||
240 | { | 241 | { |
241 | struct net_device *dev = NULL; | 242 | struct net_device *dev = NULL; |
242 | struct inet6_dev *idev = NULL; | 243 | struct inet6_dev *idev = NULL; |
243 | 244 | ||
244 | if (ifindex == 0) { | 245 | if (ifindex == 0) { |
245 | struct rt6_info *rt; | 246 | struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0); |
246 | 247 | ||
247 | rt = rt6_lookup(net, group, NULL, 0, 0); | ||
248 | if (rt) { | 248 | if (rt) { |
249 | dev = rt->rt6i_dev; | 249 | dev = rt->rt6i_dev; |
250 | dev_hold(dev); | 250 | dev_hold(dev); |
251 | dst_release(&rt->u.dst); | 251 | dst_release(&rt->dst); |
252 | } | 252 | } |
253 | } else | 253 | } else |
254 | dev = dev_get_by_index(net, ifindex); | 254 | dev = dev_get_by_index_rcu(net, ifindex); |
255 | 255 | ||
256 | if (!dev) | 256 | if (!dev) |
257 | goto nodev; | 257 | return NULL; |
258 | idev = in6_dev_get(dev); | 258 | idev = __in6_dev_get(dev); |
259 | if (!idev) | 259 | if (!idev) |
260 | goto release; | 260 | return NULL;; |
261 | read_lock_bh(&idev->lock); | 261 | read_lock_bh(&idev->lock); |
262 | if (idev->dead) | 262 | if (idev->dead) { |
263 | goto unlock_release; | 263 | read_unlock_bh(&idev->lock); |
264 | 264 | return NULL; | |
265 | } | ||
265 | return idev; | 266 | return idev; |
266 | |||
267 | unlock_release: | ||
268 | read_unlock_bh(&idev->lock); | ||
269 | in6_dev_put(idev); | ||
270 | release: | ||
271 | dev_put(dev); | ||
272 | nodev: | ||
273 | return NULL; | ||
274 | } | 267 | } |
275 | 268 | ||
276 | void ipv6_sock_mc_close(struct sock *sk) | 269 | void ipv6_sock_mc_close(struct sock *sk) |
@@ -286,19 +279,17 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
286 | np->ipv6_mc_list = mc_lst->next; | 279 | np->ipv6_mc_list = mc_lst->next; |
287 | write_unlock_bh(&ipv6_sk_mc_lock); | 280 | write_unlock_bh(&ipv6_sk_mc_lock); |
288 | 281 | ||
289 | dev = dev_get_by_index(net, mc_lst->ifindex); | 282 | rcu_read_lock(); |
283 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | ||
290 | if (dev) { | 284 | if (dev) { |
291 | struct inet6_dev *idev = in6_dev_get(dev); | 285 | struct inet6_dev *idev = __in6_dev_get(dev); |
292 | 286 | ||
293 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 287 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
294 | if (idev) { | 288 | if (idev) |
295 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 289 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
296 | in6_dev_put(idev); | ||
297 | } | ||
298 | dev_put(dev); | ||
299 | } else | 290 | } else |
300 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 291 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
301 | 292 | rcu_read_unlock(); | |
302 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 293 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
303 | 294 | ||
304 | write_lock_bh(&ipv6_sk_mc_lock); | 295 | write_lock_bh(&ipv6_sk_mc_lock); |
@@ -327,14 +318,17 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
327 | if (!ipv6_addr_is_multicast(group)) | 318 | if (!ipv6_addr_is_multicast(group)) |
328 | return -EINVAL; | 319 | return -EINVAL; |
329 | 320 | ||
330 | idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface); | 321 | rcu_read_lock(); |
331 | if (!idev) | 322 | idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface); |
323 | if (!idev) { | ||
324 | rcu_read_unlock(); | ||
332 | return -ENODEV; | 325 | return -ENODEV; |
326 | } | ||
333 | dev = idev->dev; | 327 | dev = idev->dev; |
334 | 328 | ||
335 | err = -EADDRNOTAVAIL; | 329 | err = -EADDRNOTAVAIL; |
336 | 330 | ||
337 | read_lock_bh(&ipv6_sk_mc_lock); | 331 | read_lock(&ipv6_sk_mc_lock); |
338 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | 332 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { |
339 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) | 333 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) |
340 | continue; | 334 | continue; |
@@ -358,7 +352,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
358 | pmc->sfmode = omode; | 352 | pmc->sfmode = omode; |
359 | } | 353 | } |
360 | 354 | ||
361 | write_lock_bh(&pmc->sflock); | 355 | write_lock(&pmc->sflock); |
362 | pmclocked = 1; | 356 | pmclocked = 1; |
363 | 357 | ||
364 | psl = pmc->sflist; | 358 | psl = pmc->sflist; |
@@ -433,11 +427,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
433 | ip6_mc_add_src(idev, group, omode, 1, source, 1); | 427 | ip6_mc_add_src(idev, group, omode, 1, source, 1); |
434 | done: | 428 | done: |
435 | if (pmclocked) | 429 | if (pmclocked) |
436 | write_unlock_bh(&pmc->sflock); | 430 | write_unlock(&pmc->sflock); |
437 | read_unlock_bh(&ipv6_sk_mc_lock); | 431 | read_unlock(&ipv6_sk_mc_lock); |
438 | read_unlock_bh(&idev->lock); | 432 | read_unlock_bh(&idev->lock); |
439 | in6_dev_put(idev); | 433 | rcu_read_unlock(); |
440 | dev_put(dev); | ||
441 | if (leavegroup) | 434 | if (leavegroup) |
442 | return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); | 435 | return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); |
443 | return err; | 436 | return err; |
@@ -463,14 +456,17 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
463 | gsf->gf_fmode != MCAST_EXCLUDE) | 456 | gsf->gf_fmode != MCAST_EXCLUDE) |
464 | return -EINVAL; | 457 | return -EINVAL; |
465 | 458 | ||
466 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); | 459 | rcu_read_lock(); |
460 | idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); | ||
467 | 461 | ||
468 | if (!idev) | 462 | if (!idev) { |
463 | rcu_read_unlock(); | ||
469 | return -ENODEV; | 464 | return -ENODEV; |
465 | } | ||
470 | dev = idev->dev; | 466 | dev = idev->dev; |
471 | 467 | ||
472 | err = 0; | 468 | err = 0; |
473 | read_lock_bh(&ipv6_sk_mc_lock); | 469 | read_lock(&ipv6_sk_mc_lock); |
474 | 470 | ||
475 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { | 471 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { |
476 | leavegroup = 1; | 472 | leavegroup = 1; |
@@ -512,7 +508,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
512 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); | 508 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); |
513 | } | 509 | } |
514 | 510 | ||
515 | write_lock_bh(&pmc->sflock); | 511 | write_lock(&pmc->sflock); |
516 | psl = pmc->sflist; | 512 | psl = pmc->sflist; |
517 | if (psl) { | 513 | if (psl) { |
518 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, | 514 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, |
@@ -522,13 +518,12 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
522 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); | 518 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); |
523 | pmc->sflist = newpsl; | 519 | pmc->sflist = newpsl; |
524 | pmc->sfmode = gsf->gf_fmode; | 520 | pmc->sfmode = gsf->gf_fmode; |
525 | write_unlock_bh(&pmc->sflock); | 521 | write_unlock(&pmc->sflock); |
526 | err = 0; | 522 | err = 0; |
527 | done: | 523 | done: |
528 | read_unlock_bh(&ipv6_sk_mc_lock); | 524 | read_unlock(&ipv6_sk_mc_lock); |
529 | read_unlock_bh(&idev->lock); | 525 | read_unlock_bh(&idev->lock); |
530 | in6_dev_put(idev); | 526 | rcu_read_unlock(); |
531 | dev_put(dev); | ||
532 | if (leavegroup) | 527 | if (leavegroup) |
533 | err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); | 528 | err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); |
534 | return err; | 529 | return err; |
@@ -551,11 +546,13 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
551 | if (!ipv6_addr_is_multicast(group)) | 546 | if (!ipv6_addr_is_multicast(group)) |
552 | return -EINVAL; | 547 | return -EINVAL; |
553 | 548 | ||
554 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); | 549 | rcu_read_lock(); |
550 | idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); | ||
555 | 551 | ||
556 | if (!idev) | 552 | if (!idev) { |
553 | rcu_read_unlock(); | ||
557 | return -ENODEV; | 554 | return -ENODEV; |
558 | 555 | } | |
559 | dev = idev->dev; | 556 | dev = idev->dev; |
560 | 557 | ||
561 | err = -EADDRNOTAVAIL; | 558 | err = -EADDRNOTAVAIL; |
@@ -577,8 +574,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
577 | psl = pmc->sflist; | 574 | psl = pmc->sflist; |
578 | count = psl ? psl->sl_count : 0; | 575 | count = psl ? psl->sl_count : 0; |
579 | read_unlock_bh(&idev->lock); | 576 | read_unlock_bh(&idev->lock); |
580 | in6_dev_put(idev); | 577 | rcu_read_unlock(); |
581 | dev_put(dev); | ||
582 | 578 | ||
583 | copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; | 579 | copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; |
584 | gsf->gf_numsrc = count; | 580 | gsf->gf_numsrc = count; |
@@ -604,8 +600,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
604 | return 0; | 600 | return 0; |
605 | done: | 601 | done: |
606 | read_unlock_bh(&idev->lock); | 602 | read_unlock_bh(&idev->lock); |
607 | in6_dev_put(idev); | 603 | rcu_read_unlock(); |
608 | dev_put(dev); | ||
609 | return err; | 604 | return err; |
610 | } | 605 | } |
611 | 606 | ||
@@ -822,6 +817,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
822 | struct ifmcaddr6 *mc; | 817 | struct ifmcaddr6 *mc; |
823 | struct inet6_dev *idev; | 818 | struct inet6_dev *idev; |
824 | 819 | ||
820 | /* we need to take a reference on idev */ | ||
825 | idev = in6_dev_get(dev); | 821 | idev = in6_dev_get(dev); |
826 | 822 | ||
827 | if (idev == NULL) | 823 | if (idev == NULL) |
@@ -860,7 +856,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
860 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); | 856 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); |
861 | 857 | ||
862 | ipv6_addr_copy(&mc->mca_addr, addr); | 858 | ipv6_addr_copy(&mc->mca_addr, addr); |
863 | mc->idev = idev; | 859 | mc->idev = idev; /* (reference taken) */ |
864 | mc->mca_users = 1; | 860 | mc->mca_users = 1; |
865 | /* mca_stamp should be updated upon changes */ | 861 | /* mca_stamp should be updated upon changes */ |
866 | mc->mca_cstamp = mc->mca_tstamp = jiffies; | 862 | mc->mca_cstamp = mc->mca_tstamp = jiffies; |
@@ -915,16 +911,18 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
915 | 911 | ||
916 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) | 912 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) |
917 | { | 913 | { |
918 | struct inet6_dev *idev = in6_dev_get(dev); | 914 | struct inet6_dev *idev; |
919 | int err; | 915 | int err; |
920 | 916 | ||
921 | if (!idev) | 917 | rcu_read_lock(); |
922 | return -ENODEV; | ||
923 | |||
924 | err = __ipv6_dev_mc_dec(idev, addr); | ||
925 | 918 | ||
926 | in6_dev_put(idev); | 919 | idev = __in6_dev_get(dev); |
920 | if (!idev) | ||
921 | err = -ENODEV; | ||
922 | else | ||
923 | err = __ipv6_dev_mc_dec(idev, addr); | ||
927 | 924 | ||
925 | rcu_read_unlock(); | ||
928 | return err; | 926 | return err; |
929 | } | 927 | } |
930 | 928 | ||
@@ -965,7 +963,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, | |||
965 | struct ifmcaddr6 *mc; | 963 | struct ifmcaddr6 *mc; |
966 | int rv = 0; | 964 | int rv = 0; |
967 | 965 | ||
968 | idev = in6_dev_get(dev); | 966 | rcu_read_lock(); |
967 | idev = __in6_dev_get(dev); | ||
969 | if (idev) { | 968 | if (idev) { |
970 | read_lock_bh(&idev->lock); | 969 | read_lock_bh(&idev->lock); |
971 | for (mc = idev->mc_list; mc; mc=mc->next) { | 970 | for (mc = idev->mc_list; mc; mc=mc->next) { |
@@ -992,8 +991,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, | |||
992 | rv = 1; /* don't filter unspecified source */ | 991 | rv = 1; /* don't filter unspecified source */ |
993 | } | 992 | } |
994 | read_unlock_bh(&idev->lock); | 993 | read_unlock_bh(&idev->lock); |
995 | in6_dev_put(idev); | ||
996 | } | 994 | } |
995 | rcu_read_unlock(); | ||
997 | return rv; | 996 | return rv; |
998 | } | 997 | } |
999 | 998 | ||
@@ -1104,6 +1103,7 @@ static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
1104 | return 1; | 1103 | return 1; |
1105 | } | 1104 | } |
1106 | 1105 | ||
1106 | /* called with rcu_read_lock() */ | ||
1107 | int igmp6_event_query(struct sk_buff *skb) | 1107 | int igmp6_event_query(struct sk_buff *skb) |
1108 | { | 1108 | { |
1109 | struct mld2_query *mlh2 = NULL; | 1109 | struct mld2_query *mlh2 = NULL; |
@@ -1127,7 +1127,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1127 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) | 1127 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) |
1128 | return -EINVAL; | 1128 | return -EINVAL; |
1129 | 1129 | ||
1130 | idev = in6_dev_get(skb->dev); | 1130 | idev = __in6_dev_get(skb->dev); |
1131 | 1131 | ||
1132 | if (idev == NULL) | 1132 | if (idev == NULL) |
1133 | return 0; | 1133 | return 0; |
@@ -1137,10 +1137,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1137 | group_type = ipv6_addr_type(group); | 1137 | group_type = ipv6_addr_type(group); |
1138 | 1138 | ||
1139 | if (group_type != IPV6_ADDR_ANY && | 1139 | if (group_type != IPV6_ADDR_ANY && |
1140 | !(group_type&IPV6_ADDR_MULTICAST)) { | 1140 | !(group_type&IPV6_ADDR_MULTICAST)) |
1141 | in6_dev_put(idev); | ||
1142 | return -EINVAL; | 1141 | return -EINVAL; |
1143 | } | ||
1144 | 1142 | ||
1145 | if (len == 24) { | 1143 | if (len == 24) { |
1146 | int switchback; | 1144 | int switchback; |
@@ -1161,10 +1159,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1161 | } else if (len >= 28) { | 1159 | } else if (len >= 28) { |
1162 | int srcs_offset = sizeof(struct mld2_query) - | 1160 | int srcs_offset = sizeof(struct mld2_query) - |
1163 | sizeof(struct icmp6hdr); | 1161 | sizeof(struct icmp6hdr); |
1164 | if (!pskb_may_pull(skb, srcs_offset)) { | 1162 | if (!pskb_may_pull(skb, srcs_offset)) |
1165 | in6_dev_put(idev); | ||
1166 | return -EINVAL; | 1163 | return -EINVAL; |
1167 | } | 1164 | |
1168 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1165 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1169 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; | 1166 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; |
1170 | if (!max_delay) | 1167 | if (!max_delay) |
@@ -1173,28 +1170,23 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1173 | if (mlh2->mld2q_qrv) | 1170 | if (mlh2->mld2q_qrv) |
1174 | idev->mc_qrv = mlh2->mld2q_qrv; | 1171 | idev->mc_qrv = mlh2->mld2q_qrv; |
1175 | if (group_type == IPV6_ADDR_ANY) { /* general query */ | 1172 | if (group_type == IPV6_ADDR_ANY) { /* general query */ |
1176 | if (mlh2->mld2q_nsrcs) { | 1173 | if (mlh2->mld2q_nsrcs) |
1177 | in6_dev_put(idev); | ||
1178 | return -EINVAL; /* no sources allowed */ | 1174 | return -EINVAL; /* no sources allowed */ |
1179 | } | 1175 | |
1180 | mld_gq_start_timer(idev); | 1176 | mld_gq_start_timer(idev); |
1181 | in6_dev_put(idev); | ||
1182 | return 0; | 1177 | return 0; |
1183 | } | 1178 | } |
1184 | /* mark sources to include, if group & source-specific */ | 1179 | /* mark sources to include, if group & source-specific */ |
1185 | if (mlh2->mld2q_nsrcs != 0) { | 1180 | if (mlh2->mld2q_nsrcs != 0) { |
1186 | if (!pskb_may_pull(skb, srcs_offset + | 1181 | if (!pskb_may_pull(skb, srcs_offset + |
1187 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { | 1182 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) |
1188 | in6_dev_put(idev); | ||
1189 | return -EINVAL; | 1183 | return -EINVAL; |
1190 | } | 1184 | |
1191 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1185 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1192 | mark = 1; | 1186 | mark = 1; |
1193 | } | 1187 | } |
1194 | } else { | 1188 | } else |
1195 | in6_dev_put(idev); | ||
1196 | return -EINVAL; | 1189 | return -EINVAL; |
1197 | } | ||
1198 | 1190 | ||
1199 | read_lock_bh(&idev->lock); | 1191 | read_lock_bh(&idev->lock); |
1200 | if (group_type == IPV6_ADDR_ANY) { | 1192 | if (group_type == IPV6_ADDR_ANY) { |
@@ -1227,12 +1219,11 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1227 | } | 1219 | } |
1228 | } | 1220 | } |
1229 | read_unlock_bh(&idev->lock); | 1221 | read_unlock_bh(&idev->lock); |
1230 | in6_dev_put(idev); | ||
1231 | 1222 | ||
1232 | return 0; | 1223 | return 0; |
1233 | } | 1224 | } |
1234 | 1225 | ||
1235 | 1226 | /* called with rcu_read_lock() */ | |
1236 | int igmp6_event_report(struct sk_buff *skb) | 1227 | int igmp6_event_report(struct sk_buff *skb) |
1237 | { | 1228 | { |
1238 | struct ifmcaddr6 *ma; | 1229 | struct ifmcaddr6 *ma; |
@@ -1260,7 +1251,7 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1260 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1251 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
1261 | return -EINVAL; | 1252 | return -EINVAL; |
1262 | 1253 | ||
1263 | idev = in6_dev_get(skb->dev); | 1254 | idev = __in6_dev_get(skb->dev); |
1264 | if (idev == NULL) | 1255 | if (idev == NULL) |
1265 | return -ENODEV; | 1256 | return -ENODEV; |
1266 | 1257 | ||
@@ -1280,7 +1271,6 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1280 | } | 1271 | } |
1281 | } | 1272 | } |
1282 | read_unlock_bh(&idev->lock); | 1273 | read_unlock_bh(&idev->lock); |
1283 | in6_dev_put(idev); | ||
1284 | return 0; | 1274 | return 0; |
1285 | } | 1275 | } |
1286 | 1276 | ||
@@ -1356,7 +1346,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1356 | IPV6_TLV_PADN, 0 }; | 1346 | IPV6_TLV_PADN, 0 }; |
1357 | 1347 | ||
1358 | /* we assume size > sizeof(ra) here */ | 1348 | /* we assume size > sizeof(ra) here */ |
1359 | skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err); | 1349 | size += LL_ALLOCATED_SPACE(dev); |
1350 | /* limit our allocations to order-0 page */ | ||
1351 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); | ||
1352 | skb = sock_alloc_send_skb(sk, size, 1, &err); | ||
1360 | 1353 | ||
1361 | if (!skb) | 1354 | if (!skb) |
1362 | return NULL; | 1355 | return NULL; |
@@ -1393,12 +1386,14 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1393 | struct mld2_report *pmr = | 1386 | struct mld2_report *pmr = |
1394 | (struct mld2_report *)skb_transport_header(skb); | 1387 | (struct mld2_report *)skb_transport_header(skb); |
1395 | int payload_len, mldlen; | 1388 | int payload_len, mldlen; |
1396 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1389 | struct inet6_dev *idev; |
1397 | struct net *net = dev_net(skb->dev); | 1390 | struct net *net = dev_net(skb->dev); |
1398 | int err; | 1391 | int err; |
1399 | struct flowi fl; | 1392 | struct flowi fl; |
1400 | struct dst_entry *dst; | 1393 | struct dst_entry *dst; |
1401 | 1394 | ||
1395 | rcu_read_lock(); | ||
1396 | idev = __in6_dev_get(skb->dev); | ||
1402 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1397 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
1403 | 1398 | ||
1404 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); | 1399 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); |
@@ -1438,8 +1433,7 @@ out: | |||
1438 | } else | 1433 | } else |
1439 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); | 1434 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); |
1440 | 1435 | ||
1441 | if (likely(idev != NULL)) | 1436 | rcu_read_unlock(); |
1442 | in6_dev_put(idev); | ||
1443 | return; | 1437 | return; |
1444 | 1438 | ||
1445 | err_out: | 1439 | err_out: |
@@ -1776,7 +1770,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1776 | IPPROTO_ICMPV6, | 1770 | IPPROTO_ICMPV6, |
1777 | csum_partial(hdr, len, 0)); | 1771 | csum_partial(hdr, len, 0)); |
1778 | 1772 | ||
1779 | idev = in6_dev_get(skb->dev); | 1773 | rcu_read_lock(); |
1774 | idev = __in6_dev_get(skb->dev); | ||
1780 | 1775 | ||
1781 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | 1776 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); |
1782 | if (!dst) { | 1777 | if (!dst) { |
@@ -1803,8 +1798,7 @@ out: | |||
1803 | } else | 1798 | } else |
1804 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); | 1799 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); |
1805 | 1800 | ||
1806 | if (likely(idev != NULL)) | 1801 | rcu_read_unlock(); |
1807 | in6_dev_put(idev); | ||
1808 | return; | 1802 | return; |
1809 | 1803 | ||
1810 | err_out: | 1804 | err_out: |
@@ -1995,8 +1989,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc) | |||
1995 | &psf->sf_addr)) | 1989 | &psf->sf_addr)) |
1996 | break; | 1990 | break; |
1997 | if (!dpsf) { | 1991 | if (!dpsf) { |
1998 | dpsf = (struct ip6_sf_list *) | 1992 | dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC); |
1999 | kmalloc(sizeof(*dpsf), GFP_ATOMIC); | ||
2000 | if (!dpsf) | 1993 | if (!dpsf) |
2001 | continue; | 1994 | continue; |
2002 | *dpsf = *psf; | 1995 | *dpsf = *psf; |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 2794b6002836..d6e9599d0705 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -347,11 +347,12 @@ static const struct xfrm_type mip6_destopt_type = | |||
347 | 347 | ||
348 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) | 348 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) |
349 | { | 349 | { |
350 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
350 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; | 351 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; |
351 | int err = rt2->rt_hdr.nexthdr; | 352 | int err = rt2->rt_hdr.nexthdr; |
352 | 353 | ||
353 | spin_lock(&x->lock); | 354 | spin_lock(&x->lock); |
354 | if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) && | 355 | if (!ipv6_addr_equal(&iph->daddr, (struct in6_addr *)x->coaddr) && |
355 | !ipv6_addr_any((struct in6_addr *)x->coaddr)) | 356 | !ipv6_addr_any((struct in6_addr *)x->coaddr)) |
356 | err = -ENOENT; | 357 | err = -ENOENT; |
357 | spin_unlock(&x->lock); | 358 | spin_unlock(&x->lock); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0abdc242ddb7..58841c4ae947 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -586,6 +586,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
586 | src_addr = solicited_addr; | 586 | src_addr = solicited_addr; |
587 | if (ifp->flags & IFA_F_OPTIMISTIC) | 587 | if (ifp->flags & IFA_F_OPTIMISTIC) |
588 | override = 0; | 588 | override = 0; |
589 | inc_opt |= ifp->idev->cnf.force_tllao; | ||
589 | in6_ifa_put(ifp); | 590 | in6_ifa_put(ifp); |
590 | } else { | 591 | } else { |
591 | if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr, | 592 | if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr, |
@@ -599,7 +600,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
599 | icmp6h.icmp6_solicited = solicited; | 600 | icmp6h.icmp6_solicited = solicited; |
600 | icmp6h.icmp6_override = override; | 601 | icmp6h.icmp6_override = override; |
601 | 602 | ||
602 | inc_opt |= ifp->idev->cnf.force_tllao; | ||
603 | __ndisc_send(dev, neigh, daddr, src_addr, | 603 | __ndisc_send(dev, neigh, daddr, src_addr, |
604 | &icmp6h, solicited_addr, | 604 | &icmp6h, solicited_addr, |
605 | inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); | 605 | inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); |
@@ -1229,7 +1229,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1229 | ND_PRINTK0(KERN_ERR | 1229 | ND_PRINTK0(KERN_ERR |
1230 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1230 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
1231 | __func__); | 1231 | __func__); |
1232 | dst_release(&rt->u.dst); | 1232 | dst_release(&rt->dst); |
1233 | in6_dev_put(in6_dev); | 1233 | in6_dev_put(in6_dev); |
1234 | return; | 1234 | return; |
1235 | } | 1235 | } |
@@ -1244,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1244 | if (ra_msg->icmph.icmp6_hop_limit) { | 1244 | if (ra_msg->icmph.icmp6_hop_limit) { |
1245 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1245 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; |
1246 | if (rt) | 1246 | if (rt) |
1247 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; | 1247 | rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; |
1248 | } | 1248 | } |
1249 | 1249 | ||
1250 | skip_defrtr: | 1250 | skip_defrtr: |
@@ -1363,7 +1363,7 @@ skip_linkparms: | |||
1363 | in6_dev->cnf.mtu6 = mtu; | 1363 | in6_dev->cnf.mtu6 = mtu; |
1364 | 1364 | ||
1365 | if (rt) | 1365 | if (rt) |
1366 | rt->u.dst.metrics[RTAX_MTU-1] = mtu; | 1366 | rt->dst.metrics[RTAX_MTU-1] = mtu; |
1367 | 1367 | ||
1368 | rt6_mtu_change(skb->dev, mtu); | 1368 | rt6_mtu_change(skb->dev, mtu); |
1369 | } | 1369 | } |
@@ -1384,7 +1384,7 @@ skip_linkparms: | |||
1384 | } | 1384 | } |
1385 | out: | 1385 | out: |
1386 | if (rt) | 1386 | if (rt) |
1387 | dst_release(&rt->u.dst); | 1387 | dst_release(&rt->dst); |
1388 | else if (neigh) | 1388 | else if (neigh) |
1389 | neigh_release(neigh); | 1389 | neigh_release(neigh); |
1390 | in6_dev_put(in6_dev); | 1390 | in6_dev_put(in6_dev); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index a74951c039b6..7155b2451d7c 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -151,9 +151,7 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
151 | protocol, | 151 | protocol, |
152 | csum_sub(0, hsum))); | 152 | csum_sub(0, hsum))); |
153 | skb->ip_summed = CHECKSUM_NONE; | 153 | skb->ip_summed = CHECKSUM_NONE; |
154 | csum = __skb_checksum_complete_head(skb, dataoff + len); | 154 | return __skb_checksum_complete_head(skb, dataoff + len); |
155 | if (!csum) | ||
156 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
157 | } | 155 | } |
158 | return csum; | 156 | return csum; |
159 | }; | 157 | }; |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 8c201743d96d..413ab0754e1f 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -43,7 +43,7 @@ typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); | |||
43 | 43 | ||
44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; | 44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; |
45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; | 45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; |
46 | static DEFINE_RWLOCK(queue_lock); | 46 | static DEFINE_SPINLOCK(queue_lock); |
47 | static int peer_pid __read_mostly; | 47 | static int peer_pid __read_mostly; |
48 | static unsigned int copy_range __read_mostly; | 48 | static unsigned int copy_range __read_mostly; |
49 | static unsigned int queue_total; | 49 | static unsigned int queue_total; |
@@ -73,10 +73,10 @@ __ipq_set_mode(unsigned char mode, unsigned int range) | |||
73 | break; | 73 | break; |
74 | 74 | ||
75 | case IPQ_COPY_PACKET: | 75 | case IPQ_COPY_PACKET: |
76 | copy_mode = mode; | 76 | if (range > 0xFFFF) |
77 | range = 0xFFFF; | ||
77 | copy_range = range; | 78 | copy_range = range; |
78 | if (copy_range > 0xFFFF) | 79 | copy_mode = mode; |
79 | copy_range = 0xFFFF; | ||
80 | break; | 80 | break; |
81 | 81 | ||
82 | default: | 82 | default: |
@@ -102,7 +102,7 @@ ipq_find_dequeue_entry(unsigned long id) | |||
102 | { | 102 | { |
103 | struct nf_queue_entry *entry = NULL, *i; | 103 | struct nf_queue_entry *entry = NULL, *i; |
104 | 104 | ||
105 | write_lock_bh(&queue_lock); | 105 | spin_lock_bh(&queue_lock); |
106 | 106 | ||
107 | list_for_each_entry(i, &queue_list, list) { | 107 | list_for_each_entry(i, &queue_list, list) { |
108 | if ((unsigned long)i == id) { | 108 | if ((unsigned long)i == id) { |
@@ -116,7 +116,7 @@ ipq_find_dequeue_entry(unsigned long id) | |||
116 | queue_total--; | 116 | queue_total--; |
117 | } | 117 | } |
118 | 118 | ||
119 | write_unlock_bh(&queue_lock); | 119 | spin_unlock_bh(&queue_lock); |
120 | return entry; | 120 | return entry; |
121 | } | 121 | } |
122 | 122 | ||
@@ -137,9 +137,9 @@ __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | |||
137 | static void | 137 | static void |
138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
139 | { | 139 | { |
140 | write_lock_bh(&queue_lock); | 140 | spin_lock_bh(&queue_lock); |
141 | __ipq_flush(cmpfn, data); | 141 | __ipq_flush(cmpfn, data); |
142 | write_unlock_bh(&queue_lock); | 142 | spin_unlock_bh(&queue_lock); |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct sk_buff * | 145 | static struct sk_buff * |
@@ -153,9 +153,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
153 | struct nlmsghdr *nlh; | 153 | struct nlmsghdr *nlh; |
154 | struct timeval tv; | 154 | struct timeval tv; |
155 | 155 | ||
156 | read_lock_bh(&queue_lock); | 156 | switch (ACCESS_ONCE(copy_mode)) { |
157 | |||
158 | switch (copy_mode) { | ||
159 | case IPQ_COPY_META: | 157 | case IPQ_COPY_META: |
160 | case IPQ_COPY_NONE: | 158 | case IPQ_COPY_NONE: |
161 | size = NLMSG_SPACE(sizeof(*pmsg)); | 159 | size = NLMSG_SPACE(sizeof(*pmsg)); |
@@ -163,26 +161,21 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
163 | 161 | ||
164 | case IPQ_COPY_PACKET: | 162 | case IPQ_COPY_PACKET: |
165 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && | 163 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
166 | (*errp = skb_checksum_help(entry->skb))) { | 164 | (*errp = skb_checksum_help(entry->skb))) |
167 | read_unlock_bh(&queue_lock); | ||
168 | return NULL; | 165 | return NULL; |
169 | } | 166 | |
170 | if (copy_range == 0 || copy_range > entry->skb->len) | 167 | data_len = ACCESS_ONCE(copy_range); |
168 | if (data_len == 0 || data_len > entry->skb->len) | ||
171 | data_len = entry->skb->len; | 169 | data_len = entry->skb->len; |
172 | else | ||
173 | data_len = copy_range; | ||
174 | 170 | ||
175 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); | 171 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); |
176 | break; | 172 | break; |
177 | 173 | ||
178 | default: | 174 | default: |
179 | *errp = -EINVAL; | 175 | *errp = -EINVAL; |
180 | read_unlock_bh(&queue_lock); | ||
181 | return NULL; | 176 | return NULL; |
182 | } | 177 | } |
183 | 178 | ||
184 | read_unlock_bh(&queue_lock); | ||
185 | |||
186 | skb = alloc_skb(size, GFP_ATOMIC); | 179 | skb = alloc_skb(size, GFP_ATOMIC); |
187 | if (!skb) | 180 | if (!skb) |
188 | goto nlmsg_failure; | 181 | goto nlmsg_failure; |
@@ -242,7 +235,7 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
242 | if (nskb == NULL) | 235 | if (nskb == NULL) |
243 | return status; | 236 | return status; |
244 | 237 | ||
245 | write_lock_bh(&queue_lock); | 238 | spin_lock_bh(&queue_lock); |
246 | 239 | ||
247 | if (!peer_pid) | 240 | if (!peer_pid) |
248 | goto err_out_free_nskb; | 241 | goto err_out_free_nskb; |
@@ -266,14 +259,14 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
266 | 259 | ||
267 | __ipq_enqueue_entry(entry); | 260 | __ipq_enqueue_entry(entry); |
268 | 261 | ||
269 | write_unlock_bh(&queue_lock); | 262 | spin_unlock_bh(&queue_lock); |
270 | return status; | 263 | return status; |
271 | 264 | ||
272 | err_out_free_nskb: | 265 | err_out_free_nskb: |
273 | kfree_skb(nskb); | 266 | kfree_skb(nskb); |
274 | 267 | ||
275 | err_out_unlock: | 268 | err_out_unlock: |
276 | write_unlock_bh(&queue_lock); | 269 | spin_unlock_bh(&queue_lock); |
277 | return status; | 270 | return status; |
278 | } | 271 | } |
279 | 272 | ||
@@ -342,9 +335,9 @@ ipq_set_mode(unsigned char mode, unsigned int range) | |||
342 | { | 335 | { |
343 | int status; | 336 | int status; |
344 | 337 | ||
345 | write_lock_bh(&queue_lock); | 338 | spin_lock_bh(&queue_lock); |
346 | status = __ipq_set_mode(mode, range); | 339 | status = __ipq_set_mode(mode, range); |
347 | write_unlock_bh(&queue_lock); | 340 | spin_unlock_bh(&queue_lock); |
348 | return status; | 341 | return status; |
349 | } | 342 | } |
350 | 343 | ||
@@ -441,11 +434,11 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
441 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 434 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) |
442 | RCV_SKB_FAIL(-EPERM); | 435 | RCV_SKB_FAIL(-EPERM); |
443 | 436 | ||
444 | write_lock_bh(&queue_lock); | 437 | spin_lock_bh(&queue_lock); |
445 | 438 | ||
446 | if (peer_pid) { | 439 | if (peer_pid) { |
447 | if (peer_pid != pid) { | 440 | if (peer_pid != pid) { |
448 | write_unlock_bh(&queue_lock); | 441 | spin_unlock_bh(&queue_lock); |
449 | RCV_SKB_FAIL(-EBUSY); | 442 | RCV_SKB_FAIL(-EBUSY); |
450 | } | 443 | } |
451 | } else { | 444 | } else { |
@@ -453,7 +446,7 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
453 | peer_pid = pid; | 446 | peer_pid = pid; |
454 | } | 447 | } |
455 | 448 | ||
456 | write_unlock_bh(&queue_lock); | 449 | spin_unlock_bh(&queue_lock); |
457 | 450 | ||
458 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 451 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
459 | nlmsglen - NLMSG_LENGTH(0)); | 452 | nlmsglen - NLMSG_LENGTH(0)); |
@@ -498,10 +491,10 @@ ipq_rcv_nl_event(struct notifier_block *this, | |||
498 | struct netlink_notify *n = ptr; | 491 | struct netlink_notify *n = ptr; |
499 | 492 | ||
500 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { | 493 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { |
501 | write_lock_bh(&queue_lock); | 494 | spin_lock_bh(&queue_lock); |
502 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 495 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
503 | __ipq_reset(); | 496 | __ipq_reset(); |
504 | write_unlock_bh(&queue_lock); | 497 | spin_unlock_bh(&queue_lock); |
505 | } | 498 | } |
506 | return NOTIFY_DONE; | 499 | return NOTIFY_DONE; |
507 | } | 500 | } |
@@ -528,7 +521,7 @@ static ctl_table ipq_table[] = { | |||
528 | #ifdef CONFIG_PROC_FS | 521 | #ifdef CONFIG_PROC_FS |
529 | static int ip6_queue_show(struct seq_file *m, void *v) | 522 | static int ip6_queue_show(struct seq_file *m, void *v) |
530 | { | 523 | { |
531 | read_lock_bh(&queue_lock); | 524 | spin_lock_bh(&queue_lock); |
532 | 525 | ||
533 | seq_printf(m, | 526 | seq_printf(m, |
534 | "Peer PID : %d\n" | 527 | "Peer PID : %d\n" |
@@ -546,7 +539,7 @@ static int ip6_queue_show(struct seq_file *m, void *v) | |||
546 | queue_dropped, | 539 | queue_dropped, |
547 | queue_user_dropped); | 540 | queue_user_dropped); |
548 | 541 | ||
549 | read_unlock_bh(&queue_lock); | 542 | spin_unlock_bh(&queue_lock); |
550 | return 0; | 543 | return 0; |
551 | } | 544 | } |
552 | 545 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 6f517bd83692..dc41d6d3c6c6 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -363,7 +363,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
363 | cpu = smp_processor_id(); | 363 | cpu = smp_processor_id(); |
364 | table_base = private->entries[cpu]; | 364 | table_base = private->entries[cpu]; |
365 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; | 365 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; |
366 | stackptr = &private->stackptr[cpu]; | 366 | stackptr = per_cpu_ptr(private->stackptr, cpu); |
367 | origptr = *stackptr; | 367 | origptr = *stackptr; |
368 | 368 | ||
369 | e = get_entry(table_base, private->hook_entry[hook]); | 369 | e = get_entry(table_base, private->hook_entry[hook]); |
@@ -943,7 +943,7 @@ static struct xt_counters *alloc_counters(const struct xt_table *table) | |||
943 | (other than comefrom, which userspace doesn't care | 943 | (other than comefrom, which userspace doesn't care |
944 | about). */ | 944 | about). */ |
945 | countersize = sizeof(struct xt_counters) * private->number; | 945 | countersize = sizeof(struct xt_counters) * private->number; |
946 | counters = vmalloc_node(countersize, numa_node_id()); | 946 | counters = vmalloc(countersize); |
947 | 947 | ||
948 | if (counters == NULL) | 948 | if (counters == NULL) |
949 | return ERR_PTR(-ENOMEM); | 949 | return ERR_PTR(-ENOMEM); |
@@ -1213,8 +1213,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1213 | struct ip6t_entry *iter; | 1213 | struct ip6t_entry *iter; |
1214 | 1214 | ||
1215 | ret = 0; | 1215 | ret = 0; |
1216 | counters = vmalloc_node(num_counters * sizeof(struct xt_counters), | 1216 | counters = vmalloc(num_counters * sizeof(struct xt_counters)); |
1217 | numa_node_id()); | ||
1218 | if (!counters) { | 1217 | if (!counters) { |
1219 | ret = -ENOMEM; | 1218 | ret = -ENOMEM; |
1220 | goto out; | 1219 | goto out; |
@@ -1368,7 +1367,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
1368 | if (len != size + num_counters * sizeof(struct xt_counters)) | 1367 | if (len != size + num_counters * sizeof(struct xt_counters)) |
1369 | return -EINVAL; | 1368 | return -EINVAL; |
1370 | 1369 | ||
1371 | paddc = vmalloc_node(len - size, numa_node_id()); | 1370 | paddc = vmalloc(len - size); |
1372 | if (!paddc) | 1371 | if (!paddc) |
1373 | return -ENOMEM; | 1372 | return -ENOMEM; |
1374 | 1373 | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index af4ee11f2066..0a07ae7b933f 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -373,6 +373,56 @@ static void dump_packet(const struct nf_loginfo *info, | |||
373 | printk("MARK=0x%x ", skb->mark); | 373 | printk("MARK=0x%x ", skb->mark); |
374 | } | 374 | } |
375 | 375 | ||
376 | static void dump_mac_header(const struct nf_loginfo *info, | ||
377 | const struct sk_buff *skb) | ||
378 | { | ||
379 | struct net_device *dev = skb->dev; | ||
380 | unsigned int logflags = 0; | ||
381 | |||
382 | if (info->type == NF_LOG_TYPE_LOG) | ||
383 | logflags = info->u.log.logflags; | ||
384 | |||
385 | if (!(logflags & IP6T_LOG_MACDECODE)) | ||
386 | goto fallback; | ||
387 | |||
388 | switch (dev->type) { | ||
389 | case ARPHRD_ETHER: | ||
390 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
392 | ntohs(eth_hdr(skb)->h_proto)); | ||
393 | return; | ||
394 | default: | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | fallback: | ||
399 | printk("MAC="); | ||
400 | if (dev->hard_header_len && | ||
401 | skb->mac_header != skb->network_header) { | ||
402 | const unsigned char *p = skb_mac_header(skb); | ||
403 | unsigned int len = dev->hard_header_len; | ||
404 | unsigned int i; | ||
405 | |||
406 | if (dev->type == ARPHRD_SIT && | ||
407 | (p -= ETH_HLEN) < skb->head) | ||
408 | p = NULL; | ||
409 | |||
410 | if (p != NULL) { | ||
411 | printk("%02x", *p++); | ||
412 | for (i = 1; i < len; i++) | ||
413 | printk(":%02x", p[i]); | ||
414 | } | ||
415 | printk(" "); | ||
416 | |||
417 | if (dev->type == ARPHRD_SIT) { | ||
418 | const struct iphdr *iph = | ||
419 | (struct iphdr *)skb_mac_header(skb); | ||
420 | printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | ||
421 | } | ||
422 | } else | ||
423 | printk(" "); | ||
424 | } | ||
425 | |||
376 | static struct nf_loginfo default_loginfo = { | 426 | static struct nf_loginfo default_loginfo = { |
377 | .type = NF_LOG_TYPE_LOG, | 427 | .type = NF_LOG_TYPE_LOG, |
378 | .u = { | 428 | .u = { |
@@ -400,35 +450,10 @@ ip6t_log_packet(u_int8_t pf, | |||
400 | prefix, | 450 | prefix, |
401 | in ? in->name : "", | 451 | in ? in->name : "", |
402 | out ? out->name : ""); | 452 | out ? out->name : ""); |
403 | if (in && !out) { | ||
404 | unsigned int len; | ||
405 | /* MAC logging for input chain only. */ | ||
406 | printk("MAC="); | ||
407 | if (skb->dev && (len = skb->dev->hard_header_len) && | ||
408 | skb->mac_header != skb->network_header) { | ||
409 | const unsigned char *p = skb_mac_header(skb); | ||
410 | int i; | ||
411 | |||
412 | if (skb->dev->type == ARPHRD_SIT && | ||
413 | (p -= ETH_HLEN) < skb->head) | ||
414 | p = NULL; | ||
415 | |||
416 | if (p != NULL) { | ||
417 | for (i = 0; i < len; i++) | ||
418 | printk("%02x%s", p[i], | ||
419 | i == len - 1 ? "" : ":"); | ||
420 | } | ||
421 | printk(" "); | ||
422 | 453 | ||
423 | if (skb->dev->type == ARPHRD_SIT) { | 454 | /* MAC logging for input path only. */ |
424 | const struct iphdr *iph = | 455 | if (in && !out) |
425 | (struct iphdr *)skb_mac_header(skb); | 456 | dump_mac_header(loginfo, skb); |
426 | printk("TUNNEL=%pI4->%pI4 ", | ||
427 | &iph->saddr, &iph->daddr); | ||
428 | } | ||
429 | } else | ||
430 | printk(" "); | ||
431 | } | ||
432 | 457 | ||
433 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); | 458 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); |
434 | printk("\n"); | 459 | printk("\n"); |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 47d227713758..2933396e0281 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -97,9 +97,11 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
97 | fl.fl_ip_dport = otcph.source; | 97 | fl.fl_ip_dport = otcph.source; |
98 | security_skb_classify_flow(oldskb, &fl); | 98 | security_skb_classify_flow(oldskb, &fl); |
99 | dst = ip6_route_output(net, NULL, &fl); | 99 | dst = ip6_route_output(net, NULL, &fl); |
100 | if (dst == NULL) | 100 | if (dst == NULL || dst->error) { |
101 | dst_release(dst); | ||
101 | return; | 102 | return; |
102 | if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0)) | 103 | } |
104 | if (xfrm_lookup(net, &dst, &fl, NULL, 0)) | ||
103 | return; | 105 | return; |
104 | 106 | ||
105 | hh_len = (dst->dev->hard_header_len + 15)&~15; | 107 | hh_len = (dst->dev->hard_header_len + 15)&~15; |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9be81776415e..1df3c8b6bf47 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -208,7 +208,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, | |||
208 | type = icmp6h->icmp6_type - 130; | 208 | type = icmp6h->icmp6_type - 130; |
209 | if (type >= 0 && type < sizeof(noct_valid_new) && | 209 | if (type >= 0 && type < sizeof(noct_valid_new) && |
210 | noct_valid_new[type]) { | 210 | noct_valid_new[type]) { |
211 | skb->nfct = &nf_conntrack_untracked.ct_general; | 211 | skb->nfct = &nf_ct_untracked_get()->ct_general; |
212 | skb->nfctinfo = IP_CT_NEW; | 212 | skb->nfctinfo = IP_CT_NEW; |
213 | nf_conntrack_get(skb->nfct); | 213 | nf_conntrack_get(skb->nfct); |
214 | return NF_ACCEPT; | 214 | return NF_ACCEPT; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6fb890187de0..9254008602d4 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -114,10 +114,8 @@ static void nf_skb_free(struct sk_buff *skb) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | /* Memory Tracking Functions. */ | 116 | /* Memory Tracking Functions. */ |
117 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) | 117 | static void frag_kfree_skb(struct sk_buff *skb) |
118 | { | 118 | { |
119 | if (work) | ||
120 | *work -= skb->truesize; | ||
121 | atomic_sub(skb->truesize, &nf_init_frags.mem); | 119 | atomic_sub(skb->truesize, &nf_init_frags.mem); |
122 | nf_skb_free(skb); | 120 | nf_skb_free(skb); |
123 | kfree_skb(skb); | 121 | kfree_skb(skb); |
@@ -335,7 +333,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
335 | fq->q.fragments = next; | 333 | fq->q.fragments = next; |
336 | 334 | ||
337 | fq->q.meat -= free_it->len; | 335 | fq->q.meat -= free_it->len; |
338 | frag_kfree_skb(free_it, NULL); | 336 | frag_kfree_skb(free_it); |
339 | } | 337 | } |
340 | } | 338 | } |
341 | 339 | ||
@@ -442,7 +440,6 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
442 | skb_shinfo(head)->frag_list = head->next; | 440 | skb_shinfo(head)->frag_list = head->next; |
443 | skb_reset_transport_header(head); | 441 | skb_reset_transport_header(head); |
444 | skb_push(head, head->data - skb_network_header(head)); | 442 | skb_push(head, head->data - skb_network_header(head)); |
445 | atomic_sub(head->truesize, &nf_init_frags.mem); | ||
446 | 443 | ||
447 | for (fp=head->next; fp; fp = fp->next) { | 444 | for (fp=head->next; fp; fp = fp->next) { |
448 | head->data_len += fp->len; | 445 | head->data_len += fp->len; |
@@ -452,8 +449,8 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
452 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 449 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
453 | head->csum = csum_add(head->csum, fp->csum); | 450 | head->csum = csum_add(head->csum, fp->csum); |
454 | head->truesize += fp->truesize; | 451 | head->truesize += fp->truesize; |
455 | atomic_sub(fp->truesize, &nf_init_frags.mem); | ||
456 | } | 452 | } |
453 | atomic_sub(head->truesize, &nf_init_frags.mem); | ||
457 | 454 | ||
458 | head->next = NULL; | 455 | head->next = NULL; |
459 | head->dev = dev; | 456 | head->dev = dev; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 566798d69f37..d082eaeefa25 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -174,17 +174,28 @@ static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, | |||
174 | const struct snmp_mib *itemlist) | 174 | const struct snmp_mib *itemlist) |
175 | { | 175 | { |
176 | int i; | 176 | int i; |
177 | for (i=0; itemlist[i].name; i++) | 177 | |
178 | for (i = 0; itemlist[i].name; i++) | ||
178 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, | 179 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, |
179 | snmp_fold_field(mib, itemlist[i].entry)); | 180 | snmp_fold_field(mib, itemlist[i].entry)); |
180 | } | 181 | } |
181 | 182 | ||
183 | static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu **mib, | ||
184 | const struct snmp_mib *itemlist, size_t syncpoff) | ||
185 | { | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; itemlist[i].name; i++) | ||
189 | seq_printf(seq, "%-32s\t%llu\n", itemlist[i].name, | ||
190 | snmp_fold_field64(mib, itemlist[i].entry, syncpoff)); | ||
191 | } | ||
192 | |||
182 | static int snmp6_seq_show(struct seq_file *seq, void *v) | 193 | static int snmp6_seq_show(struct seq_file *seq, void *v) |
183 | { | 194 | { |
184 | struct net *net = (struct net *)seq->private; | 195 | struct net *net = (struct net *)seq->private; |
185 | 196 | ||
186 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.ipv6_statistics, | 197 | snmp6_seq_show_item64(seq, (void __percpu **)net->mib.ipv6_statistics, |
187 | snmp6_ipstats_list); | 198 | snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); |
188 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, | 199 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, |
189 | snmp6_icmp6_list); | 200 | snmp6_icmp6_list); |
190 | snmp6_seq_show_icmpv6msg(seq, | 201 | snmp6_seq_show_icmpv6msg(seq, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a4dcbe4f8b2..e677937a07fc 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -602,31 +602,33 @@ out: | |||
602 | } | 602 | } |
603 | 603 | ||
604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, |
605 | struct flowi *fl, struct rt6_info *rt, | 605 | struct flowi *fl, struct dst_entry **dstp, |
606 | unsigned int flags) | 606 | unsigned int flags) |
607 | { | 607 | { |
608 | struct ipv6_pinfo *np = inet6_sk(sk); | 608 | struct ipv6_pinfo *np = inet6_sk(sk); |
609 | struct ipv6hdr *iph; | 609 | struct ipv6hdr *iph; |
610 | struct sk_buff *skb; | 610 | struct sk_buff *skb; |
611 | int err; | 611 | int err; |
612 | struct rt6_info *rt = (struct rt6_info *)*dstp; | ||
612 | 613 | ||
613 | if (length > rt->u.dst.dev->mtu) { | 614 | if (length > rt->dst.dev->mtu) { |
614 | ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu); | 615 | ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); |
615 | return -EMSGSIZE; | 616 | return -EMSGSIZE; |
616 | } | 617 | } |
617 | if (flags&MSG_PROBE) | 618 | if (flags&MSG_PROBE) |
618 | goto out; | 619 | goto out; |
619 | 620 | ||
620 | skb = sock_alloc_send_skb(sk, | 621 | skb = sock_alloc_send_skb(sk, |
621 | length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15, | 622 | length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, |
622 | flags & MSG_DONTWAIT, &err); | 623 | flags & MSG_DONTWAIT, &err); |
623 | if (skb == NULL) | 624 | if (skb == NULL) |
624 | goto error; | 625 | goto error; |
625 | skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev)); | 626 | skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); |
626 | 627 | ||
627 | skb->priority = sk->sk_priority; | 628 | skb->priority = sk->sk_priority; |
628 | skb->mark = sk->sk_mark; | 629 | skb->mark = sk->sk_mark; |
629 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 630 | skb_dst_set(skb, &rt->dst); |
631 | *dstp = NULL; | ||
630 | 632 | ||
631 | skb_put(skb, length); | 633 | skb_put(skb, length); |
632 | skb_reset_network_header(skb); | 634 | skb_reset_network_header(skb); |
@@ -641,7 +643,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
641 | 643 | ||
642 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 644 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
643 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, | 645 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
644 | rt->u.dst.dev, dst_output); | 646 | rt->dst.dev, dst_output); |
645 | if (err > 0) | 647 | if (err > 0) |
646 | err = net_xmit_errno(err); | 648 | err = net_xmit_errno(err); |
647 | if (err) | 649 | if (err) |
@@ -725,7 +727,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
725 | { | 727 | { |
726 | struct ipv6_txoptions opt_space; | 728 | struct ipv6_txoptions opt_space; |
727 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 729 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; |
728 | struct in6_addr *daddr, *final_p = NULL, final; | 730 | struct in6_addr *daddr, *final_p, final; |
729 | struct inet_sock *inet = inet_sk(sk); | 731 | struct inet_sock *inet = inet_sk(sk); |
730 | struct ipv6_pinfo *np = inet6_sk(sk); | 732 | struct ipv6_pinfo *np = inet6_sk(sk); |
731 | struct raw6_sock *rp = raw6_sk(sk); | 733 | struct raw6_sock *rp = raw6_sk(sk); |
@@ -847,13 +849,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
847 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 849 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
848 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 850 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
849 | 851 | ||
850 | /* merge ip6_build_xmit from ip6_output */ | 852 | final_p = fl6_update_dst(&fl, opt, &final); |
851 | if (opt && opt->srcrt) { | ||
852 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
853 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
854 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
855 | final_p = &final; | ||
856 | } | ||
857 | 853 | ||
858 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 854 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
859 | fl.oif = np->mcast_oif; | 855 | fl.oif = np->mcast_oif; |
@@ -892,9 +888,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
892 | goto do_confirm; | 888 | goto do_confirm; |
893 | 889 | ||
894 | back_from_confirm: | 890 | back_from_confirm: |
895 | if (inet->hdrincl) { | 891 | if (inet->hdrincl) |
896 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags); | 892 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags); |
897 | } else { | 893 | else { |
898 | lock_sock(sk); | 894 | lock_sock(sk); |
899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 895 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 896 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 6d4292ff5854..545c4141b755 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -150,11 +150,8 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
150 | EXPORT_SYMBOL(ip6_frag_match); | 150 | EXPORT_SYMBOL(ip6_frag_match); |
151 | 151 | ||
152 | /* Memory Tracking Functions. */ | 152 | /* Memory Tracking Functions. */ |
153 | static inline void frag_kfree_skb(struct netns_frags *nf, | 153 | static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb) |
154 | struct sk_buff *skb, int *work) | ||
155 | { | 154 | { |
156 | if (work) | ||
157 | *work -= skb->truesize; | ||
158 | atomic_sub(skb->truesize, &nf->mem); | 155 | atomic_sub(skb->truesize, &nf->mem); |
159 | kfree_skb(skb); | 156 | kfree_skb(skb); |
160 | } | 157 | } |
@@ -336,6 +333,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
336 | * in the chain of fragments so far. We must know where to put | 333 | * in the chain of fragments so far. We must know where to put |
337 | * this fragment, right? | 334 | * this fragment, right? |
338 | */ | 335 | */ |
336 | prev = fq->q.fragments_tail; | ||
337 | if (!prev || FRAG6_CB(prev)->offset < offset) { | ||
338 | next = NULL; | ||
339 | goto found; | ||
340 | } | ||
339 | prev = NULL; | 341 | prev = NULL; |
340 | for(next = fq->q.fragments; next != NULL; next = next->next) { | 342 | for(next = fq->q.fragments; next != NULL; next = next->next) { |
341 | if (FRAG6_CB(next)->offset >= offset) | 343 | if (FRAG6_CB(next)->offset >= offset) |
@@ -343,6 +345,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
343 | prev = next; | 345 | prev = next; |
344 | } | 346 | } |
345 | 347 | ||
348 | found: | ||
346 | /* We found where to put this one. Check for overlap with | 349 | /* We found where to put this one. Check for overlap with |
347 | * preceding fragment, and, if needed, align things so that | 350 | * preceding fragment, and, if needed, align things so that |
348 | * any overlaps are eliminated. | 351 | * any overlaps are eliminated. |
@@ -392,7 +395,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
392 | fq->q.fragments = next; | 395 | fq->q.fragments = next; |
393 | 396 | ||
394 | fq->q.meat -= free_it->len; | 397 | fq->q.meat -= free_it->len; |
395 | frag_kfree_skb(fq->q.net, free_it, NULL); | 398 | frag_kfree_skb(fq->q.net, free_it); |
396 | } | 399 | } |
397 | } | 400 | } |
398 | 401 | ||
@@ -400,6 +403,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
400 | 403 | ||
401 | /* Insert this fragment in the chain of fragments. */ | 404 | /* Insert this fragment in the chain of fragments. */ |
402 | skb->next = next; | 405 | skb->next = next; |
406 | if (!next) | ||
407 | fq->q.fragments_tail = skb; | ||
403 | if (prev) | 408 | if (prev) |
404 | prev->next = skb; | 409 | prev->next = skb; |
405 | else | 410 | else |
@@ -466,6 +471,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
466 | goto out_oom; | 471 | goto out_oom; |
467 | 472 | ||
468 | fp->next = head->next; | 473 | fp->next = head->next; |
474 | if (!fp->next) | ||
475 | fq->q.fragments_tail = fp; | ||
469 | prev->next = fp; | 476 | prev->next = fp; |
470 | 477 | ||
471 | skb_morph(head, fq->q.fragments); | 478 | skb_morph(head, fq->q.fragments); |
@@ -524,7 +531,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
524 | skb_shinfo(head)->frag_list = head->next; | 531 | skb_shinfo(head)->frag_list = head->next; |
525 | skb_reset_transport_header(head); | 532 | skb_reset_transport_header(head); |
526 | skb_push(head, head->data - skb_network_header(head)); | 533 | skb_push(head, head->data - skb_network_header(head)); |
527 | atomic_sub(head->truesize, &fq->q.net->mem); | ||
528 | 534 | ||
529 | for (fp=head->next; fp; fp = fp->next) { | 535 | for (fp=head->next; fp; fp = fp->next) { |
530 | head->data_len += fp->len; | 536 | head->data_len += fp->len; |
@@ -534,8 +540,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
534 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 540 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
535 | head->csum = csum_add(head->csum, fp->csum); | 541 | head->csum = csum_add(head->csum, fp->csum); |
536 | head->truesize += fp->truesize; | 542 | head->truesize += fp->truesize; |
537 | atomic_sub(fp->truesize, &fq->q.net->mem); | ||
538 | } | 543 | } |
544 | atomic_sub(head->truesize, &fq->q.net->mem); | ||
539 | 545 | ||
540 | head->next = NULL; | 546 | head->next = NULL; |
541 | head->dev = dev; | 547 | head->dev = dev; |
@@ -553,6 +559,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
553 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 559 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
554 | rcu_read_unlock(); | 560 | rcu_read_unlock(); |
555 | fq->q.fragments = NULL; | 561 | fq->q.fragments = NULL; |
562 | fq->q.fragments_tail = NULL; | ||
556 | return 1; | 563 | return 1; |
557 | 564 | ||
558 | out_oversize: | 565 | out_oversize: |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 294cbe8b0725..8f2d0400cf8a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -126,16 +126,14 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
126 | }; | 126 | }; |
127 | 127 | ||
128 | static struct rt6_info ip6_null_entry_template = { | 128 | static struct rt6_info ip6_null_entry_template = { |
129 | .u = { | 129 | .dst = { |
130 | .dst = { | 130 | .__refcnt = ATOMIC_INIT(1), |
131 | .__refcnt = ATOMIC_INIT(1), | 131 | .__use = 1, |
132 | .__use = 1, | 132 | .obsolete = -1, |
133 | .obsolete = -1, | 133 | .error = -ENETUNREACH, |
134 | .error = -ENETUNREACH, | 134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
135 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 135 | .input = ip6_pkt_discard, |
136 | .input = ip6_pkt_discard, | 136 | .output = ip6_pkt_discard_out, |
137 | .output = ip6_pkt_discard_out, | ||
138 | } | ||
139 | }, | 137 | }, |
140 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 138 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
141 | .rt6i_protocol = RTPROT_KERNEL, | 139 | .rt6i_protocol = RTPROT_KERNEL, |
@@ -149,16 +147,14 @@ static int ip6_pkt_prohibit(struct sk_buff *skb); | |||
149 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 147 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
150 | 148 | ||
151 | static struct rt6_info ip6_prohibit_entry_template = { | 149 | static struct rt6_info ip6_prohibit_entry_template = { |
152 | .u = { | 150 | .dst = { |
153 | .dst = { | 151 | .__refcnt = ATOMIC_INIT(1), |
154 | .__refcnt = ATOMIC_INIT(1), | 152 | .__use = 1, |
155 | .__use = 1, | 153 | .obsolete = -1, |
156 | .obsolete = -1, | 154 | .error = -EACCES, |
157 | .error = -EACCES, | 155 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
158 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 156 | .input = ip6_pkt_prohibit, |
159 | .input = ip6_pkt_prohibit, | 157 | .output = ip6_pkt_prohibit_out, |
160 | .output = ip6_pkt_prohibit_out, | ||
161 | } | ||
162 | }, | 158 | }, |
163 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 159 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
164 | .rt6i_protocol = RTPROT_KERNEL, | 160 | .rt6i_protocol = RTPROT_KERNEL, |
@@ -167,16 +163,14 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
167 | }; | 163 | }; |
168 | 164 | ||
169 | static struct rt6_info ip6_blk_hole_entry_template = { | 165 | static struct rt6_info ip6_blk_hole_entry_template = { |
170 | .u = { | 166 | .dst = { |
171 | .dst = { | 167 | .__refcnt = ATOMIC_INIT(1), |
172 | .__refcnt = ATOMIC_INIT(1), | 168 | .__use = 1, |
173 | .__use = 1, | 169 | .obsolete = -1, |
174 | .obsolete = -1, | 170 | .error = -EINVAL, |
175 | .error = -EINVAL, | 171 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
176 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 172 | .input = dst_discard, |
177 | .input = dst_discard, | 173 | .output = dst_discard, |
178 | .output = dst_discard, | ||
179 | } | ||
180 | }, | 174 | }, |
181 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 175 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
182 | .rt6i_protocol = RTPROT_KERNEL, | 176 | .rt6i_protocol = RTPROT_KERNEL, |
@@ -249,7 +243,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
249 | if (!oif && ipv6_addr_any(saddr)) | 243 | if (!oif && ipv6_addr_any(saddr)) |
250 | goto out; | 244 | goto out; |
251 | 245 | ||
252 | for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { | 246 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { |
253 | struct net_device *dev = sprt->rt6i_dev; | 247 | struct net_device *dev = sprt->rt6i_dev; |
254 | 248 | ||
255 | if (oif) { | 249 | if (oif) { |
@@ -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) { |
@@ -677,7 +671,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
677 | if (net_ratelimit()) | 671 | if (net_ratelimit()) |
678 | printk(KERN_WARNING | 672 | printk(KERN_WARNING |
679 | "Neighbour table overflow.\n"); | 673 | "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,7 +808,7 @@ 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 (fl->oif || 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)) |
@@ -835,15 +829,15 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
835 | struct dst_entry *new = NULL; | 829 | struct dst_entry *new = NULL; |
836 | 830 | ||
837 | if (rt) { | 831 | if (rt) { |
838 | new = &rt->u.dst; | 832 | new = &rt->dst; |
839 | 833 | ||
840 | atomic_set(&new->__refcnt, 1); | 834 | atomic_set(&new->__refcnt, 1); |
841 | new->__use = 1; | 835 | new->__use = 1; |
842 | new->input = dst_discard; | 836 | new->input = dst_discard; |
843 | new->output = dst_discard; | 837 | new->output = dst_discard; |
844 | 838 | ||
845 | memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 839 | memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
846 | new->dev = ort->u.dst.dev; | 840 | new->dev = ort->dst.dev; |
847 | if (new->dev) | 841 | if (new->dev) |
848 | dev_hold(new->dev); | 842 | dev_hold(new->dev); |
849 | rt->rt6i_idev = ort->rt6i_idev; | 843 | rt->rt6i_idev = ort->rt6i_idev; |
@@ -912,7 +906,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
912 | rt = (struct rt6_info *) skb_dst(skb); | 906 | rt = (struct rt6_info *) skb_dst(skb); |
913 | if (rt) { | 907 | if (rt) { |
914 | if (rt->rt6i_flags&RTF_CACHE) { | 908 | if (rt->rt6i_flags&RTF_CACHE) { |
915 | dst_set_expires(&rt->u.dst, 0); | 909 | dst_set_expires(&rt->dst, 0); |
916 | rt->rt6i_flags |= RTF_EXPIRES; | 910 | rt->rt6i_flags |= RTF_EXPIRES; |
917 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | 911 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
918 | rt->rt6i_node->fn_sernum = -1; | 912 | rt->rt6i_node->fn_sernum = -1; |
@@ -986,14 +980,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
986 | rt->rt6i_dev = dev; | 980 | rt->rt6i_dev = dev; |
987 | rt->rt6i_idev = idev; | 981 | rt->rt6i_idev = idev; |
988 | rt->rt6i_nexthop = neigh; | 982 | rt->rt6i_nexthop = neigh; |
989 | atomic_set(&rt->u.dst.__refcnt, 1); | 983 | atomic_set(&rt->dst.__refcnt, 1); |
990 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 984 | rt->dst.metrics[RTAX_HOPLIMIT-1] = 255; |
991 | 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); |
992 | 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)); |
993 | rt->u.dst.output = ip6_output; | 987 | rt->dst.output = ip6_output; |
994 | 988 | ||
995 | #if 0 /* there's no chance to use these for ndisc */ | 989 | #if 0 /* there's no chance to use these for ndisc */ |
996 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 990 | rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
997 | ? DST_HOST | 991 | ? DST_HOST |
998 | : 0; | 992 | : 0; |
999 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 993 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
@@ -1001,14 +995,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1001 | #endif | 995 | #endif |
1002 | 996 | ||
1003 | spin_lock_bh(&icmp6_dst_lock); | 997 | spin_lock_bh(&icmp6_dst_lock); |
1004 | rt->u.dst.next = icmp6_dst_gc_list; | 998 | rt->dst.next = icmp6_dst_gc_list; |
1005 | icmp6_dst_gc_list = &rt->u.dst; | 999 | icmp6_dst_gc_list = &rt->dst; |
1006 | spin_unlock_bh(&icmp6_dst_lock); | 1000 | spin_unlock_bh(&icmp6_dst_lock); |
1007 | 1001 | ||
1008 | fib6_force_start_gc(net); | 1002 | fib6_force_start_gc(net); |
1009 | 1003 | ||
1010 | out: | 1004 | out: |
1011 | return &rt->u.dst; | 1005 | return &rt->dst; |
1012 | } | 1006 | } |
1013 | 1007 | ||
1014 | int icmp6_dst_gc(void) | 1008 | int icmp6_dst_gc(void) |
@@ -1090,11 +1084,11 @@ static int ipv6_get_mtu(struct net_device *dev) | |||
1090 | int mtu = IPV6_MIN_MTU; | 1084 | int mtu = IPV6_MIN_MTU; |
1091 | struct inet6_dev *idev; | 1085 | struct inet6_dev *idev; |
1092 | 1086 | ||
1093 | idev = in6_dev_get(dev); | 1087 | rcu_read_lock(); |
1094 | if (idev) { | 1088 | idev = __in6_dev_get(dev); |
1089 | if (idev) | ||
1095 | mtu = idev->cnf.mtu6; | 1090 | mtu = idev->cnf.mtu6; |
1096 | in6_dev_put(idev); | 1091 | rcu_read_unlock(); |
1097 | } | ||
1098 | return mtu; | 1092 | return mtu; |
1099 | } | 1093 | } |
1100 | 1094 | ||
@@ -1103,12 +1097,15 @@ int ip6_dst_hoplimit(struct dst_entry *dst) | |||
1103 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); | 1097 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); |
1104 | if (hoplimit < 0) { | 1098 | if (hoplimit < 0) { |
1105 | struct net_device *dev = dst->dev; | 1099 | struct net_device *dev = dst->dev; |
1106 | struct inet6_dev *idev = in6_dev_get(dev); | 1100 | struct inet6_dev *idev; |
1107 | if (idev) { | 1101 | |
1102 | rcu_read_lock(); | ||
1103 | idev = __in6_dev_get(dev); | ||
1104 | if (idev) | ||
1108 | hoplimit = idev->cnf.hop_limit; | 1105 | hoplimit = idev->cnf.hop_limit; |
1109 | in6_dev_put(idev); | 1106 | else |
1110 | } else | ||
1111 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; | 1107 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; |
1108 | rcu_read_unlock(); | ||
1112 | } | 1109 | } |
1113 | return hoplimit; | 1110 | return hoplimit; |
1114 | } | 1111 | } |
@@ -1159,7 +1156,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1159 | goto out; | 1156 | goto out; |
1160 | } | 1157 | } |
1161 | 1158 | ||
1162 | rt->u.dst.obsolete = -1; | 1159 | rt->dst.obsolete = -1; |
1163 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1160 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? |
1164 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1161 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : |
1165 | 0; | 1162 | 0; |
@@ -1171,16 +1168,16 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1171 | addr_type = ipv6_addr_type(&cfg->fc_dst); | 1168 | addr_type = ipv6_addr_type(&cfg->fc_dst); |
1172 | 1169 | ||
1173 | if (addr_type & IPV6_ADDR_MULTICAST) | 1170 | if (addr_type & IPV6_ADDR_MULTICAST) |
1174 | rt->u.dst.input = ip6_mc_input; | 1171 | rt->dst.input = ip6_mc_input; |
1175 | else | 1172 | else |
1176 | rt->u.dst.input = ip6_forward; | 1173 | rt->dst.input = ip6_forward; |
1177 | 1174 | ||
1178 | rt->u.dst.output = ip6_output; | 1175 | rt->dst.output = ip6_output; |
1179 | 1176 | ||
1180 | 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); |
1181 | rt->rt6i_dst.plen = cfg->fc_dst_len; | 1178 | rt->rt6i_dst.plen = cfg->fc_dst_len; |
1182 | if (rt->rt6i_dst.plen == 128) | 1179 | if (rt->rt6i_dst.plen == 128) |
1183 | rt->u.dst.flags = DST_HOST; | 1180 | rt->dst.flags = DST_HOST; |
1184 | 1181 | ||
1185 | #ifdef CONFIG_IPV6_SUBTREES | 1182 | #ifdef CONFIG_IPV6_SUBTREES |
1186 | 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); |
@@ -1208,9 +1205,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1208 | goto out; | 1205 | goto out; |
1209 | } | 1206 | } |
1210 | } | 1207 | } |
1211 | rt->u.dst.output = ip6_pkt_discard_out; | 1208 | rt->dst.output = ip6_pkt_discard_out; |
1212 | rt->u.dst.input = ip6_pkt_discard; | 1209 | rt->dst.input = ip6_pkt_discard; |
1213 | rt->u.dst.error = -ENETUNREACH; | 1210 | rt->dst.error = -ENETUNREACH; |
1214 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; | 1211 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; |
1215 | goto install_route; | 1212 | goto install_route; |
1216 | } | 1213 | } |
@@ -1244,7 +1241,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1244 | goto out; | 1241 | goto out; |
1245 | if (dev) { | 1242 | if (dev) { |
1246 | if (dev != grt->rt6i_dev) { | 1243 | if (dev != grt->rt6i_dev) { |
1247 | dst_release(&grt->u.dst); | 1244 | dst_release(&grt->dst); |
1248 | goto out; | 1245 | goto out; |
1249 | } | 1246 | } |
1250 | } else { | 1247 | } else { |
@@ -1255,7 +1252,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1255 | } | 1252 | } |
1256 | if (!(grt->rt6i_flags&RTF_GATEWAY)) | 1253 | if (!(grt->rt6i_flags&RTF_GATEWAY)) |
1257 | err = 0; | 1254 | err = 0; |
1258 | dst_release(&grt->u.dst); | 1255 | dst_release(&grt->dst); |
1259 | 1256 | ||
1260 | if (err) | 1257 | if (err) |
1261 | goto out; | 1258 | goto out; |
@@ -1294,18 +1291,18 @@ install_route: | |||
1294 | goto out; | 1291 | goto out; |
1295 | } | 1292 | } |
1296 | 1293 | ||
1297 | rt->u.dst.metrics[type - 1] = nla_get_u32(nla); | 1294 | rt->dst.metrics[type - 1] = nla_get_u32(nla); |
1298 | } | 1295 | } |
1299 | } | 1296 | } |
1300 | } | 1297 | } |
1301 | 1298 | ||
1302 | if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0) | 1299 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) |
1303 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1300 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
1304 | if (!dst_mtu(&rt->u.dst)) | 1301 | if (!dst_mtu(&rt->dst)) |
1305 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1302 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
1306 | if (!dst_metric(&rt->u.dst, RTAX_ADVMSS)) | 1303 | if (!dst_metric(&rt->dst, RTAX_ADVMSS)) |
1307 | 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)); |
1308 | rt->u.dst.dev = dev; | 1305 | rt->dst.dev = dev; |
1309 | rt->rt6i_idev = idev; | 1306 | rt->rt6i_idev = idev; |
1310 | rt->rt6i_table = table; | 1307 | rt->rt6i_table = table; |
1311 | 1308 | ||
@@ -1319,7 +1316,7 @@ out: | |||
1319 | if (idev) | 1316 | if (idev) |
1320 | in6_dev_put(idev); | 1317 | in6_dev_put(idev); |
1321 | if (rt) | 1318 | if (rt) |
1322 | dst_free(&rt->u.dst); | 1319 | dst_free(&rt->dst); |
1323 | return err; | 1320 | return err; |
1324 | } | 1321 | } |
1325 | 1322 | ||
@@ -1336,7 +1333,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1336 | write_lock_bh(&table->tb6_lock); | 1333 | write_lock_bh(&table->tb6_lock); |
1337 | 1334 | ||
1338 | err = fib6_del(rt, info); | 1335 | err = fib6_del(rt, info); |
1339 | dst_release(&rt->u.dst); | 1336 | dst_release(&rt->dst); |
1340 | 1337 | ||
1341 | write_unlock_bh(&table->tb6_lock); | 1338 | write_unlock_bh(&table->tb6_lock); |
1342 | 1339 | ||
@@ -1369,7 +1366,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1369 | &cfg->fc_src, cfg->fc_src_len); | 1366 | &cfg->fc_src, cfg->fc_src_len); |
1370 | 1367 | ||
1371 | if (fn) { | 1368 | if (fn) { |
1372 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1369 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1373 | if (cfg->fc_ifindex && | 1370 | if (cfg->fc_ifindex && |
1374 | (rt->rt6i_dev == NULL || | 1371 | (rt->rt6i_dev == NULL || |
1375 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) | 1372 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) |
@@ -1379,7 +1376,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1379 | continue; | 1376 | continue; |
1380 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) | 1377 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) |
1381 | continue; | 1378 | continue; |
1382 | dst_hold(&rt->u.dst); | 1379 | dst_hold(&rt->dst); |
1383 | read_unlock_bh(&table->tb6_lock); | 1380 | read_unlock_bh(&table->tb6_lock); |
1384 | 1381 | ||
1385 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); | 1382 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); |
@@ -1421,7 +1418,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
1421 | read_lock_bh(&table->tb6_lock); | 1418 | read_lock_bh(&table->tb6_lock); |
1422 | 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); |
1423 | restart: | 1420 | restart: |
1424 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1421 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1425 | /* | 1422 | /* |
1426 | * Current route is on-link; redirect is always invalid. | 1423 | * Current route is on-link; redirect is always invalid. |
1427 | * | 1424 | * |
@@ -1445,7 +1442,7 @@ restart: | |||
1445 | rt = net->ipv6.ip6_null_entry; | 1442 | rt = net->ipv6.ip6_null_entry; |
1446 | BACKTRACK(net, &fl->fl6_src); | 1443 | BACKTRACK(net, &fl->fl6_src); |
1447 | out: | 1444 | out: |
1448 | dst_hold(&rt->u.dst); | 1445 | dst_hold(&rt->dst); |
1449 | 1446 | ||
1450 | read_unlock_bh(&table->tb6_lock); | 1447 | read_unlock_bh(&table->tb6_lock); |
1451 | 1448 | ||
@@ -1513,10 +1510,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1513 | * Look, redirects are sent only in response to data packets, | 1510 | * Look, redirects are sent only in response to data packets, |
1514 | * so that this nexthop apparently is reachable. --ANK | 1511 | * so that this nexthop apparently is reachable. --ANK |
1515 | */ | 1512 | */ |
1516 | dst_confirm(&rt->u.dst); | 1513 | dst_confirm(&rt->dst); |
1517 | 1514 | ||
1518 | /* Duplicate redirect: silently ignore. */ | 1515 | /* Duplicate redirect: silently ignore. */ |
1519 | if (neigh == rt->u.dst.neighbour) | 1516 | if (neigh == rt->dst.neighbour) |
1520 | goto out; | 1517 | goto out; |
1521 | 1518 | ||
1522 | nrt = ip6_rt_copy(rt); | 1519 | nrt = ip6_rt_copy(rt); |
@@ -1529,20 +1526,20 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1529 | 1526 | ||
1530 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); | 1527 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); |
1531 | nrt->rt6i_dst.plen = 128; | 1528 | nrt->rt6i_dst.plen = 128; |
1532 | nrt->u.dst.flags |= DST_HOST; | 1529 | nrt->dst.flags |= DST_HOST; |
1533 | 1530 | ||
1534 | 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); |
1535 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1532 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1536 | /* Reset pmtu, it may be better */ | 1533 | /* Reset pmtu, it may be better */ |
1537 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1534 | nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); |
1538 | 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), |
1539 | dst_mtu(&nrt->u.dst)); | 1536 | dst_mtu(&nrt->dst)); |
1540 | 1537 | ||
1541 | if (ip6_ins_rt(nrt)) | 1538 | if (ip6_ins_rt(nrt)) |
1542 | goto out; | 1539 | goto out; |
1543 | 1540 | ||
1544 | netevent.old = &rt->u.dst; | 1541 | netevent.old = &rt->dst; |
1545 | netevent.new = &nrt->u.dst; | 1542 | netevent.new = &nrt->dst; |
1546 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); | 1543 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); |
1547 | 1544 | ||
1548 | if (rt->rt6i_flags&RTF_CACHE) { | 1545 | if (rt->rt6i_flags&RTF_CACHE) { |
@@ -1551,7 +1548,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1551 | } | 1548 | } |
1552 | 1549 | ||
1553 | out: | 1550 | out: |
1554 | dst_release(&rt->u.dst); | 1551 | dst_release(&rt->dst); |
1555 | } | 1552 | } |
1556 | 1553 | ||
1557 | /* | 1554 | /* |
@@ -1570,7 +1567,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1570 | if (rt == NULL) | 1567 | if (rt == NULL) |
1571 | return; | 1568 | return; |
1572 | 1569 | ||
1573 | if (pmtu >= dst_mtu(&rt->u.dst)) | 1570 | if (pmtu >= dst_mtu(&rt->dst)) |
1574 | goto out; | 1571 | goto out; |
1575 | 1572 | ||
1576 | if (pmtu < IPV6_MIN_MTU) { | 1573 | if (pmtu < IPV6_MIN_MTU) { |
@@ -1588,7 +1585,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1588 | They are sent only in response to data packets, | 1585 | They are sent only in response to data packets, |
1589 | so that this nexthop apparently is reachable. --ANK | 1586 | so that this nexthop apparently is reachable. --ANK |
1590 | */ | 1587 | */ |
1591 | dst_confirm(&rt->u.dst); | 1588 | dst_confirm(&rt->dst); |
1592 | 1589 | ||
1593 | /* Host route. If it is static, it would be better | 1590 | /* Host route. If it is static, it would be better |
1594 | not to override it, but add new one, so that | 1591 | not to override it, but add new one, so that |
@@ -1596,10 +1593,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1596 | would return automatically. | 1593 | would return automatically. |
1597 | */ | 1594 | */ |
1598 | if (rt->rt6i_flags & RTF_CACHE) { | 1595 | if (rt->rt6i_flags & RTF_CACHE) { |
1599 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1596 | rt->dst.metrics[RTAX_MTU-1] = pmtu; |
1600 | if (allfrag) | 1597 | if (allfrag) |
1601 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1598 | rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
1602 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1599 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1603 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1600 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
1604 | goto out; | 1601 | goto out; |
1605 | } | 1602 | } |
@@ -1615,9 +1612,9 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1615 | nrt = rt6_alloc_clone(rt, daddr); | 1612 | nrt = rt6_alloc_clone(rt, daddr); |
1616 | 1613 | ||
1617 | if (nrt) { | 1614 | if (nrt) { |
1618 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1615 | nrt->dst.metrics[RTAX_MTU-1] = pmtu; |
1619 | if (allfrag) | 1616 | if (allfrag) |
1620 | nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1617 | nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
1621 | 1618 | ||
1622 | /* According to RFC 1981, detecting PMTU increase shouldn't be | 1619 | /* According to RFC 1981, detecting PMTU increase shouldn't be |
1623 | * happened within 5 mins, the recommended timer is 10 mins. | 1620 | * happened within 5 mins, the recommended timer is 10 mins. |
@@ -1625,13 +1622,13 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1625 | * which is 10 mins. After 10 mins the decreased pmtu is expired | 1622 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
1626 | * and detecting PMTU increase will be automatically happened. | 1623 | * and detecting PMTU increase will be automatically happened. |
1627 | */ | 1624 | */ |
1628 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1625 | dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1629 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1626 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
1630 | 1627 | ||
1631 | ip6_ins_rt(nrt); | 1628 | ip6_ins_rt(nrt); |
1632 | } | 1629 | } |
1633 | out: | 1630 | out: |
1634 | dst_release(&rt->u.dst); | 1631 | dst_release(&rt->dst); |
1635 | } | 1632 | } |
1636 | 1633 | ||
1637 | /* | 1634 | /* |
@@ -1644,18 +1641,18 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1644 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1641 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); |
1645 | 1642 | ||
1646 | if (rt) { | 1643 | if (rt) { |
1647 | rt->u.dst.input = ort->u.dst.input; | 1644 | rt->dst.input = ort->dst.input; |
1648 | rt->u.dst.output = ort->u.dst.output; | 1645 | rt->dst.output = ort->dst.output; |
1649 | 1646 | ||
1650 | memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 1647 | memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
1651 | rt->u.dst.error = ort->u.dst.error; | 1648 | rt->dst.error = ort->dst.error; |
1652 | rt->u.dst.dev = ort->u.dst.dev; | 1649 | rt->dst.dev = ort->dst.dev; |
1653 | if (rt->u.dst.dev) | 1650 | if (rt->dst.dev) |
1654 | dev_hold(rt->u.dst.dev); | 1651 | dev_hold(rt->dst.dev); |
1655 | rt->rt6i_idev = ort->rt6i_idev; | 1652 | rt->rt6i_idev = ort->rt6i_idev; |
1656 | if (rt->rt6i_idev) | 1653 | if (rt->rt6i_idev) |
1657 | in6_dev_hold(rt->rt6i_idev); | 1654 | in6_dev_hold(rt->rt6i_idev); |
1658 | rt->u.dst.lastuse = jiffies; | 1655 | rt->dst.lastuse = jiffies; |
1659 | rt->rt6i_expires = 0; | 1656 | rt->rt6i_expires = 0; |
1660 | 1657 | ||
1661 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 1658 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); |
@@ -1689,14 +1686,14 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1689 | if (!fn) | 1686 | if (!fn) |
1690 | goto out; | 1687 | goto out; |
1691 | 1688 | ||
1692 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1689 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1693 | if (rt->rt6i_dev->ifindex != ifindex) | 1690 | if (rt->rt6i_dev->ifindex != ifindex) |
1694 | continue; | 1691 | continue; |
1695 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) | 1692 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) |
1696 | continue; | 1693 | continue; |
1697 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) | 1694 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) |
1698 | continue; | 1695 | continue; |
1699 | dst_hold(&rt->u.dst); | 1696 | dst_hold(&rt->dst); |
1700 | break; | 1697 | break; |
1701 | } | 1698 | } |
1702 | out: | 1699 | out: |
@@ -1744,14 +1741,14 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1744 | return NULL; | 1741 | return NULL; |
1745 | 1742 | ||
1746 | write_lock_bh(&table->tb6_lock); | 1743 | write_lock_bh(&table->tb6_lock); |
1747 | for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) { | 1744 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
1748 | if (dev == rt->rt6i_dev && | 1745 | if (dev == rt->rt6i_dev && |
1749 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1746 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
1750 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) | 1747 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) |
1751 | break; | 1748 | break; |
1752 | } | 1749 | } |
1753 | if (rt) | 1750 | if (rt) |
1754 | dst_hold(&rt->u.dst); | 1751 | dst_hold(&rt->dst); |
1755 | write_unlock_bh(&table->tb6_lock); | 1752 | write_unlock_bh(&table->tb6_lock); |
1756 | return rt; | 1753 | return rt; |
1757 | } | 1754 | } |
@@ -1790,9 +1787,9 @@ void rt6_purge_dflt_routers(struct net *net) | |||
1790 | 1787 | ||
1791 | restart: | 1788 | restart: |
1792 | read_lock_bh(&table->tb6_lock); | 1789 | read_lock_bh(&table->tb6_lock); |
1793 | for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) { | 1790 | for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { |
1794 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { | 1791 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { |
1795 | dst_hold(&rt->u.dst); | 1792 | dst_hold(&rt->dst); |
1796 | read_unlock_bh(&table->tb6_lock); | 1793 | read_unlock_bh(&table->tb6_lock); |
1797 | ip6_del_rt(rt); | 1794 | ip6_del_rt(rt); |
1798 | goto restart; | 1795 | goto restart; |
@@ -1930,15 +1927,15 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1930 | dev_hold(net->loopback_dev); | 1927 | dev_hold(net->loopback_dev); |
1931 | in6_dev_hold(idev); | 1928 | in6_dev_hold(idev); |
1932 | 1929 | ||
1933 | rt->u.dst.flags = DST_HOST; | 1930 | rt->dst.flags = DST_HOST; |
1934 | rt->u.dst.input = ip6_input; | 1931 | rt->dst.input = ip6_input; |
1935 | rt->u.dst.output = ip6_output; | 1932 | rt->dst.output = ip6_output; |
1936 | rt->rt6i_dev = net->loopback_dev; | 1933 | rt->rt6i_dev = net->loopback_dev; |
1937 | rt->rt6i_idev = idev; | 1934 | rt->rt6i_idev = idev; |
1938 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1935 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
1939 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 1936 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
1940 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1937 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
1941 | rt->u.dst.obsolete = -1; | 1938 | rt->dst.obsolete = -1; |
1942 | 1939 | ||
1943 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 1940 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
1944 | if (anycast) | 1941 | if (anycast) |
@@ -1947,7 +1944,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1947 | rt->rt6i_flags |= RTF_LOCAL; | 1944 | rt->rt6i_flags |= RTF_LOCAL; |
1948 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1945 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
1949 | if (IS_ERR(neigh)) { | 1946 | if (IS_ERR(neigh)) { |
1950 | dst_free(&rt->u.dst); | 1947 | dst_free(&rt->dst); |
1951 | 1948 | ||
1952 | /* We are casting this because that is the return | 1949 | /* We are casting this because that is the return |
1953 | * value type. But an errno encoded pointer is the | 1950 | * value type. But an errno encoded pointer is the |
@@ -1962,7 +1959,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1962 | rt->rt6i_dst.plen = 128; | 1959 | rt->rt6i_dst.plen = 128; |
1963 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 1960 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
1964 | 1961 | ||
1965 | atomic_set(&rt->u.dst.__refcnt, 1); | 1962 | atomic_set(&rt->dst.__refcnt, 1); |
1966 | 1963 | ||
1967 | return rt; | 1964 | return rt; |
1968 | } | 1965 | } |
@@ -2033,12 +2030,12 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2033 | PMTU discouvery. | 2030 | PMTU discouvery. |
2034 | */ | 2031 | */ |
2035 | if (rt->rt6i_dev == arg->dev && | 2032 | if (rt->rt6i_dev == arg->dev && |
2036 | !dst_metric_locked(&rt->u.dst, RTAX_MTU) && | 2033 | !dst_metric_locked(&rt->dst, RTAX_MTU) && |
2037 | (dst_mtu(&rt->u.dst) >= arg->mtu || | 2034 | (dst_mtu(&rt->dst) >= arg->mtu || |
2038 | (dst_mtu(&rt->u.dst) < arg->mtu && | 2035 | (dst_mtu(&rt->dst) < arg->mtu && |
2039 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 2036 | dst_mtu(&rt->dst) == idev->cnf.mtu6))) { |
2040 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 2037 | rt->dst.metrics[RTAX_MTU-1] = arg->mtu; |
2041 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); | 2038 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
2042 | } | 2039 | } |
2043 | return 0; | 2040 | return 0; |
2044 | } | 2041 | } |
@@ -2252,20 +2249,20 @@ static int rt6_fill_node(struct net *net, | |||
2252 | #endif | 2249 | #endif |
2253 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2250 | NLA_PUT_U32(skb, RTA_IIF, iif); |
2254 | } else if (dst) { | 2251 | } else if (dst) { |
2255 | struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst); | 2252 | struct inet6_dev *idev = ip6_dst_idev(&rt->dst); |
2256 | struct in6_addr saddr_buf; | 2253 | struct in6_addr saddr_buf; |
2257 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2254 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
2258 | dst, 0, &saddr_buf) == 0) | 2255 | dst, 0, &saddr_buf) == 0) |
2259 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2256 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2260 | } | 2257 | } |
2261 | 2258 | ||
2262 | if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) | 2259 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) |
2263 | goto nla_put_failure; | 2260 | goto nla_put_failure; |
2264 | 2261 | ||
2265 | if (rt->u.dst.neighbour) | 2262 | if (rt->dst.neighbour) |
2266 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); | 2263 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); |
2267 | 2264 | ||
2268 | if (rt->u.dst.dev) | 2265 | if (rt->dst.dev) |
2269 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2266 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
2270 | 2267 | ||
2271 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2268 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
@@ -2277,8 +2274,8 @@ static int rt6_fill_node(struct net *net, | |||
2277 | else | 2274 | else |
2278 | expires = INT_MAX; | 2275 | expires = INT_MAX; |
2279 | 2276 | ||
2280 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, | 2277 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, |
2281 | expires, rt->u.dst.error) < 0) | 2278 | expires, rt->dst.error) < 0) |
2282 | goto nla_put_failure; | 2279 | goto nla_put_failure; |
2283 | 2280 | ||
2284 | return nlmsg_end(skb, nlh); | 2281 | return nlmsg_end(skb, nlh); |
@@ -2364,7 +2361,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2364 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2361 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2365 | 2362 | ||
2366 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); | 2363 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
2367 | skb_dst_set(skb, &rt->u.dst); | 2364 | skb_dst_set(skb, &rt->dst); |
2368 | 2365 | ||
2369 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2366 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
2370 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2367 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
@@ -2416,12 +2413,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
2416 | struct net *net = dev_net(dev); | 2413 | struct net *net = dev_net(dev); |
2417 | 2414 | ||
2418 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | 2415 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { |
2419 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | 2416 | net->ipv6.ip6_null_entry->dst.dev = dev; |
2420 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | 2417 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); |
2421 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2418 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2422 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | 2419 | net->ipv6.ip6_prohibit_entry->dst.dev = dev; |
2423 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | 2420 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); |
2424 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | 2421 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; |
2425 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | 2422 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); |
2426 | #endif | 2423 | #endif |
2427 | } | 2424 | } |
@@ -2464,8 +2461,8 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2464 | seq_puts(m, "00000000000000000000000000000000"); | 2461 | seq_puts(m, "00000000000000000000000000000000"); |
2465 | } | 2462 | } |
2466 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2463 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
2467 | rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), | 2464 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
2468 | rt->u.dst.__use, rt->rt6i_flags, | 2465 | rt->dst.__use, rt->rt6i_flags, |
2469 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); | 2466 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); |
2470 | return 0; | 2467 | return 0; |
2471 | } | 2468 | } |
@@ -2646,9 +2643,9 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2646 | GFP_KERNEL); | 2643 | GFP_KERNEL); |
2647 | if (!net->ipv6.ip6_null_entry) | 2644 | if (!net->ipv6.ip6_null_entry) |
2648 | goto out_ip6_dst_ops; | 2645 | goto out_ip6_dst_ops; |
2649 | net->ipv6.ip6_null_entry->u.dst.path = | 2646 | net->ipv6.ip6_null_entry->dst.path = |
2650 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2647 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2651 | net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2648 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2652 | 2649 | ||
2653 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2650 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2654 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2651 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2656,18 +2653,18 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2656 | GFP_KERNEL); | 2653 | GFP_KERNEL); |
2657 | if (!net->ipv6.ip6_prohibit_entry) | 2654 | if (!net->ipv6.ip6_prohibit_entry) |
2658 | goto out_ip6_null_entry; | 2655 | goto out_ip6_null_entry; |
2659 | net->ipv6.ip6_prohibit_entry->u.dst.path = | 2656 | net->ipv6.ip6_prohibit_entry->dst.path = |
2660 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2657 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2661 | net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2658 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2662 | 2659 | ||
2663 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2660 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2664 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2661 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
2665 | GFP_KERNEL); | 2662 | GFP_KERNEL); |
2666 | if (!net->ipv6.ip6_blk_hole_entry) | 2663 | if (!net->ipv6.ip6_blk_hole_entry) |
2667 | goto out_ip6_prohibit_entry; | 2664 | goto out_ip6_prohibit_entry; |
2668 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | 2665 | net->ipv6.ip6_blk_hole_entry->dst.path = |
2669 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2666 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2670 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2667 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2671 | #endif | 2668 | #endif |
2672 | 2669 | ||
2673 | net->ipv6.sysctl.flush_delay = 0; | 2670 | net->ipv6.sysctl.flush_delay = 0; |
@@ -2742,12 +2739,12 @@ int __init ip6_route_init(void) | |||
2742 | /* Registering of the loopback is done before this portion of code, | 2739 | /* Registering of the loopback is done before this portion of code, |
2743 | * the loopback reference in rt6_info will not be taken, do it | 2740 | * the loopback reference in rt6_info will not be taken, do it |
2744 | * manually for init_net */ | 2741 | * manually for init_net */ |
2745 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | 2742 | init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; |
2746 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2743 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
2747 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2744 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2748 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | 2745 | init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; |
2749 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2746 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
2750 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | 2747 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; |
2751 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2748 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
2752 | #endif | 2749 | #endif |
2753 | ret = fib6_init(); | 2750 | ret = fib6_init(); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e51e650ea80b..4699cd3c3118 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -249,8 +249,6 @@ failed: | |||
249 | return NULL; | 249 | return NULL; |
250 | } | 250 | } |
251 | 251 | ||
252 | static DEFINE_SPINLOCK(ipip6_prl_lock); | ||
253 | |||
254 | #define for_each_prl_rcu(start) \ | 252 | #define for_each_prl_rcu(start) \ |
255 | for (prl = rcu_dereference(start); \ | 253 | for (prl = rcu_dereference(start); \ |
256 | prl; \ | 254 | prl; \ |
@@ -340,7 +338,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
340 | if (a->addr == htonl(INADDR_ANY)) | 338 | if (a->addr == htonl(INADDR_ANY)) |
341 | return -EINVAL; | 339 | return -EINVAL; |
342 | 340 | ||
343 | spin_lock(&ipip6_prl_lock); | 341 | ASSERT_RTNL(); |
344 | 342 | ||
345 | for (p = t->prl; p; p = p->next) { | 343 | for (p = t->prl; p; p = p->next) { |
346 | if (p->addr == a->addr) { | 344 | if (p->addr == a->addr) { |
@@ -370,7 +368,6 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
370 | t->prl_count++; | 368 | t->prl_count++; |
371 | rcu_assign_pointer(t->prl, p); | 369 | rcu_assign_pointer(t->prl, p); |
372 | out: | 370 | out: |
373 | spin_unlock(&ipip6_prl_lock); | ||
374 | return err; | 371 | return err; |
375 | } | 372 | } |
376 | 373 | ||
@@ -397,7 +394,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
397 | struct ip_tunnel_prl_entry *x, **p; | 394 | struct ip_tunnel_prl_entry *x, **p; |
398 | int err = 0; | 395 | int err = 0; |
399 | 396 | ||
400 | spin_lock(&ipip6_prl_lock); | 397 | ASSERT_RTNL(); |
401 | 398 | ||
402 | if (a && a->addr != htonl(INADDR_ANY)) { | 399 | if (a && a->addr != htonl(INADDR_ANY)) { |
403 | for (p = &t->prl; *p; p = &(*p)->next) { | 400 | for (p = &t->prl; *p; p = &(*p)->next) { |
@@ -419,7 +416,6 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
419 | } | 416 | } |
420 | } | 417 | } |
421 | out: | 418 | out: |
422 | spin_unlock(&ipip6_prl_lock); | ||
423 | return err; | 419 | return err; |
424 | } | 420 | } |
425 | 421 | ||
@@ -716,7 +712,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
716 | stats->tx_carrier_errors++; | 712 | stats->tx_carrier_errors++; |
717 | goto tx_error_icmp; | 713 | goto tx_error_icmp; |
718 | } | 714 | } |
719 | tdev = rt->u.dst.dev; | 715 | tdev = rt->dst.dev; |
720 | 716 | ||
721 | if (tdev == dev) { | 717 | if (tdev == dev) { |
722 | ip_rt_put(rt); | 718 | ip_rt_put(rt); |
@@ -725,7 +721,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
725 | } | 721 | } |
726 | 722 | ||
727 | if (df) { | 723 | if (df) { |
728 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 724 | mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); |
729 | 725 | ||
730 | if (mtu < 68) { | 726 | if (mtu < 68) { |
731 | stats->collisions++; | 727 | stats->collisions++; |
@@ -784,7 +780,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
784 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 780 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
785 | IPCB(skb)->flags = 0; | 781 | IPCB(skb)->flags = 0; |
786 | skb_dst_drop(skb); | 782 | skb_dst_drop(skb); |
787 | skb_dst_set(skb, &rt->u.dst); | 783 | skb_dst_set(skb, &rt->dst); |
788 | 784 | ||
789 | /* | 785 | /* |
790 | * Push down and install the IPIP header. | 786 | * Push down and install the IPIP header. |
@@ -833,7 +829,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
833 | .proto = IPPROTO_IPV6 }; | 829 | .proto = IPPROTO_IPV6 }; |
834 | struct rtable *rt; | 830 | struct rtable *rt; |
835 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 831 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { |
836 | tdev = rt->u.dst.dev; | 832 | tdev = rt->dst.dev; |
837 | ip_rt_put(rt); | 833 | ip_rt_put(rt); |
838 | } | 834 | } |
839 | dev->flags |= IFF_POINTOPOINT; | 835 | dev->flags |= IFF_POINTOPOINT; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 34d1f0690d7e..09fd34f0dbf2 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -27,28 +27,17 @@ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | |||
27 | #define COOKIEBITS 24 /* Upper bits store count */ | 27 | #define COOKIEBITS 24 /* Upper bits store count */ |
28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) |
29 | 29 | ||
30 | /* | 30 | /* Table must be sorted. */ |
31 | * This table has to be sorted and terminated with (__u16)-1. | ||
32 | * XXX generate a better table. | ||
33 | * Unresolved Issues: HIPPI with a 64k MSS is not well supported. | ||
34 | * | ||
35 | * Taken directly from ipv4 implementation. | ||
36 | * Should this list be modified for ipv6 use or is it close enough? | ||
37 | * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart | ||
38 | */ | ||
39 | static __u16 const msstab[] = { | 31 | static __u16 const msstab[] = { |
40 | 64 - 1, | 32 | 64, |
41 | 256 - 1, | 33 | 512, |
42 | 512 - 1, | 34 | 536, |
43 | 536 - 1, | 35 | 1280 - 60, |
44 | 1024 - 1, | 36 | 1480 - 60, |
45 | 1440 - 1, | 37 | 1500 - 60, |
46 | 1460 - 1, | 38 | 4460 - 60, |
47 | 4312 - 1, | 39 | 9000 - 60, |
48 | (__u16)-1 | ||
49 | }; | 40 | }; |
50 | /* The number doesn't include the -1 terminator */ | ||
51 | #define NUM_MSS (ARRAY_SIZE(msstab) - 1) | ||
52 | 41 | ||
53 | /* | 42 | /* |
54 | * This (misnamed) value is the age of syncookie which is permitted. | 43 | * This (misnamed) value is the age of syncookie which is permitted. |
@@ -134,9 +123,11 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | |||
134 | 123 | ||
135 | tcp_synq_overflow(sk); | 124 | tcp_synq_overflow(sk); |
136 | 125 | ||
137 | for (mssind = 0; mss > msstab[mssind + 1]; mssind++) | 126 | for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--) |
138 | ; | 127 | if (mss >= msstab[mssind]) |
139 | *mssp = msstab[mssind] + 1; | 128 | break; |
129 | |||
130 | *mssp = msstab[mssind]; | ||
140 | 131 | ||
141 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); | 132 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); |
142 | 133 | ||
@@ -154,7 +145,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | |||
154 | th->source, th->dest, seq, | 145 | th->source, th->dest, seq, |
155 | jiffies / (HZ * 60), COUNTER_TRIES); | 146 | jiffies / (HZ * 60), COUNTER_TRIES); |
156 | 147 | ||
157 | return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; | 148 | return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; |
158 | } | 149 | } |
159 | 150 | ||
160 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 151 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) |
@@ -173,8 +164,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
173 | int mss; | 164 | int mss; |
174 | struct dst_entry *dst; | 165 | struct dst_entry *dst; |
175 | __u8 rcv_wscale; | 166 | __u8 rcv_wscale; |
167 | bool ecn_ok; | ||
176 | 168 | ||
177 | if (!sysctl_tcp_syncookies || !th->ack) | 169 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
178 | goto out; | 170 | goto out; |
179 | 171 | ||
180 | if (tcp_synq_no_recent_overflow(sk) || | 172 | if (tcp_synq_no_recent_overflow(sk) || |
@@ -189,8 +181,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
189 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 181 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
190 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 182 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
191 | 183 | ||
192 | if (tcp_opt.saw_tstamp) | 184 | if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) |
193 | cookie_check_timestamp(&tcp_opt); | 185 | goto out; |
194 | 186 | ||
195 | ret = NULL; | 187 | ret = NULL; |
196 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 188 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); |
@@ -224,9 +216,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
224 | 216 | ||
225 | req->expires = 0UL; | 217 | req->expires = 0UL; |
226 | req->retrans = 0; | 218 | req->retrans = 0; |
227 | ireq->ecn_ok = 0; | 219 | ireq->ecn_ok = ecn_ok; |
228 | ireq->snd_wscale = tcp_opt.snd_wscale; | 220 | ireq->snd_wscale = tcp_opt.snd_wscale; |
229 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
230 | ireq->sack_ok = tcp_opt.sack_ok; | 221 | ireq->sack_ok = tcp_opt.sack_ok; |
231 | ireq->wscale_ok = tcp_opt.wscale_ok; | 222 | ireq->wscale_ok = tcp_opt.wscale_ok; |
232 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 223 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |
@@ -240,17 +231,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
240 | * me if there is a preferred way. | 231 | * me if there is a preferred way. |
241 | */ | 232 | */ |
242 | { | 233 | { |
243 | struct in6_addr *final_p = NULL, final; | 234 | struct in6_addr *final_p, final; |
244 | struct flowi fl; | 235 | struct flowi fl; |
245 | memset(&fl, 0, sizeof(fl)); | 236 | memset(&fl, 0, sizeof(fl)); |
246 | fl.proto = IPPROTO_TCP; | 237 | fl.proto = IPPROTO_TCP; |
247 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 238 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); |
248 | if (np->opt && np->opt->srcrt) { | 239 | final_p = fl6_update_dst(&fl, np->opt, &final); |
249 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
250 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
251 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
252 | final_p = &final; | ||
253 | } | ||
254 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 240 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); |
255 | fl.oif = sk->sk_bound_dev_if; | 241 | fl.oif = sk->sk_bound_dev_if; |
256 | fl.mark = sk->sk_mark; | 242 | fl.mark = sk->sk_mark; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2b7c3a100e2c..fe6d40418c0b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
129 | struct inet_connection_sock *icsk = inet_csk(sk); | 129 | struct inet_connection_sock *icsk = inet_csk(sk); |
130 | struct ipv6_pinfo *np = inet6_sk(sk); | 130 | struct ipv6_pinfo *np = inet6_sk(sk); |
131 | struct tcp_sock *tp = tcp_sk(sk); | 131 | struct tcp_sock *tp = tcp_sk(sk); |
132 | struct in6_addr *saddr = NULL, *final_p = NULL, final; | 132 | struct in6_addr *saddr = NULL, *final_p, final; |
133 | struct flowi fl; | 133 | struct flowi fl; |
134 | struct dst_entry *dst; | 134 | struct dst_entry *dst; |
135 | int addr_type; | 135 | int addr_type; |
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
250 | fl.fl_ip_dport = usin->sin6_port; | 250 | fl.fl_ip_dport = usin->sin6_port; |
251 | fl.fl_ip_sport = inet->inet_sport; | 251 | fl.fl_ip_sport = inet->inet_sport; |
252 | 252 | ||
253 | if (np->opt && np->opt->srcrt) { | 253 | final_p = fl6_update_dst(&fl, np->opt, &final); |
254 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
255 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
256 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
257 | final_p = &final; | ||
258 | } | ||
259 | 254 | ||
260 | security_sk_classify_flow(sk, &fl); | 255 | security_sk_classify_flow(sk, &fl); |
261 | 256 | ||
@@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
477 | struct ipv6_pinfo *np = inet6_sk(sk); | 472 | struct ipv6_pinfo *np = inet6_sk(sk); |
478 | struct sk_buff * skb; | 473 | struct sk_buff * skb; |
479 | struct ipv6_txoptions *opt = NULL; | 474 | struct ipv6_txoptions *opt = NULL; |
480 | struct in6_addr * final_p = NULL, final; | 475 | struct in6_addr * final_p, final; |
481 | struct flowi fl; | 476 | struct flowi fl; |
482 | struct dst_entry *dst; | 477 | struct dst_entry *dst; |
483 | int err = -1; | 478 | int err = -1; |
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
494 | security_req_classify_flow(req, &fl); | 489 | security_req_classify_flow(req, &fl); |
495 | 490 | ||
496 | opt = np->opt; | 491 | opt = np->opt; |
497 | if (opt && opt->srcrt) { | 492 | final_p = fl6_update_dst(&fl, opt, &final); |
498 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
499 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
500 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
501 | final_p = &final; | ||
502 | } | ||
503 | 493 | ||
504 | err = ip6_dst_lookup(sk, &dst, &fl); | 494 | err = ip6_dst_lookup(sk, &dst, &fl); |
505 | if (err) | 495 | if (err) |
@@ -1167,7 +1157,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1167 | } | 1157 | } |
1168 | 1158 | ||
1169 | #ifdef CONFIG_SYN_COOKIES | 1159 | #ifdef CONFIG_SYN_COOKIES |
1170 | if (!th->rst && !th->syn && th->ack) | 1160 | if (!th->syn) |
1171 | sk = cookie_v6_check(sk, skb); | 1161 | sk = cookie_v6_check(sk, skb); |
1172 | #endif | 1162 | #endif |
1173 | return sk; | 1163 | return sk; |
@@ -1279,13 +1269,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1279 | treq = inet6_rsk(req); | 1269 | treq = inet6_rsk(req); |
1280 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1270 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1281 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1271 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1282 | if (!want_cookie) | 1272 | if (!want_cookie || tmp_opt.tstamp_ok) |
1283 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1273 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1284 | 1274 | ||
1285 | if (want_cookie) { | 1275 | if (!isn) { |
1286 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
1287 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1288 | } else if (!isn) { | ||
1289 | if (ipv6_opt_accepted(sk, skb) || | 1276 | if (ipv6_opt_accepted(sk, skb) || |
1290 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1277 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
1291 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1278 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { |
@@ -1298,8 +1285,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1298 | if (!sk->sk_bound_dev_if && | 1285 | if (!sk->sk_bound_dev_if && |
1299 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1286 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1300 | treq->iif = inet6_iif(skb); | 1287 | treq->iif = inet6_iif(skb); |
1301 | 1288 | if (!want_cookie) { | |
1302 | isn = tcp_v6_init_sequence(skb); | 1289 | isn = tcp_v6_init_sequence(skb); |
1290 | } else { | ||
1291 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
1292 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1293 | } | ||
1303 | } | 1294 | } |
1304 | tcp_rsk(req)->snt_isn = isn; | 1295 | tcp_rsk(req)->snt_isn = isn; |
1305 | 1296 | ||
@@ -1392,18 +1383,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1392 | goto out_overflow; | 1383 | goto out_overflow; |
1393 | 1384 | ||
1394 | if (dst == NULL) { | 1385 | if (dst == NULL) { |
1395 | struct in6_addr *final_p = NULL, final; | 1386 | struct in6_addr *final_p, final; |
1396 | struct flowi fl; | 1387 | struct flowi fl; |
1397 | 1388 | ||
1398 | memset(&fl, 0, sizeof(fl)); | 1389 | memset(&fl, 0, sizeof(fl)); |
1399 | fl.proto = IPPROTO_TCP; | 1390 | fl.proto = IPPROTO_TCP; |
1400 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 1391 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
1401 | if (opt && opt->srcrt) { | 1392 | final_p = fl6_update_dst(&fl, opt, &final); |
1402 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
1403 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
1404 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
1405 | final_p = &final; | ||
1406 | } | ||
1407 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 1393 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
1408 | fl.oif = sk->sk_bound_dev_if; | 1394 | fl.oif = sk->sk_bound_dev_if; |
1409 | fl.mark = sk->sk_mark; | 1395 | fl.mark = sk->sk_mark; |
@@ -2156,6 +2142,8 @@ struct proto tcpv6_prot = { | |||
2156 | .setsockopt = tcp_setsockopt, | 2142 | .setsockopt = tcp_setsockopt, |
2157 | .getsockopt = tcp_getsockopt, | 2143 | .getsockopt = tcp_getsockopt, |
2158 | .recvmsg = tcp_recvmsg, | 2144 | .recvmsg = tcp_recvmsg, |
2145 | .sendmsg = tcp_sendmsg, | ||
2146 | .sendpage = tcp_sendpage, | ||
2159 | .backlog_rcv = tcp_v6_do_rcv, | 2147 | .backlog_rcv = tcp_v6_do_rcv, |
2160 | .hash = tcp_v6_hash, | 2148 | .hash = tcp_v6_hash, |
2161 | .unhash = inet_unhash, | 2149 | .unhash = inet_unhash, |
@@ -2174,6 +2162,7 @@ struct proto tcpv6_prot = { | |||
2174 | .twsk_prot = &tcp6_timewait_sock_ops, | 2162 | .twsk_prot = &tcp6_timewait_sock_ops, |
2175 | .rsk_prot = &tcp6_request_sock_ops, | 2163 | .rsk_prot = &tcp6_request_sock_ops, |
2176 | .h.hashinfo = &tcp_hashinfo, | 2164 | .h.hashinfo = &tcp_hashinfo, |
2165 | .no_autobind = true, | ||
2177 | #ifdef CONFIG_COMPAT | 2166 | #ifdef CONFIG_COMPAT |
2178 | .compat_setsockopt = compat_tcp_setsockopt, | 2167 | .compat_setsockopt = compat_tcp_setsockopt, |
2179 | .compat_getsockopt = compat_tcp_getsockopt, | 2168 | .compat_getsockopt = compat_tcp_getsockopt, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 3d7a2c0b836a..1dd1affdead2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -328,6 +328,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
328 | int err; | 328 | int err; |
329 | int is_udplite = IS_UDPLITE(sk); | 329 | int is_udplite = IS_UDPLITE(sk); |
330 | int is_udp4; | 330 | int is_udp4; |
331 | bool slow; | ||
331 | 332 | ||
332 | if (addr_len) | 333 | if (addr_len) |
333 | *addr_len=sizeof(struct sockaddr_in6); | 334 | *addr_len=sizeof(struct sockaddr_in6); |
@@ -424,7 +425,7 @@ out: | |||
424 | return err; | 425 | return err; |
425 | 426 | ||
426 | csum_copy_err: | 427 | csum_copy_err: |
427 | lock_sock_bh(sk); | 428 | slow = lock_sock_fast(sk); |
428 | if (!skb_kill_datagram(sk, skb, flags)) { | 429 | if (!skb_kill_datagram(sk, skb, flags)) { |
429 | if (is_udp4) | 430 | if (is_udp4) |
430 | UDP_INC_STATS_USER(sock_net(sk), | 431 | UDP_INC_STATS_USER(sock_net(sk), |
@@ -433,7 +434,7 @@ csum_copy_err: | |||
433 | UDP6_INC_STATS_USER(sock_net(sk), | 434 | UDP6_INC_STATS_USER(sock_net(sk), |
434 | UDP_MIB_INERRORS, is_udplite); | 435 | UDP_MIB_INERRORS, is_udplite); |
435 | } | 436 | } |
436 | unlock_sock_bh(sk); | 437 | unlock_sock_fast(sk, slow); |
437 | 438 | ||
438 | if (flags & MSG_DONTWAIT) | 439 | if (flags & MSG_DONTWAIT) |
439 | return -EAGAIN; | 440 | return -EAGAIN; |
@@ -926,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
926 | struct inet_sock *inet = inet_sk(sk); | 927 | struct inet_sock *inet = inet_sk(sk); |
927 | struct ipv6_pinfo *np = inet6_sk(sk); | 928 | struct ipv6_pinfo *np = inet6_sk(sk); |
928 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; | 929 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; |
929 | struct in6_addr *daddr, *final_p = NULL, final; | 930 | struct in6_addr *daddr, *final_p, final; |
930 | struct ipv6_txoptions *opt = NULL; | 931 | struct ipv6_txoptions *opt = NULL; |
931 | struct ip6_flowlabel *flowlabel = NULL; | 932 | struct ip6_flowlabel *flowlabel = NULL; |
932 | struct flowi fl; | 933 | struct flowi fl; |
@@ -1096,14 +1097,9 @@ do_udp_sendmsg: | |||
1096 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1097 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
1097 | fl.fl_ip_sport = inet->inet_sport; | 1098 | fl.fl_ip_sport = inet->inet_sport; |
1098 | 1099 | ||
1099 | /* merge ip6_build_xmit from ip6_output */ | 1100 | final_p = fl6_update_dst(&fl, opt, &final); |
1100 | if (opt && opt->srcrt) { | 1101 | if (final_p) |
1101 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
1102 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
1103 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
1104 | final_p = &final; | ||
1105 | connected = 0; | 1102 | connected = 0; |
1106 | } | ||
1107 | 1103 | ||
1108 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1104 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { |
1109 | fl.oif = np->mcast_oif; | 1105 | fl.oif = np->mcast_oif; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 4a0e77e14468..6baeabbbca82 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -124,6 +124,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
124 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 124 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; |
125 | 125 | ||
126 | memset(fl, 0, sizeof(struct flowi)); | 126 | memset(fl, 0, sizeof(struct flowi)); |
127 | fl->mark = skb->mark; | ||
128 | |||
127 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); | 129 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); |
128 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); | 130 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); |
129 | 131 | ||