diff options
| author | Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 2002-11-13 16:53:10 -0800 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-11-13 16:53:10 -0800 |
| commit | 217040aed7ca98e22c26529d388a7e332d702532 (patch) | |
| tree | f04d7b40a4b5bdc70a02c192348288ac6b08b222 | |
| parent | b423fed1330fa4844996e771a93435ebb0aa85ec (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.h | 2 | ||||
| -rw-r--r-- | net/ipv4/xfrm_state.c | 9 | ||||
| -rw-r--r-- | net/key/af_key.c | 21 |
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; |
