| From stable-bounces@linux.kernel.org Mon Dec 19 17:04:42 2005 |
| Date: Mon, 19 Dec 2005 17:03:02 -0800 (PST) |
| Message-Id: <20051219.170302.02916628.davem@davemloft.net> |
| To: stable@kernel.org |
| From: "David S. Miller" <davem@davemloft.net> |
| Subject: [IPSEC]: Perform SA switchover immediately. |
| |
| When we insert a new xfrm_state which potentially |
| subsumes an existing one, make sure all cached |
| bundles are flushed so that the new SA is used |
| immediately. |
| |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Chris Wright <chrisw@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| include/net/xfrm.h | 1 + |
| net/xfrm/xfrm_policy.c | 19 ++++++++++++++----- |
| net/xfrm/xfrm_state.c | 5 +++++ |
| 3 files changed, 20 insertions(+), 5 deletions(-) |
| |
| --- linux-2.6.14.4.orig/include/net/xfrm.h |
| +++ linux-2.6.14.4/include/net/xfrm.h |
| @@ -890,6 +890,7 @@ struct xfrm_state * xfrm_find_acq(u8 mod |
| extern void xfrm_policy_flush(void); |
| extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); |
| extern int xfrm_flush_bundles(void); |
| +extern void xfrm_flush_all_bundles(void); |
| extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); |
| extern void xfrm_init_pmtu(struct dst_entry *dst); |
| |
| --- linux-2.6.14.4.orig/net/xfrm/xfrm_policy.c |
| +++ linux-2.6.14.4/net/xfrm/xfrm_policy.c |
| @@ -1014,13 +1014,12 @@ int __xfrm_route_forward(struct sk_buff |
| } |
| EXPORT_SYMBOL(__xfrm_route_forward); |
| |
| -/* Optimize later using cookies and generation ids. */ |
| - |
| static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) |
| { |
| - if (!stale_bundle(dst)) |
| - return dst; |
| - |
| + /* If it is marked obsolete, which is how we even get here, |
| + * then we have purged it from the policy bundle list and we |
| + * did that for a good reason. |
| + */ |
| return NULL; |
| } |
| |
| @@ -1104,6 +1103,16 @@ int xfrm_flush_bundles(void) |
| return 0; |
| } |
| |
| +static int always_true(struct dst_entry *dst) |
| +{ |
| + return 1; |
| +} |
| + |
| +void xfrm_flush_all_bundles(void) |
| +{ |
| + xfrm_prune_bundles(always_true); |
| +} |
| + |
| void xfrm_init_pmtu(struct dst_entry *dst) |
| { |
| do { |
| --- linux-2.6.14.4.orig/net/xfrm/xfrm_state.c |
| +++ linux-2.6.14.4/net/xfrm/xfrm_state.c |
| @@ -435,6 +435,8 @@ void xfrm_state_insert(struct xfrm_state |
| spin_lock_bh(&xfrm_state_lock); |
| __xfrm_state_insert(x); |
| spin_unlock_bh(&xfrm_state_lock); |
| + |
| + xfrm_flush_all_bundles(); |
| } |
| EXPORT_SYMBOL(xfrm_state_insert); |
| |
| @@ -482,6 +484,9 @@ out: |
| spin_unlock_bh(&xfrm_state_lock); |
| xfrm_state_put_afinfo(afinfo); |
| |
| + if (!err) |
| + xfrm_flush_all_bundles(); |
| + |
| if (x1) { |
| xfrm_state_delete(x1); |
| xfrm_state_put(x1); |