aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-09 16:29:52 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:55:01 -0400
commit658b219e9379d75fbdc578b9630b598098471258 (patch)
treefe802c4e1ee6468a9c2558a5e529b2380845a003 /net/xfrm/xfrm_state.c
parent75ba28c633952f7994a7117c98ae6515b58f8d30 (diff)
[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>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0d07f6b92d26..344f0a6abec5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1275,26 +1275,33 @@ u32 xfrm_get_acqseq(void)
1275} 1275}
1276EXPORT_SYMBOL(xfrm_get_acqseq); 1276EXPORT_SYMBOL(xfrm_get_acqseq);
1277 1277
1278void 1278int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
1279xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi)
1280{ 1279{
1281 unsigned int h; 1280 unsigned int h;
1282 struct xfrm_state *x0; 1281 struct xfrm_state *x0;
1282 int err = -ENOENT;
1283 __be32 minspi = htonl(low);
1284 __be32 maxspi = htonl(high);
1285
1286 spin_lock_bh(&x->lock);
1287 if (x->km.state == XFRM_STATE_DEAD)
1288 goto unlock;
1283 1289
1290 err = 0;
1284 if (x->id.spi) 1291 if (x->id.spi)
1285 return; 1292 goto unlock;
1293
1294 err = -ENOENT;
1286 1295
1287 if (minspi == maxspi) { 1296 if (minspi == maxspi) {
1288 x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family); 1297 x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family);
1289 if (x0) { 1298 if (x0) {
1290 xfrm_state_put(x0); 1299 xfrm_state_put(x0);
1291 return; 1300 goto unlock;
1292 } 1301 }
1293 x->id.spi = minspi; 1302 x->id.spi = minspi;
1294 } else { 1303 } else {
1295 u32 spi = 0; 1304 u32 spi = 0;
1296 u32 low = ntohl(minspi);
1297 u32 high = ntohl(maxspi);
1298 for (h=0; h<high-low+1; h++) { 1305 for (h=0; h<high-low+1; h++) {
1299 spi = low + net_random()%(high-low+1); 1306 spi = low + net_random()%(high-low+1);
1300 x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family); 1307 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)
1310 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); 1317 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
1311 hlist_add_head(&x->byspi, xfrm_state_byspi+h); 1318 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
1312 spin_unlock_bh(&xfrm_state_lock); 1319 spin_unlock_bh(&xfrm_state_lock);
1320
1321 err = 0;
1313 } 1322 }
1323
1324unlock:
1325 spin_unlock_bh(&x->lock);
1326
1327 return err;
1314} 1328}
1315EXPORT_SYMBOL(xfrm_alloc_spi); 1329EXPORT_SYMBOL(xfrm_alloc_spi);
1316 1330