diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_state.c | 26 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 13 |
2 files changed, 24 insertions, 15 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 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 8e10e9098a83..52c7fce54641 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -784,16 +784,11 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
784 | if (x == NULL) | 784 | if (x == NULL) |
785 | goto out_noput; | 785 | goto out_noput; |
786 | 786 | ||
787 | resp_skb = ERR_PTR(-ENOENT); | 787 | err = xfrm_alloc_spi(x, p->min, p->max); |
788 | 788 | if (err) | |
789 | spin_lock_bh(&x->lock); | 789 | goto out; |
790 | if (x->km.state != XFRM_STATE_DEAD) { | ||
791 | xfrm_alloc_spi(x, htonl(p->min), htonl(p->max)); | ||
792 | if (x->id.spi) | ||
793 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); | ||
794 | } | ||
795 | spin_unlock_bh(&x->lock); | ||
796 | 790 | ||
791 | resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); | ||
797 | if (IS_ERR(resp_skb)) { | 792 | if (IS_ERR(resp_skb)) { |
798 | err = PTR_ERR(resp_skb); | 793 | err = PTR_ERR(resp_skb); |
799 | goto out; | 794 | goto out; |