Commit 6f3118b5 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by David S. Miller

ipv6: use net->rt_genid to check dst validity

IPv6 dst should take care of rt_genid too. When a xfrm policy is inserted or
deleted, all dst should be invalidated.
To force the validation, dst entries should be created with ->obsolete set to
DST_OBSOLETE_FORCE_CHK. This was already the case for all functions calling
ip6_dst_alloc(), except for ip6_rt_copy().

As a consequence, we can remove the specific code in inet6_connection_sock.
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ee8372dd
...@@ -111,9 +111,8 @@ struct rt6_info { ...@@ -111,9 +111,8 @@ struct rt6_info {
struct inet6_dev *rt6i_idev; struct inet6_dev *rt6i_idev;
unsigned long _rt6i_peer; unsigned long _rt6i_peer;
#ifdef CONFIG_XFRM u32 rt6i_genid;
u32 rt6i_flow_cache_genid;
#endif
/* more non-fragment space at head required */ /* more non-fragment space at head required */
unsigned short rt6i_nfheader_len; unsigned short rt6i_nfheader_len;
......
...@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, ...@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
const struct in6_addr *saddr) const struct in6_addr *saddr)
{ {
__ip6_dst_store(sk, dst, daddr, saddr); __ip6_dst_store(sk, dst, daddr, saddr);
#ifdef CONFIG_XFRM
{
struct rt6_info *rt = (struct rt6_info *)dst;
rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
}
#endif
} }
static inline static inline
struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
{ {
struct dst_entry *dst; return __sk_dst_check(sk, cookie);
dst = __sk_dst_check(sk, cookie);
#ifdef CONFIG_XFRM
if (dst) {
struct rt6_info *rt = (struct rt6_info *)dst;
if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
__sk_dst_reset(sk);
dst = NULL;
}
}
#endif
return dst;
} }
static struct dst_entry *inet6_csk_route_socket(struct sock *sk, static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
......
...@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, ...@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
struct fib6_table *table) struct fib6_table *table)
{ {
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
0, DST_OBSOLETE_NONE, flags); 0, DST_OBSOLETE_FORCE_CHK, flags);
if (rt) { if (rt) {
struct dst_entry *dst = &rt->dst; struct dst_entry *dst = &rt->dst;
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
rt->rt6i_genid = rt_genid(net);
} }
return rt; return rt;
} }
...@@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) ...@@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
rt = (struct rt6_info *) dst; rt = (struct rt6_info *) dst;
/* All IPV6 dsts are created with ->obsolete set to the value
* DST_OBSOLETE_FORCE_CHK which forces validation calls down
* into this function always.
*/
if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
return NULL;
if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
if (rt->rt6i_peer_genid != rt6_peer_genid()) { if (rt->rt6i_peer_genid != rt6_peer_genid()) {
if (!rt6_has_peer(rt)) if (!rt6_has_peer(rt))
...@@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg) ...@@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg)
goto out; goto out;
} }
rt->dst.obsolete = -1;
if (cfg->fc_flags & RTF_EXPIRES) if (cfg->fc_flags & RTF_EXPIRES)
rt6_set_expires(rt, jiffies + rt6_set_expires(rt, jiffies +
clock_t_to_jiffies(cfg->fc_expires)); clock_t_to_jiffies(cfg->fc_expires));
...@@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, ...@@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->dst.input = ip6_input; rt->dst.input = ip6_input;
rt->dst.output = ip6_output; rt->dst.output = ip6_output;
rt->rt6i_idev = idev; rt->rt6i_idev = idev;
rt->dst.obsolete = -1;
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
if (anycast) if (anycast)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment