aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h12
-rw-r--r--net/ipv4/ah4.c5
-rw-r--r--net/ipv6/ah6.c5
-rw-r--r--net/ipv6/esp6.c5
-rw-r--r--net/key/af_key.c8
-rw-r--r--net/xfrm/xfrm_device.c2
-rw-r--r--net/xfrm/xfrm_policy.c13
-rw-r--r--net/xfrm/xfrm_state.c35
-rw-r--r--net/xfrm/xfrm_user.c37
9 files changed, 74 insertions, 48 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 7e7e2b0d2915..01f5bc144ee5 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -631,7 +631,8 @@ struct xfrm_mgr {
631 u8 dir, u8 type, 631 u8 dir, u8 type,
632 const struct xfrm_migrate *m, 632 const struct xfrm_migrate *m,
633 int num_bundles, 633 int num_bundles,
634 const struct xfrm_kmaddress *k); 634 const struct xfrm_kmaddress *k,
635 const struct xfrm_encap_tmpl *encap);
635 bool (*is_alive)(const struct km_event *c); 636 bool (*is_alive)(const struct km_event *c);
636}; 637};
637 638
@@ -1675,13 +1676,16 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
1675#ifdef CONFIG_XFRM_MIGRATE 1676#ifdef CONFIG_XFRM_MIGRATE
1676int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 1677int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1677 const struct xfrm_migrate *m, int num_bundles, 1678 const struct xfrm_migrate *m, int num_bundles,
1678 const struct xfrm_kmaddress *k); 1679 const struct xfrm_kmaddress *k,
1680 const struct xfrm_encap_tmpl *encap);
1679struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net); 1681struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
1680struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, 1682struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
1681 struct xfrm_migrate *m); 1683 struct xfrm_migrate *m,
1684 struct xfrm_encap_tmpl *encap);
1682int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 1685int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1683 struct xfrm_migrate *m, int num_bundles, 1686 struct xfrm_migrate *m, int num_bundles,
1684 struct xfrm_kmaddress *k, struct net *net); 1687 struct xfrm_kmaddress *k, struct net *net,
1688 struct xfrm_encap_tmpl *encap);
1685#endif 1689#endif
1686 1690
1687int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); 1691int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e8f862358518..37db44f60718 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -1,5 +1,6 @@
1#define pr_fmt(fmt) "IPsec: " fmt 1#define pr_fmt(fmt) "IPsec: " fmt
2 2
3#include <crypto/algapi.h>
3#include <crypto/hash.h> 4#include <crypto/hash.h>
4#include <linux/err.h> 5#include <linux/err.h>
5#include <linux/module.h> 6#include <linux/module.h>
@@ -279,7 +280,7 @@ static void ah_input_done(struct crypto_async_request *base, int err)
279 auth_data = ah_tmp_auth(work_iph, ihl); 280 auth_data = ah_tmp_auth(work_iph, ihl);
280 icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); 281 icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
281 282
282 err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0; 283 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
283 if (err) 284 if (err)
284 goto out; 285 goto out;
285 286
@@ -417,7 +418,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
417 goto out_free; 418 goto out_free;
418 } 419 }
419 420
420 err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0; 421 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
421 if (err) 422 if (err)
422 goto out_free; 423 goto out_free;
423 424
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 755f38271dd5..7802b72196f3 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -25,6 +25,7 @@
25 25
26#define pr_fmt(fmt) "IPv6: " fmt 26#define pr_fmt(fmt) "IPv6: " fmt
27 27
28#include <crypto/algapi.h>
28#include <crypto/hash.h> 29#include <crypto/hash.h>
29#include <linux/module.h> 30#include <linux/module.h>
30#include <linux/slab.h> 31#include <linux/slab.h>
@@ -483,7 +484,7 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
483 auth_data = ah_tmp_auth(work_iph, hdr_len); 484 auth_data = ah_tmp_auth(work_iph, hdr_len);
484 icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); 485 icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
485 486
486 err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 487 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
487 if (err) 488 if (err)
488 goto out; 489 goto out;
489 490
@@ -631,7 +632,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
631 goto out_free; 632 goto out_free;
632 } 633 }
633 634
634 err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 635 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
635 if (err) 636 if (err)
636 goto out_free; 637 goto out_free;
637 638
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index d8b40ff4b2e6..71faffdd55d9 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -118,7 +118,6 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
118 118
119static void esp_ssg_unref(struct xfrm_state *x, void *tmp) 119static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
120{ 120{
121 __be32 *seqhi;
122 struct crypto_aead *aead = x->data; 121 struct crypto_aead *aead = x->data;
123 int seqhilen = 0; 122 int seqhilen = 0;
124 u8 *iv; 123 u8 *iv;
@@ -128,7 +127,6 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
128 if (x->props.flags & XFRM_STATE_ESN) 127 if (x->props.flags & XFRM_STATE_ESN)
129 seqhilen += sizeof(__be32); 128 seqhilen += sizeof(__be32);
130 129
131 seqhi = esp_tmp_seqhi(tmp);
132 iv = esp_tmp_iv(aead, tmp, seqhilen); 130 iv = esp_tmp_iv(aead, tmp, seqhilen);
133 req = esp_tmp_req(aead, iv); 131 req = esp_tmp_req(aead, iv);
134 132
@@ -224,12 +222,9 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
224 u8 *vaddr; 222 u8 *vaddr;
225 int nfrags; 223 int nfrags;
226 struct page *page; 224 struct page *page;
227 struct ip_esp_hdr *esph;
228 struct sk_buff *trailer; 225 struct sk_buff *trailer;
229 int tailen = esp->tailen; 226 int tailen = esp->tailen;
230 227
231 esph = ip_esp_hdr(skb);
232
233 if (!skb_cloned(skb)) { 228 if (!skb_cloned(skb)) {
234 if (tailen <= skb_availroom(skb)) { 229 if (tailen <= skb_availroom(skb)) {
235 nfrags = 1; 230 nfrags = 1;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index daa4e90dc4db..ce9b8565d825 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2589,7 +2589,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
2589 } 2589 }
2590 2590
2591 return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, 2591 return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
2592 kma ? &k : NULL, net); 2592 kma ? &k : NULL, net, NULL);
2593 2593
2594 out: 2594 out:
2595 return err; 2595 return err;
@@ -3488,7 +3488,8 @@ static int set_ipsecrequest(struct sk_buff *skb,
3488#ifdef CONFIG_NET_KEY_MIGRATE 3488#ifdef CONFIG_NET_KEY_MIGRATE
3489static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 3489static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3490 const struct xfrm_migrate *m, int num_bundles, 3490 const struct xfrm_migrate *m, int num_bundles,
3491 const struct xfrm_kmaddress *k) 3491 const struct xfrm_kmaddress *k,
3492 const struct xfrm_encap_tmpl *encap)
3492{ 3493{
3493 int i; 3494 int i;
3494 int sasize_sel; 3495 int sasize_sel;
@@ -3598,7 +3599,8 @@ err:
3598#else 3599#else
3599static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 3600static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3600 const struct xfrm_migrate *m, int num_bundles, 3601 const struct xfrm_migrate *m, int num_bundles,
3601 const struct xfrm_kmaddress *k) 3602 const struct xfrm_kmaddress *k,
3603 const struct xfrm_encap_tmpl *encap)
3602{ 3604{
3603 return -ENOPROTOOPT; 3605 return -ENOPROTOOPT;
3604} 3606}
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 574e6f32f94f..6d4a60d1bf19 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -138,7 +138,7 @@ ok:
138} 138}
139EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok); 139EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);
140 140
141int xfrm_dev_register(struct net_device *dev) 141static int xfrm_dev_register(struct net_device *dev)
142{ 142{
143 if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops) 143 if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops)
144 return NOTIFY_BAD; 144 return NOTIFY_BAD;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index af8e38f47b5b..a3dc7ab0b7ed 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3279,11 +3279,6 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
3279 return -EINVAL; 3279 return -EINVAL;
3280 3280
3281 for (i = 0; i < num_migrate; i++) { 3281 for (i = 0; i < num_migrate; i++) {
3282 if (xfrm_addr_equal(&m[i].old_daddr, &m[i].new_daddr,
3283 m[i].old_family) &&
3284 xfrm_addr_equal(&m[i].old_saddr, &m[i].new_saddr,
3285 m[i].old_family))
3286 return -EINVAL;
3287 if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) || 3282 if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
3288 xfrm_addr_any(&m[i].new_saddr, m[i].new_family)) 3283 xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
3289 return -EINVAL; 3284 return -EINVAL;
@@ -3307,7 +3302,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
3307 3302
3308int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 3303int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3309 struct xfrm_migrate *m, int num_migrate, 3304 struct xfrm_migrate *m, int num_migrate,
3310 struct xfrm_kmaddress *k, struct net *net) 3305 struct xfrm_kmaddress *k, struct net *net,
3306 struct xfrm_encap_tmpl *encap)
3311{ 3307{
3312 int i, err, nx_cur = 0, nx_new = 0; 3308 int i, err, nx_cur = 0, nx_new = 0;
3313 struct xfrm_policy *pol = NULL; 3309 struct xfrm_policy *pol = NULL;
@@ -3330,7 +3326,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3330 if ((x = xfrm_migrate_state_find(mp, net))) { 3326 if ((x = xfrm_migrate_state_find(mp, net))) {
3331 x_cur[nx_cur] = x; 3327 x_cur[nx_cur] = x;
3332 nx_cur++; 3328 nx_cur++;
3333 if ((xc = xfrm_state_migrate(x, mp))) { 3329 xc = xfrm_state_migrate(x, mp, encap);
3330 if (xc) {
3334 x_new[nx_new] = xc; 3331 x_new[nx_new] = xc;
3335 nx_new++; 3332 nx_new++;
3336 } else { 3333 } else {
@@ -3351,7 +3348,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3351 } 3348 }
3352 3349
3353 /* Stage 5 - announce */ 3350 /* Stage 5 - announce */
3354 km_migrate(sel, dir, type, m, num_migrate, k); 3351 km_migrate(sel, dir, type, m, num_migrate, k, encap);
3355 3352
3356 xfrm_pol_put(pol); 3353 xfrm_pol_put(pol);
3357 3354
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2e291bc5f1fc..4a28f669c915 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1309,7 +1309,8 @@ out:
1309EXPORT_SYMBOL(xfrm_state_add); 1309EXPORT_SYMBOL(xfrm_state_add);
1310 1310
1311#ifdef CONFIG_XFRM_MIGRATE 1311#ifdef CONFIG_XFRM_MIGRATE
1312static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) 1312static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
1313 struct xfrm_encap_tmpl *encap)
1313{ 1314{
1314 struct net *net = xs_net(orig); 1315 struct net *net = xs_net(orig);
1315 struct xfrm_state *x = xfrm_state_alloc(net); 1316 struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
1351 } 1352 }
1352 x->props.calgo = orig->props.calgo; 1353 x->props.calgo = orig->props.calgo;
1353 1354
1354 if (orig->encap) { 1355 if (encap || orig->encap) {
1355 x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL); 1356 if (encap)
1357 x->encap = kmemdup(encap, sizeof(*x->encap),
1358 GFP_KERNEL);
1359 else
1360 x->encap = kmemdup(orig->encap, sizeof(*x->encap),
1361 GFP_KERNEL);
1362
1356 if (!x->encap) 1363 if (!x->encap)
1357 goto error; 1364 goto error;
1358 } 1365 }
@@ -1442,11 +1449,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
1442EXPORT_SYMBOL(xfrm_migrate_state_find); 1449EXPORT_SYMBOL(xfrm_migrate_state_find);
1443 1450
1444struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, 1451struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
1445 struct xfrm_migrate *m) 1452 struct xfrm_migrate *m,
1453 struct xfrm_encap_tmpl *encap)
1446{ 1454{
1447 struct xfrm_state *xc; 1455 struct xfrm_state *xc;
1448 1456
1449 xc = xfrm_state_clone(x); 1457 xc = xfrm_state_clone(x, encap);
1450 if (!xc) 1458 if (!xc)
1451 return NULL; 1459 return NULL;
1452 1460
@@ -1958,7 +1966,8 @@ EXPORT_SYMBOL(km_policy_expired);
1958#ifdef CONFIG_XFRM_MIGRATE 1966#ifdef CONFIG_XFRM_MIGRATE
1959int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 1967int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1960 const struct xfrm_migrate *m, int num_migrate, 1968 const struct xfrm_migrate *m, int num_migrate,
1961 const struct xfrm_kmaddress *k) 1969 const struct xfrm_kmaddress *k,
1970 const struct xfrm_encap_tmpl *encap)
1962{ 1971{
1963 int err = -EINVAL; 1972 int err = -EINVAL;
1964 int ret; 1973 int ret;
@@ -1967,7 +1976,8 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1967 rcu_read_lock(); 1976 rcu_read_lock();
1968 list_for_each_entry_rcu(km, &xfrm_km_list, list) { 1977 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1969 if (km->migrate) { 1978 if (km->migrate) {
1970 ret = km->migrate(sel, dir, type, m, num_migrate, k); 1979 ret = km->migrate(sel, dir, type, m, num_migrate, k,
1980 encap);
1971 if (!ret) 1981 if (!ret)
1972 err = ret; 1982 err = ret;
1973 } 1983 }
@@ -2025,13 +2035,9 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
2025 if (optlen <= 0 || optlen > PAGE_SIZE) 2035 if (optlen <= 0 || optlen > PAGE_SIZE)
2026 return -EMSGSIZE; 2036 return -EMSGSIZE;
2027 2037
2028 data = kmalloc(optlen, GFP_KERNEL); 2038 data = memdup_user(optval, optlen);
2029 if (!data) 2039 if (IS_ERR(data))
2030 return -ENOMEM; 2040 return PTR_ERR(data);
2031
2032 err = -EFAULT;
2033 if (copy_from_user(data, optval, optlen))
2034 goto out;
2035 2041
2036 err = -EINVAL; 2042 err = -EINVAL;
2037 rcu_read_lock(); 2043 rcu_read_lock();
@@ -2049,7 +2055,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
2049 err = 0; 2055 err = 0;
2050 } 2056 }
2051 2057
2052out:
2053 kfree(data); 2058 kfree(data);
2054 return err; 2059 return err;
2055} 2060}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38614df33ec8..6197c7231bc7 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2243,6 +2243,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2243 int err; 2243 int err;
2244 int n = 0; 2244 int n = 0;
2245 struct net *net = sock_net(skb->sk); 2245 struct net *net = sock_net(skb->sk);
2246 struct xfrm_encap_tmpl *encap = NULL;
2246 2247
2247 if (attrs[XFRMA_MIGRATE] == NULL) 2248 if (attrs[XFRMA_MIGRATE] == NULL)
2248 return -EINVAL; 2249 return -EINVAL;
@@ -2260,9 +2261,18 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2260 if (!n) 2261 if (!n)
2261 return 0; 2262 return 0;
2262 2263
2263 xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net); 2264 if (attrs[XFRMA_ENCAP]) {
2265 encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
2266 sizeof(*encap), GFP_KERNEL);
2267 if (!encap)
2268 return 0;
2269 }
2264 2270
2265 return 0; 2271 err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);
2272
2273 kfree(encap);
2274
2275 return err;
2266} 2276}
2267#else 2277#else
2268static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, 2278static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2304,17 +2314,20 @@ static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff
2304 return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); 2314 return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
2305} 2315}
2306 2316
2307static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) 2317static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma,
2318 int with_encp)
2308{ 2319{
2309 return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) 2320 return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
2310 + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) 2321 + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
2322 + (with_encp ? nla_total_size(sizeof(struct xfrm_encap_tmpl)) : 0)
2311 + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) 2323 + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
2312 + userpolicy_type_attrsize(); 2324 + userpolicy_type_attrsize();
2313} 2325}
2314 2326
2315static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, 2327static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
2316 int num_migrate, const struct xfrm_kmaddress *k, 2328 int num_migrate, const struct xfrm_kmaddress *k,
2317 const struct xfrm_selector *sel, u8 dir, u8 type) 2329 const struct xfrm_selector *sel,
2330 const struct xfrm_encap_tmpl *encap, u8 dir, u8 type)
2318{ 2331{
2319 const struct xfrm_migrate *mp; 2332 const struct xfrm_migrate *mp;
2320 struct xfrm_userpolicy_id *pol_id; 2333 struct xfrm_userpolicy_id *pol_id;
@@ -2336,6 +2349,11 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
2336 if (err) 2349 if (err)
2337 goto out_cancel; 2350 goto out_cancel;
2338 } 2351 }
2352 if (encap) {
2353 err = nla_put(skb, XFRMA_ENCAP, sizeof(*encap), encap);
2354 if (err)
2355 goto out_cancel;
2356 }
2339 err = copy_to_user_policy_type(type, skb); 2357 err = copy_to_user_policy_type(type, skb);
2340 if (err) 2358 if (err)
2341 goto out_cancel; 2359 goto out_cancel;
@@ -2355,17 +2373,19 @@ out_cancel:
2355 2373
2356static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 2374static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
2357 const struct xfrm_migrate *m, int num_migrate, 2375 const struct xfrm_migrate *m, int num_migrate,
2358 const struct xfrm_kmaddress *k) 2376 const struct xfrm_kmaddress *k,
2377 const struct xfrm_encap_tmpl *encap)
2359{ 2378{
2360 struct net *net = &init_net; 2379 struct net *net = &init_net;
2361 struct sk_buff *skb; 2380 struct sk_buff *skb;
2362 2381
2363 skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); 2382 skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k, !!encap),
2383 GFP_ATOMIC);
2364 if (skb == NULL) 2384 if (skb == NULL)
2365 return -ENOMEM; 2385 return -ENOMEM;
2366 2386
2367 /* build migrate */ 2387 /* build migrate */
2368 if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) 2388 if (build_migrate(skb, m, num_migrate, k, sel, encap, dir, type) < 0)
2369 BUG(); 2389 BUG();
2370 2390
2371 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE); 2391 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
@@ -2373,7 +2393,8 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
2373#else 2393#else
2374static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 2394static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
2375 const struct xfrm_migrate *m, int num_migrate, 2395 const struct xfrm_migrate *m, int num_migrate,
2376 const struct xfrm_kmaddress *k) 2396 const struct xfrm_kmaddress *k,
2397 const struct xfrm_encap_tmpl *encap)
2377{ 2398{
2378 return -ENOPROTOOPT; 2399 return -ENOPROTOOPT;
2379} 2400}