aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/inet6_connection_sock.c
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 /net/ipv6/inet6_connection_sock.c
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>
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r--net/ipv6/inet6_connection_sock.c39
1 files changed, 37 insertions, 2 deletions
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);