aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
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
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')
-rw-r--r--net/xfrm/xfrm_state.c26
-rw-r--r--net/xfrm/xfrm_user.c13
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}
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
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;