r1051 - in trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian: . patches

Simon Horman horms@haydn.debian.org
Thu, 12 Aug 2004 19:31:44 -0600


Author: horms
Date: 2004-08-12 19:31:41 -0600 (Thu, 12 Aug 2004)
New Revision: 1051

Modified:
   trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/changelog
   trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/patches/patch-2.4.26-6
Log:
Updated xfrm from 2.6 bitkeeper

Modified: trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/changelog
===================================================================
--- trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/changelog	2004-08-13 00:36:06 UTC (rev 1050)
+++ trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/changelog	2004-08-13 01:31:41 UTC (rev 1051)
@@ -103,8 +103,59 @@
     . include/linux/fs.h
     . kernel/ksyms.c
     . mm/filemap.c
+  * Various updates to xfrm.
+    Brings 2.4.26 backport up to date with the 2.6 tree
+    - Lock in Policy Timer. Herbert Xu
+      . ChangeSet1.1722.10.22 (linux-2.5 tree)
+      . net/xfrm/xfrm_policy.c
+    - Fix memory leak in xfrm_state_find. Herbert Xu
+      . ChangeSet1.1722.15.5 (linux-2.5 tree)
+      . net/xfrm/xfrm_state.c
+    - Fix outdated comment in __xfrm_state_delete. Herbert Xu
+      ChangeSet1.1722.15.6 (linux-2.5 tree)
+      . net/xfrm/xfrm_state.c
+    - Use add_timer() in xfrm_state_find.. Herbert Xu
+      ChangeSet1.1722.15.7 (linux-2.5 tree)
+      . net/xfrm/xfrm_state.c
+    - Fix dependancy issues for CONFIG_IPV6=m. Hideaki Yoshifuji
+      . ChangeSet1.1722.172.4 (linux-2.5 tree)
+      . include/net/xfrm.h
+      . net/xfrm/Makefile
+      . net/xfrm/xfrm_export.c
+      . net/xfrm/xfrm_output.c
+      . net/xfrm/xfrm_state.c
+    - Fix counting in __xfrmN_bundle_create(). Herbert Xu
+      . ChangeSet1.1722.2.41 (linux-2.5 tree)
+      . net/ipv4/xfrm4_policy.c
+      . net/ipv6/xfrm6_policy.c
+      . net/xfrm/xfrm_policy.c
+    - Fix state modifications in xfrm_state_update(). Herbert Xu
+      . ChangeSet1.1722.6.4 (linux-2.5 tree)
+      . net/xfrm/xfrm_state.c
+    - Fix xfrm_tunnel leak. Herbert Xu
+      ChangeSet1.1722.74.3 (linux-2.5 tree)
+      . net/ipv4/ipcomp.c
+      . net/xfrm/xfrm_state.c
+    - Add FLUSHSA and FLUSHPOLICY. Herbert Xu
+      . ChangeSet1.1784.11.13 (linux-2.5 tree)
+      . include/linux/xfrm.h
+      . net/xfrm/xfrm_user.c
+    - Missing unlock in policy timer. Herbert Xu
+      ChangeSet1.1807.2.27 (linux-2.5 tree)
+      . net/xfrm/xfrm_policy.c
+    - Wake up km_waitq once per gc-run instead of once per state.
+      Patrick McHardy, David Miller
+      . ChangeSet1.1807.13.20 (linux-2.5 tree)
+      . net/xfrm/xfrm_state.c 
+    - Add missing unlock in policy timer
+      . ChangeSet1.1807.13.3
+      . net/xfrm/xfrm_policy.c
+    - Fix adding SA through netlink. Masahide Nakamura
+      . ChangeSet1.1807.19.12
+      . algo-detect.patch
+      . linux26/net/xfrm/xfrm_user.c
 
- -- Simon Horman <horms@debian.org>  Thu, 12 Aug 2004 14:49:38 +0900
+ -- Simon Horman <horms@debian.org>  Thu, 12 Aug 2004 15:38:33 +0900
 
 kernel-source-2.4.26 (2.4.26-5) unstable; urgency=high
 

Modified: trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/patches/patch-2.4.26-6
===================================================================
--- trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/patches/patch-2.4.26-6	2004-08-13 00:36:06 UTC (rev 1050)
+++ trunk/kernel-2.4/source/kernel-source-2.4.26-2.4.26/debian/patches/patch-2.4.26-6	2004-08-13 01:31:41 UTC (rev 1051)
@@ -5519,3 +5519,814 @@
  
  	do {
  		unsigned long index, offset;
+#ChangeSet1.1722.10.22
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/22 13:35:20-07:00 herbet@gondor.apana.org.au 
+#   [IPSEC]: Lock policy in policy timer.
+# 
+# net/xfrm/xfrm_policy.c
+#   2004/05/22 13:35:06-07:00 herbet@gondor.apana.org.au +3 -0
+#   [IPSEC]: Lock policy in policy timer.
+# 
+diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+--- a/net/xfrm/xfrm_policy.c	2004-07-28 22:26:39 -07:00
++++ b/net/xfrm/xfrm_policy.c	2004-07-28 22:26:39 -07:00
+@@ -148,6 +148,8 @@
+ 	int warn = 0;
+ 	int dir;
+ 
++	read_lock(&xp->lock);
++
+ 	if (xp->dead)
+ 		goto out;
+ 
+@@ -197,6 +199,7 @@
+ 		xfrm_pol_hold(xp);
+ 
+ out:
++	read_unlock(&xp->lock);
+ 	xfrm_pol_put(xp);
+ 	return;
+ 
+#ChangeSet1.1722.15.5
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/25 11:01:22-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Do not leak entries in xfrm_state_find.
+#   
+#   In xfrm_state_find, the larval state never actually matures with
+#   Openswan so it only ever gets deleted by the timer which means
+#   that the time crash can't happen :)  It becomes a (possible) memory
+#   leak instead.
+# 
+# net/xfrm/xfrm_state.c
+#   2004/05/25 11:01:09-07:00 herbert@gondor.apana.org.au +6 -10
+#   [IPSEC]: Do not leak entries in xfrm_state_find.
+#   
+#   In xfrm_state_find, the larval state never actually matures with
+#   Openswan so it only ever gets deleted by the timer which means
+#   that the time crash can't happen :)  It becomes a (possible) memory
+#   leak instead.
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:51:45 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:51:45 -07:00
+@@ -331,14 +331,8 @@
+ 		}
+ 	}
+ 
+-	if (best) {
+-		xfrm_state_hold(best);
+-		spin_unlock_bh(&xfrm_state_lock);
+-		return best;
+-	}
+-
+-	x = NULL;
+-	if (!error && !acquire_in_progress &&
++	x = best;
++	if (!x && !error && !acquire_in_progress &&
+ 	    ((x = xfrm_state_alloc()) != NULL)) {
+ 		/* Initialize temporary selector matching only
+ 		 * to current session. */
+@@ -363,10 +357,12 @@
+ 			error = 1;
+ 		}
+ 	}
+-	spin_unlock_bh(&xfrm_state_lock);
+-	if (!x)
++	if (x)
++		xfrm_state_hold(x);
++	else
+ 		*err = acquire_in_progress ? -EAGAIN :
+ 			(error ? -ESRCH : -ENOMEM);
++	spin_unlock_bh(&xfrm_state_lock);
+ 	return x;
+ }
+ 
+#ChangeSet1.1722.15.6
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/25 11:02:07-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Fix outdated comment in __xfrm_state_delete.
+# 
+# net/xfrm/xfrm_state.c
+#   2004/05/25 11:01:54-07:00 herbert@gondor.apana.org.au +3 -7
+#   [IPSEC]: Fix outdated comment in __xfrm_state_delete.
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:50:36 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:50:36 -07:00
+@@ -221,13 +221,9 @@
+ 		if (atomic_read(&x->refcnt) > 2)
+ 			xfrm_flush_bundles();
+ 
+-		/* All xfrm_state objects are created by one of two possible
+-		 * paths:
+-		 *
+-		 * 2) xfrm_state_lookup --> xfrm_state_insert
+-		 *
+-		 * The xfrm_state_lookup or xfrm_state_alloc call gives a
+-		 * reference, and that is what we are dropping here.
++		/* All xfrm_state objects are created by xfrm_state_alloc.
++		 * The xfrm_state_alloc call gives a reference, and that
++		 * is what we are dropping here.
+ 		 */
+ 		atomic_dec(&x->refcnt);
+ 	}
+#ChangeSet1.1722.15.7
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/25 11:02:48-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Use add_timer() in xfrm_state_find.
+# 
+# net/xfrm/xfrm_state.c
+#   2004/05/25 11:02:35-07:00 herbert@gondor.apana.org.au +2 -1
+#   [IPSEC]: Use add_timer() in xfrm_state_find.
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:45:32 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:45:32 -07:00
+@@ -345,7 +345,8 @@
+ 			}
+ 			x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+ 			xfrm_state_hold(x);
+-			mod_timer(&x->timer, XFRM_ACQ_EXPIRES*HZ);
++			x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
++			add_timer(&x->timer);
+ 		} else {
+ 			x->km.state = XFRM_STATE_DEAD;
+ 			xfrm_state_put(x);
+#ChangeSet1.1722.172.4
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/06/18 15:21:08+09:00 yoshfuji@linux-ipv6.org 
+#   [XFRM] fix dependency issues for CONFIG_IPV6=m.
+# 
+# include/net/xfrm.h
+#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
+#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
+# 
+# net/xfrm/Makefile
+#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
+#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
+# 
+# net/xfrm/xfrm_export.c
+#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1
+#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
+# 
+# net/xfrm/xfrm_state.c
+#   2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +10 -0
+#   [XFRM] split up xfrm_check_output() into two functions to solve dependency issues.
+# 
+diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
+--- a/include/net/xfrm.h	2004-07-28 21:35:50 -07:00
++++ b/include/net/xfrm.h	2004-07-28 21:35:50 -07:00
+@@ -816,7 +816,7 @@
+ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
+ extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
+ extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
+-extern int xfrm_check_output(struct xfrm_state *x, struct sk_buff *skb, unsigned short family);
++extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
+ extern int xfrm4_rcv(struct sk_buff *skb);
+ extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
+ extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
+diff -Nru a/net/xfrm/Makefile b/net/xfrm/Makefile
+--- a/net/xfrm/Makefile	2004-07-28 21:35:50 -07:00
++++ b/net/xfrm/Makefile	2004-07-28 21:35:50 -07:00
+@@ -2,7 +2,7 @@
+ # Makefile for the XFRM subsystem.
+ #
+ 
+-obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o xfrm_output.o \
++obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o \
+ 	xfrm_export.o
+ obj-$(CONFIG_XFRM_USER) += xfrm_user.o
+ 
+diff -Nru a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
+--- a/net/xfrm/xfrm_export.c	2004-07-28 21:35:50 -07:00
++++ b/net/xfrm/xfrm_export.c	2004-07-28 21:35:50 -07:00
+@@ -18,6 +18,7 @@
+ EXPORT_SYMBOL(xfrm_state_update);
+ EXPORT_SYMBOL(xfrm_state_check_expire);
+ EXPORT_SYMBOL(xfrm_state_check_space);
++EXPORT_SYMBOL(xfrm_state_check);
+ EXPORT_SYMBOL(xfrm_state_lookup);
+ EXPORT_SYMBOL(xfrm_state_register_afinfo);
+ EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
+@@ -27,7 +28,6 @@
+ EXPORT_SYMBOL(xfrm_replay_check);
+ EXPORT_SYMBOL(xfrm_replay_advance);
+ EXPORT_SYMBOL(xfrm_check_selectors);
+-EXPORT_SYMBOL(xfrm_check_output);
+ EXPORT_SYMBOL(__secpath_destroy);
+ EXPORT_SYMBOL(secpath_dup);
+ EXPORT_SYMBOL(xfrm_get_acqseq);
+diff -Nru a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
+--- a/net/xfrm/xfrm_output.c	2004-07-28 21:35:50 -07:00
++++ /dev/null	Wed Dec 31 16:00:00 196900
+@@ -1,46 +0,0 @@
+-/* 
+- * generic xfrm output routines
+- *
+- * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option) 
+- * any later version.
+- */
+-#include <linux/config.h>
+-#include <linux/kernel.h>
+-#include <linux/skbuff.h>
+-#include <net/xfrm.h>
+-
+-int xfrm_check_output(struct xfrm_state *x,
+-                      struct sk_buff *skb, unsigned short family)
+-{
+-	int err;
+-	
+-	err = xfrm_state_check_expire(x);
+-	if (err)
+-		goto out;
+-		
+-	if (x->props.mode) {
+-		switch (family) {
+-		case AF_INET:
+-			err = xfrm4_tunnel_check_size(skb);
+-			break;
+-			
+-		case AF_INET6:
+-			err = xfrm6_tunnel_check_size(skb);
+-			break;
+-			
+-		default:
+-			err = -EINVAL;
+-		}
+-		
+-		if (err)
+-			goto out;
+-	}
+-
+-	err = xfrm_state_check_space(x, skb);
+-out:
+-	return err;
+-}
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:35:50 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:35:50 -07:00
+@@ -531,6 +531,16 @@
+ 	return 0;
+ }
+ 
++int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
++{
++	int err = xfrm_state_check_expire(x);
++	if (err < 0)
++		goto err;
++	err = xfrm_state_check_space(x, skb);
++err:
++	return err;
++}
++
+ struct xfrm_state *
+ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
+ 		  unsigned short family)
+#ChangeSet1.1722.2.41
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/29 12:46:04-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Fix ref counting in __xfrmN_bundle_create().
+# 
+# net/ipv4/xfrm4_policy.c
+#   2004/05/29 12:45:43-07:00 herbert@gondor.apana.org.au +2 -1
+#   [IPSEC]: Fix ref counting in __xfrmN_bundle_create().
+# 
+# net/ipv6/xfrm6_policy.c
+#   2004/05/29 12:45:43-07:00 herbert@gondor.apana.org.au +2 -1
+#   [IPSEC]: Fix ref counting in __xfrmN_bundle_create().
+# 
+# net/xfrm/xfrm_policy.c
+#   2004/05/29 12:45:43-07:00 herbert@gondor.apana.org.au +2 -0
+#   [IPSEC]: Fix ref counting in __xfrmN_bundle_create().
+# 
+diff -Nru a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+--- a/net/ipv4/xfrm4_policy.c	2004-07-28 23:04:01 -07:00
++++ b/net/ipv4/xfrm4_policy.c	2004-07-28 23:04:01 -07:00
+@@ -90,7 +90,6 @@
+ 			goto error;
+ 		}
+ 
+-		dst1->xfrm = xfrm[i];
+ 		if (!dst)
+ 			dst = dst1;
+ 		else {
+@@ -120,10 +119,12 @@
+ 		dst_hold(&rt->u.dst);
+ 	}
+ 	dst_prev->child = &rt->u.dst;
++	i = 0;
+ 	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+ 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+ 		x->u.rt.fl = *fl;
+ 
++		dst_prev->xfrm = xfrm[i++];
+ 		dst_prev->dev = rt->u.dst.dev;
+ 		if (rt->u.dst.dev)
+ 			dev_hold(rt->u.dst.dev);
+diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+--- a/net/ipv6/xfrm6_policy.c	2004-07-28 23:04:01 -07:00
++++ b/net/ipv6/xfrm6_policy.c	2004-07-28 23:04:01 -07:00
+@@ -107,7 +107,6 @@
+ 			goto error;
+ 		}
+ 
+-		dst1->xfrm = xfrm[i];
+ 		if (!dst)
+ 			dst = dst1;
+ 		else {
+@@ -139,9 +138,11 @@
+ 		dst_hold(&rt->u.dst);
+ 	}
+ 	dst_prev->child = &rt->u.dst;
++	i = 0;
+ 	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+ 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+ 
++		dst_prev->xfrm = xfrm[i++];
+ 		dst_prev->dev = rt->u.dst.dev;
+ 		if (rt->u.dst.dev)
+ 			dev_hold(rt->u.dst.dev);
+diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+--- a/net/xfrm/xfrm_policy.c	2004-07-28 23:04:01 -07:00
++++ b/net/xfrm/xfrm_policy.c	2004-07-28 23:04:01 -07:00
+@@ -1017,6 +1017,8 @@
+ 
+ static void xfrm_dst_destroy(struct dst_entry *dst)
+ {
++	if (!dst->xfrm)
++		return;
+ 	xfrm_state_put(dst->xfrm);
+ 	dst->xfrm = NULL;
+ }
+#ChangeSet1.1722.6.4
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/05/21 14:43:13-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Fix state modifications in xfrm_state_update().
+#   
+#   doing a mod_timer on a live state without holding a lock or for that
+#   matter not even checking whether the state is dead is definitely a bad
+#   idea
+# 
+# net/xfrm/xfrm_state.c
+#   2004/05/21 14:42:59-07:00 herbert@gondor.apana.org.au +6 -5
+#   [IPSEC]: Fix state modifications in xfrm_state_update().
+#   
+#   doing a mod_timer on a live state without holding a lock or for that
+#   matter not even checking whether the state is dead is definitely a bad
+#   idea
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:52:49 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:52:49 -07:00
+@@ -489,14 +489,15 @@
+ 			memcpy(x1->encap, x->encap, sizeof(*x1->encap));
+ 		memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
+ 		x1->km.dying = 0;
++
++		if (!mod_timer(&x1->timer, jiffies + HZ))
++			xfrm_state_hold(x1);
++		if (x1->curlft.use_time)
++			xfrm_state_check_expire(x1);
++
+ 		err = 0;
+ 	}
+ 	spin_unlock_bh(&x1->lock);
+-
+-	if (!mod_timer(&x1->timer, jiffies + HZ))
+-		xfrm_state_hold(x1);
+-	if (x1->curlft.use_time)
+-		xfrm_state_check_expire(x1);
+ 
+ 	xfrm_state_put(x1);
+ 
+#ChangeSet1.1722.74.3
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/06/01 12:35:39-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Fix xfrm_tunnel leak.
+#   
+#   Turns out that the IPIP tunnel used by IPCOMP states are only freed
+#   if the IPCOMP state is deleted by xfrm_state_delete.
+#   
+#   This is not the case for all states.  For example, an immature IPCOMP
+#   state that dies in add_sa will not go through xfrm_state_delete.
+#   
+#   The following patch moves the delete_tunnel call into IPCOMP's
+#   destructor.  I think it makes more sense there as IPCOMP is the
+#   only user of the tunnel anyway.
+# 
+# net/ipv4/ipcomp.c
+#   2004/06/01 12:35:15-07:00 herbert@gondor.apana.org.au +1 -0
+#   [IPSEC]: Fix xfrm_tunnel leak.
+#   
+#   Turns out that the IPIP tunnel used by IPCOMP states are only freed
+#   if the IPCOMP state is deleted by xfrm_state_delete.
+#   
+#   This is not the case for all states.  For example, an immature IPCOMP
+#   state that dies in add_sa will not go through xfrm_state_delete.
+#   
+#   The following patch moves the delete_tunnel call into IPCOMP's
+#   destructor.  I think it makes more sense there as IPCOMP is the
+#   only user of the tunnel anyway.
+# 
+# net/xfrm/xfrm_state.c
+#   2004/06/01 12:35:15-07:00 herbert@gondor.apana.org.au +0 -1
+#   [IPSEC]: Fix xfrm_tunnel leak.
+#   
+#   Turns out that the IPIP tunnel used by IPCOMP states are only freed
+#   if the IPCOMP state is deleted by xfrm_state_delete.
+#   
+#   This is not the case for all states.  For example, an immature IPCOMP
+#   state that dies in add_sa will not go through xfrm_state_delete.
+#   
+#   The following patch moves the delete_tunnel call into IPCOMP's
+#   destructor.  I think it makes more sense there as IPCOMP is the
+#   only user of the tunnel anyway.
+# 
+diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
+--- a/net/ipv4/ipcomp.c	2004-07-28 21:37:23 -07:00
++++ b/net/ipv4/ipcomp.c	2004-07-28 21:37:23 -07:00
+@@ -339,6 +339,7 @@
+ 	struct ipcomp_data *ipcd = x->data;
+ 	if (!ipcd)
+ 		return;
++	xfrm_state_delete_tunnel(x);
+ 	ipcomp_free_data(ipcd);
+ 	kfree(ipcd);
+ }
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-07-28 21:37:23 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-07-28 21:37:23 -07:00
+@@ -231,7 +231,6 @@
+ 
+ void xfrm_state_delete(struct xfrm_state *x)
+ {
+-	xfrm_state_delete_tunnel(x);
+ 	spin_lock_bh(&x->lock);
+ 	__xfrm_state_delete(x);
+ 	spin_unlock_bh(&x->lock);
+#ChangeSet1.1784.11.13
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/09 16:51:35-07:00 herbert@gondor.apana.org.au 
+#   [XFRM]: Add FLUSHSA and FLUSHPOLICY.
+#   
+#   This patch adds FLUSHSA and FLUSHPOLICY to xfrm_user which are
+#   analagous to SADB_FLUSH and SADB_X_SPDFLUSH in af_key.
+#   
+#   This is useful in KMs on startup/shutdown so that the system is
+#   reset to a known state.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# include/linux/xfrm.h
+#   2004/07/09 16:51:20-07:00 herbert@gondor.apana.org.au +9 -0
+#   [XFRM]: Add FLUSHSA and FLUSHPOLICY.
+#   
+#   This patch adds FLUSHSA and FLUSHPOLICY to xfrm_user which are
+#   analagous to SADB_FLUSH and SADB_X_SPDFLUSH in af_key.
+#   
+#   This is useful in KMs on startup/shutdown so that the system is
+#   reset to a known state.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_user.c
+#   2004/07/09 16:51:20-07:00 herbert@gondor.apana.org.au +20 -0
+#   [XFRM]: Add FLUSHSA and FLUSHPOLICY.
+#   
+#   This patch adds FLUSHSA and FLUSHPOLICY to xfrm_user which are
+#   analagous to SADB_FLUSH and SADB_X_SPDFLUSH in af_key.
+#   
+#   This is useful in KMs on startup/shutdown so that the system is
+#   reset to a known state.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# *** xfrm.h patch updated for 2.4 backport ***
+# *** Joshua Kwan & Horms 2004/08/12        ***
+--- a/include/linux/xfrm.h.orig	2004-08-12 16:32:18.000000000 +0900
++++ b/include/linux/xfrm.h	2004-08-12 16:37:17.000000000 +0900
+@@ -122,7 +122,10 @@
+ 
+ #define XFRM_MSG_POLEXPIRE	(XFRM_MSG_BASE + 11)
+ 
+-#define XFRM_MSG_MAX		(XFRM_MSG_POLEXPIRE+1)
++#define XFRM_MSG_FLUSHSA	(XFRM_MSG_BASE + 12)
++#define XFRM_MSG_FLUSHPOLICY	(XFRM_MSG_BASE + 13)
++
++#define XFRM_MSG_MAX		(XFRM_MSG_FLUSHPOLICY+1)
+ 
+ struct xfrm_user_tmpl {
+ 	struct xfrm_id		id;
+@@ -227,6 +230,10 @@
+ 	__u8				hard;
+ };
+ 
++struct xfrm_usersa_flush {
++	__u8				proto;
++};
++
+ #define XFRMGRP_ACQUIRE		1
+ #define XFRMGRP_EXPIRE		2
+ 
+diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+--- a/net/xfrm/xfrm_user.c	2004-07-28 22:44:21 -07:00
++++ b/net/xfrm/xfrm_user.c	2004-07-28 22:44:21 -07:00
+@@ -814,6 +814,20 @@
+ 	return err;
+ }
+ 
++static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
++{
++	struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
++
++	xfrm_state_flush(p->proto);
++	return 0;
++}
++
++static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
++{
++	xfrm_policy_flush();
++	return 0;
++}
++
+ static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
+ 	NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)),	/* NEW SA */
+ 	NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),	/* DEL SA */
+@@ -826,6 +840,9 @@
+ 	NLMSG_LENGTH(sizeof(struct xfrm_user_expire)),	/* EXPIRE */
+ 	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)),/* UPD POLICY */
+ 	NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)),	/* UPD SA */
++	NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
++	NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)),	/* FLUSH SA */
++	NLMSG_LENGTH(0),				/* FLUSH POLICY */
+ };
+ 
+ static struct xfrm_link {
+@@ -849,6 +866,9 @@
+ 	{},
+ 	{	.doit	=	xfrm_add_policy 	},
+ 	{	.doit	=	xfrm_add_sa, 		},
++	{},
++	{	.doit	=	xfrm_flush_sa		},
++	{	.doit	=	xfrm_flush_policy	},
+ };
+ 
+ static int xfrm_done(struct netlink_callback *cb)
+#ChangeSet1.1807.13.20
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/25 16:54:54-07:00 kaber@trash.net 
+#   [XFRM]: Wake up km_waitq once per gc-run instead of once per state.
+#   
+#   Signed-off-by: Patrick McHardy <kaber@trash.net>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_state.c
+#   2004/07/25 16:54:39-07:00 kaber@trash.net +1 -1
+#   [XFRM]: Wake up km_waitq once per gc-run instead of once per state.
+#   
+#   Signed-off-by: Patrick McHardy <kaber@trash.net>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-08-11 23:21:30 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-08-11 23:21:30 -07:00
+@@ -65,7 +65,6 @@
+ 		xfrm_put_type(x->type);
+ 	}
+ 	kfree(x);
+-	wake_up(&km_waitq);
+ }
+ 
+ static void xfrm_state_gc_task(void *data)
+@@ -82,6 +81,7 @@
+ 		x = list_entry(entry, struct xfrm_state, bydst);
+ 		xfrm_state_gc_destroy(x);
+ 	}
++	wake_up(&km_waitq);
+ }
+ 
+ static inline unsigned long make_jiffies(long secs)
+#ChangeSet1.1807.13.3
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/23 13:23:48-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Missing unlock in policy timer.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_policy.c
+#   2004/07/23 13:23:33-07:00 herbert@gondor.apana.org.au +1 -0
+#   [IPSEC]: Missing unlock in policy timer.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+--- a/net/xfrm/xfrm_policy.c	2004-08-11 23:25:52 -07:00
++++ b/net/xfrm/xfrm_policy.c	2004-08-11 23:25:52 -07:00
+@@ -204,6 +204,7 @@
+ 	return;
+ 
+ expired:
++	read_unlock(&xp->lock);
+ 	km_policy_expired(xp, dir, 1);
+ 	xfrm_policy_delete(xp, dir);
+ 	xfrm_pol_put(xp);
+#ChangeSet1.1807.19.12
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/28 18:56:51-07:00 nakam@linux-ipv6.org 
+#   [IPSEC]: xfrm_user code forgets to call xfrm_probe_algs()
+#   
+#   Signed-off-by: Masahide Nakmura <nakam@linux-ipv6.org>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_user.c
+#   2004/07/28 18:56:37-07:00 nakam@linux-ipv6.org +2 -0
+#   [IPSEC]: xfrm_user code forgets to call xfrm_probe_algs()
+#   
+#   Signed-off-by: Masahide Nakmura <nakam@linux-ipv6.org>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+--- a/net/xfrm/xfrm_user.c	2004-08-11 23:01:30 -07:00
++++ b/net/xfrm/xfrm_user.c	2004-08-11 23:01:30 -07:00
+@@ -267,6 +267,8 @@
+ 	if (err)
+ 		return err;
+ 
++	xfrm_probe_algs();
++
+ 	x = xfrm_state_construct(p, (struct rtattr **) xfrma, &err);
+ 	if (!x)
+ 		return err;
+#ChangeSet1.1836
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/31 23:30:00-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: Remove redundant check in xfrm_state_add()
+#   
+#   This is the patch referred to in the netlink_get_spi thread.
+#   
+#   I was actually wrong about the reason for this patch though.  Firstly
+#   it's the SPI check that is redundant and not the find_acq() call.
+#   And it's redundant because of the find_acq() patch, not because
+#   of the fact that this is in xfrm_state_add().
+#   
+#   Now that find_acq() only returns SAs with SPIs, we don't need to
+#   check this in xfrm_state_add() anymore.
+#   
+#   We do still need the call though to clean up leftover larval states.
+#   
+#   Another side-effect of the change is that we can move the existence
+#   check above find_acq() since find_acq() will never return any SAs
+#   matching the SPI we're trying to add (It doesn't need to because if
+#   an SA with a matching SPI existed, it would've been returned by
+#   state_lookup() already).
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_state.c
+#   2004/07/31 23:29:46-07:00 herbert@gondor.apana.org.au +5 -11
+#   [IPSEC]: Remove redundant check in xfrm_state_add()
+#   
+#   This is the patch referred to in the netlink_get_spi thread.
+#   
+#   I was actually wrong about the reason for this patch though.  Firstly
+#   it's the SPI check that is redundant and not the find_acq() call.
+#   And it's redundant because of the find_acq() patch, not because
+#   of the fact that this is in xfrm_state_add().
+#   
+#   Now that find_acq() only returns SAs with SPIs, we don't need to
+#   check this in xfrm_state_add() anymore.
+#   
+#   We do still need the call though to clean up leftover larval states.
+#   
+#   Another side-effect of the change is that we can move the existence
+#   check above find_acq() since find_acq() will never return any SAs
+#   matching the SPI we're trying to add (It doesn't need to because if
+#   an SA with a matching SPI existed, it would've been returned by
+#   state_lookup() already).
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-08-11 23:14:58 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-08-11 23:14:58 -07:00
+@@ -400,22 +400,16 @@
+ 	spin_lock_bh(&xfrm_state_lock);
+ 
+ 	x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
+-	if (!x1) {
+-		x1 = afinfo->find_acq(
+-			x->props.mode, x->props.reqid, x->id.proto,
+-			&x->id.daddr, &x->props.saddr, 0);
+-		if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
+-			xfrm_state_put(x1);
+-			x1 = NULL;
+-		}
+-	}
+-
+-	if (x1 && x1->id.spi) {
++	if (x1) {
+ 		xfrm_state_put(x1);
+ 		x1 = NULL;
+ 		err = -EEXIST;
+ 		goto out;
+ 	}
++
++	x1 = afinfo->find_acq(
++		x->props.mode, x->props.reqid, x->id.proto,
++		&x->id.daddr, &x->props.saddr, 0);
+ 
+ 	__xfrm_state_insert(x);
+ 	err = 0;
+#ChangeSet1.1837
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/07/31 23:33:16-07:00 herbert@gondor.apana.org.au 
+#   [IPSEC]: xfrm_alloc_spi always succeeds on non-trivial range
+#   
+#   xfrm_alloc_spi will always succeed if minspi < maxspi, even if
+#   minspi + 1 == maxspi.  If the range is already occupied this
+#   will obviously lead to breakage.
+#   
+#   Of course this is very unlikely to occur in reality due to the
+#   size of the range.  Although with IPCOMP it might actually happen
+#   on a very large server.
+#   
+#   The fix is obivous.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+# net/xfrm/xfrm_state.c
+#   2004/07/31 23:33:00-07:00 herbert@gondor.apana.org.au +3 -2
+#   [IPSEC]: xfrm_alloc_spi always succeeds on non-trivial range
+#   
+#   xfrm_alloc_spi will always succeed if minspi < maxspi, even if
+#   minspi + 1 == maxspi.  If the range is already occupied this
+#   will obviously lead to breakage.
+#   
+#   Of course this is very unlikely to occur in reality due to the
+#   size of the range.  Although with IPCOMP it might actually happen
+#   on a very large server.
+#   
+#   The fix is obivous.
+#   
+#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+#   Signed-off-by: David S. Miller <davem@redhat.com>
+# 
+diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c	2004-08-11 23:21:50 -07:00
++++ b/net/xfrm/xfrm_state.c	2004-08-11 23:21:50 -07:00
+@@ -624,11 +624,12 @@
+ 		for (h=0; h<maxspi-minspi+1; h++) {
+ 			spi = minspi + net_random()%(maxspi-minspi+1);
+ 			x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
+-			if (x0 == NULL)
++			if (x0 == NULL) {
++				x->id.spi = htonl(spi);
+ 				break;
++			}
+ 			xfrm_state_put(x0);
+ 		}
+-		x->id.spi = htonl(spi);
+ 	}
+ 	if (x->id.spi) {
+ 		spin_lock_bh(&xfrm_state_lock);