aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/inet6_connection_sock.c23
-rw-r--r--net/ipv6/ip6_fib.c4
-rw-r--r--net/ipv6/route.c19
-rw-r--r--net/ipv6/tcp_ipv6.c5
-rw-r--r--net/ipv6/udp.c11
5 files changed, 31 insertions, 31 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 0251a6005be8..c4f934176cab 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
175 const struct in6_addr *saddr) 175 const struct in6_addr *saddr)
176{ 176{
177 __ip6_dst_store(sk, dst, daddr, saddr); 177 __ip6_dst_store(sk, dst, daddr, saddr);
178
179#ifdef CONFIG_XFRM
180 {
181 struct rt6_info *rt = (struct rt6_info *)dst;
182 rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
183 }
184#endif
185} 178}
186 179
187static inline 180static inline
188struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) 181struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
189{ 182{
190 struct dst_entry *dst; 183 return __sk_dst_check(sk, cookie);
191
192 dst = __sk_dst_check(sk, cookie);
193
194#ifdef CONFIG_XFRM
195 if (dst) {
196 struct rt6_info *rt = (struct rt6_info *)dst;
197 if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
198 __sk_dst_reset(sk);
199 dst = NULL;
200 }
201 }
202#endif
203
204 return dst;
205} 184}
206 185
207static struct dst_entry *inet6_csk_route_socket(struct sock *sk, 186static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 13690d650c3e..286acfc21250 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -819,6 +819,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
819 offsetof(struct rt6_info, rt6i_src), 819 offsetof(struct rt6_info, rt6i_src),
820 allow_create, replace_required); 820 allow_create, replace_required);
821 821
822 if (IS_ERR(sn)) {
823 err = PTR_ERR(sn);
824 sn = NULL;
825 }
822 if (!sn) { 826 if (!sn) {
823 /* If it is failed, discard just allocated 827 /* If it is failed, discard just allocated
824 root, and then (in st_failure) stale node 828 root, and then (in st_failure) stale node
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8e80fd279100..854e4018d205 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = {
226 .dst = { 226 .dst = {
227 .__refcnt = ATOMIC_INIT(1), 227 .__refcnt = ATOMIC_INIT(1),
228 .__use = 1, 228 .__use = 1,
229 .obsolete = -1, 229 .obsolete = DST_OBSOLETE_FORCE_CHK,
230 .error = -ENETUNREACH, 230 .error = -ENETUNREACH,
231 .input = ip6_pkt_discard, 231 .input = ip6_pkt_discard,
232 .output = ip6_pkt_discard_out, 232 .output = ip6_pkt_discard_out,
@@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
246 .dst = { 246 .dst = {
247 .__refcnt = ATOMIC_INIT(1), 247 .__refcnt = ATOMIC_INIT(1),
248 .__use = 1, 248 .__use = 1,
249 .obsolete = -1, 249 .obsolete = DST_OBSOLETE_FORCE_CHK,
250 .error = -EACCES, 250 .error = -EACCES,
251 .input = ip6_pkt_prohibit, 251 .input = ip6_pkt_prohibit,
252 .output = ip6_pkt_prohibit_out, 252 .output = ip6_pkt_prohibit_out,
@@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
261 .dst = { 261 .dst = {
262 .__refcnt = ATOMIC_INIT(1), 262 .__refcnt = ATOMIC_INIT(1),
263 .__use = 1, 263 .__use = 1,
264 .obsolete = -1, 264 .obsolete = DST_OBSOLETE_FORCE_CHK,
265 .error = -EINVAL, 265 .error = -EINVAL,
266 .input = dst_discard, 266 .input = dst_discard,
267 .output = dst_discard, 267 .output = dst_discard,
@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
281 struct fib6_table *table) 281 struct fib6_table *table)
282{ 282{
283 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, 283 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
284 0, DST_OBSOLETE_NONE, flags); 284 0, DST_OBSOLETE_FORCE_CHK, flags);
285 285
286 if (rt) { 286 if (rt) {
287 struct dst_entry *dst = &rt->dst; 287 struct dst_entry *dst = &rt->dst;
288 288
289 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); 289 memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
290 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); 290 rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
291 rt->rt6i_genid = rt_genid(net);
291 } 292 }
292 return rt; 293 return rt;
293} 294}
@@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1031 1032
1032 rt = (struct rt6_info *) dst; 1033 rt = (struct rt6_info *) dst;
1033 1034
1035 /* All IPV6 dsts are created with ->obsolete set to the value
1036 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1037 * into this function always.
1038 */
1039 if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
1040 return NULL;
1041
1034 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { 1042 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
1035 if (rt->rt6i_peer_genid != rt6_peer_genid()) { 1043 if (rt->rt6i_peer_genid != rt6_peer_genid()) {
1036 if (!rt6_has_peer(rt)) 1044 if (!rt6_has_peer(rt))
@@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg)
1397 goto out; 1405 goto out;
1398 } 1406 }
1399 1407
1400 rt->dst.obsolete = -1;
1401
1402 if (cfg->fc_flags & RTF_EXPIRES) 1408 if (cfg->fc_flags & RTF_EXPIRES)
1403 rt6_set_expires(rt, jiffies + 1409 rt6_set_expires(rt, jiffies +
1404 clock_t_to_jiffies(cfg->fc_expires)); 1410 clock_t_to_jiffies(cfg->fc_expires));
@@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2080 rt->dst.input = ip6_input; 2086 rt->dst.input = ip6_input;
2081 rt->dst.output = ip6_output; 2087 rt->dst.output = ip6_output;
2082 rt->rt6i_idev = idev; 2088 rt->rt6i_idev = idev;
2083 rt->dst.obsolete = -1;
2084 2089
2085 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; 2090 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
2086 if (anycast) 2091 if (anycast)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index a3e60cc04a8a..acd32e3f1b68 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
403 tp->mtu_info = ntohl(info); 403 tp->mtu_info = ntohl(info);
404 if (!sock_owned_by_user(sk)) 404 if (!sock_owned_by_user(sk))
405 tcp_v6_mtu_reduced(sk); 405 tcp_v6_mtu_reduced(sk);
406 else 406 else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
407 set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); 407 &tp->tsq_flags))
408 sock_hold(sk);
408 goto out; 409 goto out;
409 } 410 }
410 411
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 99d0077b56b8..07e2bfef6845 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -394,6 +394,17 @@ try_again:
394 } 394 }
395 if (unlikely(err)) { 395 if (unlikely(err)) {
396 trace_kfree_skb(skb, udpv6_recvmsg); 396 trace_kfree_skb(skb, udpv6_recvmsg);
397 if (!peeked) {
398 atomic_inc(&sk->sk_drops);
399 if (is_udp4)
400 UDP_INC_STATS_USER(sock_net(sk),
401 UDP_MIB_INERRORS,
402 is_udplite);
403 else
404 UDP6_INC_STATS_USER(sock_net(sk),
405 UDP_MIB_INERRORS,
406 is_udplite);
407 }
397 goto out_free; 408 goto out_free;
398 } 409 }
399 if (!peeked) { 410 if (!peeked) {