aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoriaki TAKAMIYA <takamiya@po.ntts.co.jp>2007-09-06 06:31:25 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:48:32 -0400
commita47ed4cd8cb0709723392f5b841e9015f765d0a6 (patch)
tree6b79a4b94602bbc0e27df9a6a869253438833f74
parente773e4faa19c54c2f32ddd16add2919588488bd9 (diff)
[IPV6] XFRM: Fix connected socket to use transformation.
When XFRM policy and state are ready after TCP connection is started, the traffic should be transformed immediately, however it does not on IPv6 TCP. It depends on a dst cache replacement policy with connected socket. It seems that the replacement is always done for IPv4, however, on IPv6 case it is done only when routing cookie is changed. This patch fix that non-transformation dst can be changed to transformation one. This behavior is required by MIPv6 and improves IPv6 IPsec. Fixes by Masahide NAKAMURA. Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp> Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip6_fib.h4
-rw-r--r--net/ipv6/inet6_connection_sock.c39
2 files changed, 41 insertions, 2 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index c48ea873f1e0..857821360bb6 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -105,6 +105,10 @@ struct rt6_info
105 struct rt6key rt6i_src; 105 struct rt6key rt6i_src;
106 106
107 u8 rt6i_protocol; 107 u8 rt6i_protocol;
108
109#ifdef CONFIG_XFRM
110 u32 rt6i_flow_cache_genid;
111#endif
108}; 112};
109 113
110static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) 114static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 116f94a49071..25b931709749 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -139,6 +139,41 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
139 139
140EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); 140EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
141 141
142static inline
143void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
144 struct in6_addr *daddr, struct in6_addr *saddr)
145{
146 __ip6_dst_store(sk, dst, daddr, saddr);
147
148#ifdef CONFIG_XFRM
149 if (dst) {
150 struct rt6_info *rt = (struct rt6_info *)dst;
151 rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
152 }
153#endif
154}
155
156static inline
157struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
158{
159 struct dst_entry *dst;
160
161 dst = __sk_dst_check(sk, cookie);
162
163#ifdef CONFIG_XFRM
164 if (dst) {
165 struct rt6_info *rt = (struct rt6_info *)dst;
166 if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
167 sk->sk_dst_cache = NULL;
168 dst_release(dst);
169 dst = NULL;
170 }
171 }
172#endif
173
174 return dst;
175}
176
142int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) 177int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
143{ 178{
144 struct sock *sk = skb->sk; 179 struct sock *sk = skb->sk;
@@ -166,7 +201,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
166 final_p = &final; 201 final_p = &final;
167 } 202 }
168 203
169 dst = __sk_dst_check(sk, np->dst_cookie); 204 dst = __inet6_csk_dst_check(sk, np->dst_cookie);
170 205
171 if (dst == NULL) { 206 if (dst == NULL) {
172 int err = ip6_dst_lookup(sk, &dst, &fl); 207 int err = ip6_dst_lookup(sk, &dst, &fl);
@@ -186,7 +221,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
186 return err; 221 return err;
187 } 222 }
188 223
189 __ip6_dst_store(sk, dst, NULL, NULL); 224 __inet6_csk_dst_store(sk, dst, NULL, NULL);
190 } 225 }
191 226
192 skb->dst = dst_clone(dst); 227 skb->dst = dst_clone(dst);