[IPSEC]: Move common code into xfrm_alloc_spi
This patch moves some common code that conceptually belongs to the xfrm core from af_key/xfrm_user into xfrm_alloc_spi. In particular, the spin lock on the state is now taken inside xfrm_alloc_spi. Previously it also protected the construction of the response PF_KEY/XFRM messages to user-space. This is inconsistent as other identical constructions are not protected by the state lock. This is bad because they in fact should be protected but only in certain spots (so as not to hold the lock for too long which may cause packet drops). The SPI byte order conversion has also been moved. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
75ba28c633
commit
658b219e93
@@ -1275,26 +1275,33 @@ u32 xfrm_get_acqseq(void)
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_get_acqseq);
|
||||
|
||||
void
|
||||
xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
|
||||
int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
|
||||
{
|
||||
unsigned int h;
|
||||
struct xfrm_state *x0;
|
||||
int err = -ENOENT;
|
||||
__be32 minspi = htonl(low);
|
||||
__be32 maxspi = htonl(high);
|
||||
|
||||
spin_lock_bh(&x->lock);
|
||||
if (x->km.state == XFRM_STATE_DEAD)
|
||||
goto unlock;
|
||||
|
||||
err = 0;
|
||||
if (x->id.spi)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
err = -ENOENT;
|
||||
|
||||
if (minspi == maxspi) {
|
||||
x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);
|
||||
if (x0) {
|
||||
xfrm_state_put(x0);
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
x->id.spi = minspi;
|
||||
} else {
|
||||
u32 spi = 0;
|
||||
u32 low = ntohl(minspi);
|
||||
u32 high = ntohl(maxspi);
|
||||
for (h=0; h<high-low+1; h++) {
|
||||
spi = low + net_random()%(high-low+1);
|
||||
x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
|
||||
@@ -1310,7 +1317,14 @@ xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
|
||||
h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
|
||||
hlist_add_head(&x->byspi, xfrm_state_byspi+h);
|
||||
spin_unlock_bh(&xfrm_state_lock);
|
||||
|
||||
err = 0;
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_alloc_spi);
|
||||
|
||||
|
Reference in New Issue
Block a user