diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 26 |
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 | } |
1276 | EXPORT_SYMBOL(xfrm_get_acqseq); | 1276 | EXPORT_SYMBOL(xfrm_get_acqseq); |
1277 | 1277 | ||
1278 | void | 1278 | int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) |
1279 | xfrm_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 | |||
1324 | unlock: | ||
1325 | spin_unlock_bh(&x->lock); | ||
1326 | |||
1327 | return err; | ||
1314 | } | 1328 | } |
1315 | EXPORT_SYMBOL(xfrm_alloc_spi); | 1329 | EXPORT_SYMBOL(xfrm_alloc_spi); |
1316 | 1330 | ||