summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>2002-11-13 16:53:10 -0800
committerDavid S. Miller <davem@nuts.ninka.net>2002-11-13 16:53:10 -0800
commit217040aed7ca98e22c26529d388a7e332d702532 (patch)
treef04d7b40a4b5bdc70a02c192348288ac6b08b222
parentb423fed1330fa4844996e771a93435ebb0aa85ec (diff)
[IPSEC]: More pfkey2 semantic fixes.
- xfrm_state.c: never return mature SAs on getspi. - af_key.c: do not forget to delete dummy super-larvals when they are resolved - af_key.c: wow! specially for this case I added gfp argument to xfrm_alloc_policy() and forgot to use it really.
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/ipv4/xfrm_state.c9
-rw-r--r--net/key/af_key.c21
3 files changed, 21 insertions, 11 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 012aa0741b3a..94c922e1ac3c 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -371,7 +371,7 @@ struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
void xfrm_policy_flush(void);
void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr);
+struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
extern void xfrm_policy_flush(void);
extern void xfrm_policy_kill(struct xfrm_policy *);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
diff --git a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c
index 75ef5a816ff5..c2f192076904 100644
--- a/net/ipv4/xfrm_state.c
+++ b/net/ipv4/xfrm_state.c
@@ -386,7 +386,7 @@ xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
}
struct xfrm_state *
-xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
+xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
{
struct xfrm_state *x, *x0;
unsigned h = ntohl(daddr);
@@ -400,10 +400,11 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
mode == x->props.mode &&
proto == x->id.proto &&
saddr == x->props.saddr.xfrm4_addr &&
- reqid == x->props.reqid) {
+ reqid == x->props.reqid &&
+ x->km.state == XFRM_STATE_ACQ) {
if (!x0)
x0 = x;
- if (x->km.state != XFRM_STATE_ACQ)
+ if (x->id.spi)
continue;
x0 = x;
break;
@@ -411,7 +412,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
}
if (x0) {
atomic_inc(&x0->refcnt);
- } else if ((x0 = xfrm_state_alloc()) != NULL) {
+ } else if (create && (x0 = xfrm_state_alloc()) != NULL) {
x0->sel.daddr.xfrm4_addr = daddr;
x0->sel.daddr.xfrm4_mask = ~0;
x0->sel.saddr.xfrm4_addr = saddr;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 3af40a20434e..55876e9ec00c 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -528,8 +528,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
switch (((struct sockaddr *)(addr + 1))->sa_family) {
case AF_INET:
- x = xfrm_state_lookup(
- ((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
+ x = xfrm_state_lookup(((struct sockaddr_in*)(addr + 1))->sin_addr.s_addr,
sa->sadb_sa_spi, proto);
break;
case AF_INET6:
@@ -1043,7 +1042,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
daddr = (struct sockaddr_in*)(addr + 1);
x = xfrm_find_acq(mode, reqid, proto, daddr->sin_addr.s_addr,
- saddr->sin_addr.s_addr);
+ saddr->sin_addr.s_addr, 1);
if (x == NULL)
return -ENOENT;
@@ -1122,7 +1121,17 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
/* XXX there is race condition */
x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
- if (x1 && hdr->sadb_msg_type == SADB_ADD) {
+ if (!x1) {
+ x1 = xfrm_find_acq(x->props.mode, x->props.reqid, x->id.proto,
+ x->id.daddr.xfrm4_addr,
+ x->props.saddr.xfrm4_addr, 0);
+ if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
+ xfrm_state_put(x1);
+ x1 = NULL;
+ }
+ }
+
+ if (x1 && x1->id.spi && hdr->sadb_msg_type == SADB_ADD) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
xfrm_state_put(x1);
@@ -1131,7 +1140,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
xfrm_state_insert(x);
- if (x1 && hdr->sadb_msg_type != SADB_ADD) {
+ if (x1) {
xfrm_state_delete(x1);
xfrm_state_put(x1);
}
@@ -2156,7 +2165,7 @@ static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int
(!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
return NULL;
- xp = xfrm_policy_alloc(GFP_KERNEL);
+ xp = xfrm_policy_alloc(GFP_ATOMIC);
if (xp == NULL) {
*dir = -ENOBUFS;
return NULL;