diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 37 |
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 |
2268 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | 2278 | static 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 | ||
2307 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | 2317 | static 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 | ||
2315 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, | 2327 | static 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 | ||
2356 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2374 | static 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 |
2374 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2394 | static 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 | } |