Re: [IPSEC] xfrm_state_replace fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jun 29, 2003 at 01:55:18PM +1000, herbert wrote:
> 
> This patch fixes a number of problems with xfrm_state_replace:
> 
> 1. Only update update lifetime and encap options if the state is valid.
> 2. Disallow updates to states that do not exist.
> 3. Bail if afinfo cannot be found.
> 
> This brings SADB_UPDATE in line with what is required by RFC2367.
> It is also needed by SFS NAT-T support as it needs to update valid
> states when the encap ports move.

Oops, I forgot the patch.
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/net/xfrm/xfrm_state.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_state.c,v
retrieving revision 1.2
diff -u -r1.2 xfrm_state.c
--- kernel-source-2.5/net/xfrm/xfrm_state.c	28 Jun 2003 00:28:01 -0000	1.2
+++ kernel-source-2.5/net/xfrm/xfrm_state.c	29 Jun 2003 03:39:38 -0000
@@ -402,42 +402,64 @@
 	int err;
 
 	afinfo = xfrm_state_get_afinfo(x->props.family);
-	x1 = NULL;
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
 
 	spin_lock_bh(&xfrm_state_lock);
 
-	if (afinfo) {
-		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 && (excl ? x1->id.spi : xfrm_state_kern(x1))) {
+	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;
-			err = -EEXIST;
-			goto out;
 		}
 	}
 
-	__xfrm_state_insert(x);
-	err = 0;
+	if (x1 && (excl ? x1->id.spi : xfrm_state_kern(x1))) {
+		xfrm_state_put(x1);
+		x = NULL;
+		x1 = NULL;
+		err = -EEXIST;
+	} else if (excl || (x1 && x1->km.state == XFRM_STATE_ACQ)) {
+		__xfrm_state_insert(x);
+		x = NULL;
+		err = 0;
+	}
 
-out:
 	spin_unlock_bh(&xfrm_state_lock);
+	xfrm_state_put_afinfo(afinfo);
+
+	err = -ESRCH;
+	if (!x) {
+		if (x1) {
+			xfrm_state_delete(x1);
+			xfrm_state_put(x1);
+		}
+		err = 0;
+	} else if (x1) {
+		err = -EINVAL;
+		spin_lock_bh(&x1->lock);
+
+		if (likely(x1->km.state == XFRM_STATE_VALID)) {
+			memcpy(x1->encap, x->encap, sizeof(*x1->encap));
+			memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
+			x1->km.dying = 0;
+			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);
 
-	if (x1) {
-		xfrm_state_delete(x1);
 		xfrm_state_put(x1);
 	}
 
-	xfrm_state_put_afinfo(afinfo);
 	return err;
 }
 

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux