aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c37
1 files changed, 29 insertions, 8 deletions
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}