diff options
-rw-r--r-- | include/net/xfrm.h | 2 | ||||
-rw-r--r-- | net/key/af_key.c | 29 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 26 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 13 |
4 files changed, 37 insertions, 33 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 064a4ca63476..1c116dc03e0e 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -1084,7 +1084,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
1084 | struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); | 1084 | struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); |
1085 | int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); | 1085 | int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); |
1086 | u32 xfrm_get_acqseq(void); | 1086 | u32 xfrm_get_acqseq(void); |
1087 | void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi); | 1087 | extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); |
1088 | struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | 1088 | struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, |
1089 | xfrm_address_t *daddr, xfrm_address_t *saddr, | 1089 | xfrm_address_t *daddr, xfrm_address_t *saddr, |
1090 | int create, unsigned short family); | 1090 | int create, unsigned short family); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index ff5c3d03005e..143d46f6329a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1253,8 +1253,11 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1253 | struct sadb_x_sa2 *sa2; | 1253 | struct sadb_x_sa2 *sa2; |
1254 | struct sadb_address *saddr, *daddr; | 1254 | struct sadb_address *saddr, *daddr; |
1255 | struct sadb_msg *out_hdr; | 1255 | struct sadb_msg *out_hdr; |
1256 | struct sadb_spirange *range; | ||
1256 | struct xfrm_state *x = NULL; | 1257 | struct xfrm_state *x = NULL; |
1257 | int mode; | 1258 | int mode; |
1259 | int err; | ||
1260 | u32 min_spi, max_spi; | ||
1258 | u32 reqid; | 1261 | u32 reqid; |
1259 | u8 proto; | 1262 | u8 proto; |
1260 | unsigned short family; | 1263 | unsigned short family; |
@@ -1309,25 +1312,17 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1309 | if (x == NULL) | 1312 | if (x == NULL) |
1310 | return -ENOENT; | 1313 | return -ENOENT; |
1311 | 1314 | ||
1312 | resp_skb = ERR_PTR(-ENOENT); | 1315 | min_spi = 0x100; |
1313 | 1316 | max_spi = 0x0fffffff; | |
1314 | spin_lock_bh(&x->lock); | ||
1315 | if (x->km.state != XFRM_STATE_DEAD) { | ||
1316 | struct sadb_spirange *range = ext_hdrs[SADB_EXT_SPIRANGE-1]; | ||
1317 | u32 min_spi, max_spi; | ||
1318 | 1317 | ||
1319 | if (range != NULL) { | 1318 | range = ext_hdrs[SADB_EXT_SPIRANGE-1]; |
1320 | min_spi = range->sadb_spirange_min; | 1319 | if (range) { |
1321 | max_spi = range->sadb_spirange_max; | 1320 | min_spi = range->sadb_spirange_min; |
1322 | } else { | 1321 | max_spi = range->sadb_spirange_max; |
1323 | min_spi = 0x100; | ||
1324 | max_spi = 0x0fffffff; | ||
1325 | } | ||
1326 | xfrm_alloc_spi(x, htonl(min_spi), htonl(max_spi)); | ||
1327 | if (x->id.spi) | ||
1328 | resp_skb = pfkey_xfrm_state2msg(x, 0, 3); | ||
1329 | } | 1322 | } |
1330 | spin_unlock_bh(&x->lock); | 1323 | |
1324 | err = xfrm_alloc_spi(x, min_spi, max_spi); | ||
1325 | resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x, 0, 3); | ||
1331 | 1326 | ||
1332 | if (IS_ERR(resp_skb)) { | 1327 | if (IS_ERR(resp_skb)) { |
1333 | xfrm_state_put(x); | 1328 | xfrm_state_put(x); |
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; |