aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
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