diff options
author | Jamal Hadi Salim <hadi@cyberus.ca> | 2010-02-22 06:33:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-22 19:21:26 -0500 |
commit | 295fae568885a93c39a0e29a9455054608b6cc0e (patch) | |
tree | 1cce881be6501a8ddad33e6ea7c6336b93e5562f /net/xfrm | |
parent | 6f26b61e177e57a41795355f6222cf817f1212dc (diff) |
xfrm: Allow user space manipulation of SPD mark
Add ability for netlink userspace to manipulate the SPD
and manipulate the mark, retrieve it and get events with a defined
mark, etc.
Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_user.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 303092f7088b..6106b72826d3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/in6.h> | 31 | #include <linux/in6.h> |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #define DUMMY_MARK 0 | ||
35 | |||
36 | static inline int aead_len(struct xfrm_algo_aead *alg) | 34 | static inline int aead_len(struct xfrm_algo_aead *alg) |
37 | { | 35 | { |
38 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); | 36 | return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); |
@@ -1234,6 +1232,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us | |||
1234 | if (err) | 1232 | if (err) |
1235 | goto error; | 1233 | goto error; |
1236 | 1234 | ||
1235 | xfrm_mark_get(attrs, &xp->mark); | ||
1236 | |||
1237 | return xp; | 1237 | return xp; |
1238 | error: | 1238 | error: |
1239 | *errp = err; | 1239 | *errp = err; |
@@ -1380,10 +1380,13 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr | |||
1380 | goto nlmsg_failure; | 1380 | goto nlmsg_failure; |
1381 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 1381 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
1382 | goto nlmsg_failure; | 1382 | goto nlmsg_failure; |
1383 | if (xfrm_mark_put(skb, &xp->mark)) | ||
1384 | goto nla_put_failure; | ||
1383 | 1385 | ||
1384 | nlmsg_end(skb, nlh); | 1386 | nlmsg_end(skb, nlh); |
1385 | return 0; | 1387 | return 0; |
1386 | 1388 | ||
1389 | nla_put_failure: | ||
1387 | nlmsg_failure: | 1390 | nlmsg_failure: |
1388 | nlmsg_cancel(skb, nlh); | 1391 | nlmsg_cancel(skb, nlh); |
1389 | return -EMSGSIZE; | 1392 | return -EMSGSIZE; |
@@ -1455,6 +1458,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1455 | int err; | 1458 | int err; |
1456 | struct km_event c; | 1459 | struct km_event c; |
1457 | int delete; | 1460 | int delete; |
1461 | struct xfrm_mark m; | ||
1462 | u32 mark = xfrm_mark_get(attrs, &m); | ||
1458 | 1463 | ||
1459 | p = nlmsg_data(nlh); | 1464 | p = nlmsg_data(nlh); |
1460 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; | 1465 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; |
@@ -1468,7 +1473,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1468 | return err; | 1473 | return err; |
1469 | 1474 | ||
1470 | if (p->index) | 1475 | if (p->index) |
1471 | xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, delete, &err); | 1476 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); |
1472 | else { | 1477 | else { |
1473 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1478 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1474 | struct xfrm_sec_ctx *ctx; | 1479 | struct xfrm_sec_ctx *ctx; |
@@ -1485,7 +1490,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1485 | if (err) | 1490 | if (err) |
1486 | return err; | 1491 | return err; |
1487 | } | 1492 | } |
1488 | xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, | 1493 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, |
1489 | ctx, delete, &err); | 1494 | ctx, delete, &err); |
1490 | security_xfrm_policy_free(ctx); | 1495 | security_xfrm_policy_free(ctx); |
1491 | } | 1496 | } |
@@ -1729,13 +1734,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1729 | struct xfrm_userpolicy_info *p = &up->pol; | 1734 | struct xfrm_userpolicy_info *p = &up->pol; |
1730 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1735 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1731 | int err = -ENOENT; | 1736 | int err = -ENOENT; |
1737 | struct xfrm_mark m; | ||
1738 | u32 mark = xfrm_mark_get(attrs, &m); | ||
1732 | 1739 | ||
1733 | err = copy_from_user_policy_type(&type, attrs); | 1740 | err = copy_from_user_policy_type(&type, attrs); |
1734 | if (err) | 1741 | if (err) |
1735 | return err; | 1742 | return err; |
1736 | 1743 | ||
1737 | if (p->index) | 1744 | if (p->index) |
1738 | xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, 0, &err); | 1745 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); |
1739 | else { | 1746 | else { |
1740 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1747 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1741 | struct xfrm_sec_ctx *ctx; | 1748 | struct xfrm_sec_ctx *ctx; |
@@ -1752,7 +1759,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1752 | if (err) | 1759 | if (err) |
1753 | return err; | 1760 | return err; |
1754 | } | 1761 | } |
1755 | xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, | 1762 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, |
1756 | &p->sel, ctx, 0, &err); | 1763 | &p->sel, ctx, 0, &err); |
1757 | security_xfrm_policy_free(ctx); | 1764 | security_xfrm_policy_free(ctx); |
1758 | } | 1765 | } |
@@ -2424,9 +2431,12 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | |||
2424 | goto nlmsg_failure; | 2431 | goto nlmsg_failure; |
2425 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2432 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2426 | goto nlmsg_failure; | 2433 | goto nlmsg_failure; |
2434 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2435 | goto nla_put_failure; | ||
2427 | 2436 | ||
2428 | return nlmsg_end(skb, nlh); | 2437 | return nlmsg_end(skb, nlh); |
2429 | 2438 | ||
2439 | nla_put_failure: | ||
2430 | nlmsg_failure: | 2440 | nlmsg_failure: |
2431 | nlmsg_cancel(skb, nlh); | 2441 | nlmsg_cancel(skb, nlh); |
2432 | return -EMSGSIZE; | 2442 | return -EMSGSIZE; |
@@ -2513,6 +2523,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) | |||
2513 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) | 2523 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) |
2514 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) | 2524 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
2515 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) | 2525 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) |
2526 | + nla_total_size(sizeof(struct xfrm_mark)) | ||
2516 | + userpolicy_type_attrsize(); | 2527 | + userpolicy_type_attrsize(); |
2517 | } | 2528 | } |
2518 | 2529 | ||
@@ -2535,10 +2546,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | |||
2535 | goto nlmsg_failure; | 2546 | goto nlmsg_failure; |
2536 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2547 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2537 | goto nlmsg_failure; | 2548 | goto nlmsg_failure; |
2549 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2550 | goto nla_put_failure; | ||
2538 | upe->hard = !!hard; | 2551 | upe->hard = !!hard; |
2539 | 2552 | ||
2540 | return nlmsg_end(skb, nlh); | 2553 | return nlmsg_end(skb, nlh); |
2541 | 2554 | ||
2555 | nla_put_failure: | ||
2542 | nlmsg_failure: | 2556 | nlmsg_failure: |
2543 | nlmsg_cancel(skb, nlh); | 2557 | nlmsg_cancel(skb, nlh); |
2544 | return -EMSGSIZE; | 2558 | return -EMSGSIZE; |
@@ -2575,6 +2589,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2575 | headlen = sizeof(*id); | 2589 | headlen = sizeof(*id); |
2576 | } | 2590 | } |
2577 | len += userpolicy_type_attrsize(); | 2591 | len += userpolicy_type_attrsize(); |
2592 | len += nla_total_size(sizeof(struct xfrm_mark)); | ||
2578 | len += NLMSG_ALIGN(headlen); | 2593 | len += NLMSG_ALIGN(headlen); |
2579 | 2594 | ||
2580 | skb = nlmsg_new(len, GFP_ATOMIC); | 2595 | skb = nlmsg_new(len, GFP_ATOMIC); |
@@ -2610,10 +2625,14 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2610 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2625 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2611 | goto nlmsg_failure; | 2626 | goto nlmsg_failure; |
2612 | 2627 | ||
2628 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2629 | goto nla_put_failure; | ||
2630 | |||
2613 | nlmsg_end(skb, nlh); | 2631 | nlmsg_end(skb, nlh); |
2614 | 2632 | ||
2615 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2633 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2616 | 2634 | ||
2635 | nla_put_failure: | ||
2617 | nlmsg_failure: | 2636 | nlmsg_failure: |
2618 | kfree_skb(skb); | 2637 | kfree_skb(skb); |
2619 | return -1; | 2638 | return -1; |