Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a47ed4cd8cb0709723392f5b841e9015f765d0a6
Commit:     a47ed4cd8cb0709723392f5b841e9015f765d0a6
Parent:     e773e4faa19c54c2f32ddd16add2919588488bd9
Author:     Noriaki TAKAMIYA <[EMAIL PROTECTED]>
AuthorDate: Thu Sep 6 03:31:25 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 16:48:32 2007 -0700

    [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 <[EMAIL PROTECTED]>
    Signed-off-by: Masahide NAKAMURA <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 include/net/ip6_fib.h            |    4 +++
 net/ipv6/inet6_connection_sock.c |   39 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index c48ea87..8578213 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -105,6 +105,10 @@ struct rt6_info
        struct rt6key                   rt6i_src;
 
        u8                              rt6i_protocol;
+
+#ifdef CONFIG_XFRM
+       u32                             rt6i_flow_cache_genid;
+#endif
 };
 
 static 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 116f94a..25b9317 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)
 
 EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
 
+static inline
+void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
+                          struct in6_addr *daddr, struct in6_addr *saddr)
+{
+       __ip6_dst_store(sk, dst, daddr, saddr);
+
+#ifdef CONFIG_XFRM
+       if (dst) {
+               struct rt6_info *rt = (struct rt6_info  *)dst;
+               rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
+       }
+#endif
+}
+
+static inline
+struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
+{
+       struct dst_entry *dst;
+
+       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->sk_dst_cache = NULL;
+                       dst_release(dst);
+                       dst = NULL;
+               }
+       }
+#endif
+
+       return dst;
+}
+
 int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
 {
        struct sock *sk = skb->sk;
@@ -166,7 +201,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
                final_p = &final;
        }
 
-       dst = __sk_dst_check(sk, np->dst_cookie);
+       dst = __inet6_csk_dst_check(sk, np->dst_cookie);
 
        if (dst == NULL) {
                int err = ip6_dst_lookup(sk, &dst, &fl);
@@ -186,7 +221,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
                        return err;
                }
 
-               __ip6_dst_store(sk, dst, NULL, NULL);
+               __inet6_csk_dst_store(sk, dst, NULL, NULL);
        }
 
        skb->dst = dst_clone(dst);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to