aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@cyberus.ca>2010-02-22 06:32:59 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-22 19:21:25 -0500
commit6f26b61e177e57a41795355f6222cf817f1212dc (patch)
tree6894f386ad84fa6d48ff860e6f04b9e5acd65024 /net/xfrm/xfrm_user.c
parent34f8d8846f69f3b5bc3916ba9145e4eebae9394e (diff)
xfrm: Allow user space config of SAD mark
Add ability for netlink userspace to manipulate the SAD and manipulate the mark, retrieve it and get events with a defined mark. MIGRATE may be added later. Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c72
1 files changed, 57 insertions, 15 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 02a67b4a64dd..303092f7088b 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -32,7 +32,6 @@
32#endif 32#endif
33 33
34#define DUMMY_MARK 0 34#define DUMMY_MARK 0
35static struct xfrm_mark dummy_mark = {0, 0};
36 35
37static inline int aead_len(struct xfrm_algo_aead *alg) 36static inline int aead_len(struct xfrm_algo_aead *alg)
38{ 37{
@@ -449,6 +448,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
449 goto error; 448 goto error;
450 } 449 }
451 450
451 xfrm_mark_get(attrs, &x->mark);
452
452 err = xfrm_init_state(x); 453 err = xfrm_init_state(x);
453 if (err) 454 if (err)
454 goto error; 455 goto error;
@@ -529,11 +530,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
529 int *errp) 530 int *errp)
530{ 531{
531 struct xfrm_state *x = NULL; 532 struct xfrm_state *x = NULL;
533 struct xfrm_mark m;
532 int err; 534 int err;
535 u32 mark = xfrm_mark_get(attrs, &m);
533 536
534 if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { 537 if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
535 err = -ESRCH; 538 err = -ESRCH;
536 x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family); 539 x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
537 } else { 540 } else {
538 xfrm_address_t *saddr = NULL; 541 xfrm_address_t *saddr = NULL;
539 542
@@ -544,7 +547,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
544 } 547 }
545 548
546 err = -ESRCH; 549 err = -ESRCH;
547 x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr, 550 x = xfrm_state_lookup_byaddr(net, mark,
551 &p->daddr, saddr,
548 p->proto, p->family); 552 p->proto, p->family);
549 } 553 }
550 554
@@ -686,6 +690,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
686 if (x->encap) 690 if (x->encap)
687 NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); 691 NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
688 692
693 if (xfrm_mark_put(skb, &x->mark))
694 goto nla_put_failure;
695
689 if (x->security && copy_sec_ctx(x->security, skb) < 0) 696 if (x->security && copy_sec_ctx(x->security, skb) < 0)
690 goto nla_put_failure; 697 goto nla_put_failure;
691 698
@@ -950,6 +957,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
950 xfrm_address_t *daddr; 957 xfrm_address_t *daddr;
951 int family; 958 int family;
952 int err; 959 int err;
960 u32 mark;
961 struct xfrm_mark m;
953 962
954 p = nlmsg_data(nlh); 963 p = nlmsg_data(nlh);
955 err = verify_userspi_info(p); 964 err = verify_userspi_info(p);
@@ -960,8 +969,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
960 daddr = &p->info.id.daddr; 969 daddr = &p->info.id.daddr;
961 970
962 x = NULL; 971 x = NULL;
972
973 mark = xfrm_mark_get(attrs, &m);
963 if (p->info.seq) { 974 if (p->info.seq) {
964 x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq); 975 x = xfrm_find_acq_byseq(net, mark, p->info.seq);
965 if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { 976 if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
966 xfrm_state_put(x); 977 xfrm_state_put(x);
967 x = NULL; 978 x = NULL;
@@ -969,7 +980,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
969 } 980 }
970 981
971 if (!x) 982 if (!x)
972 x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid, 983 x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
973 p->info.id.proto, daddr, 984 p->info.id.proto, daddr,
974 &p->info.saddr, 1, 985 &p->info.saddr, 1,
975 family); 986 family);
@@ -1474,8 +1485,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1474 if (err) 1485 if (err)
1475 return err; 1486 return err;
1476 } 1487 }
1477 xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, 1488 xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel,
1478 &p->sel, ctx, delete, &err); 1489 ctx, delete, &err);
1479 security_xfrm_policy_free(ctx); 1490 security_xfrm_policy_free(ctx);
1480 } 1491 }
1481 if (xp == NULL) 1492 if (xp == NULL)
@@ -1547,6 +1558,7 @@ static inline size_t xfrm_aevent_msgsize(void)
1547 return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) 1558 return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1548 + nla_total_size(sizeof(struct xfrm_replay_state)) 1559 + nla_total_size(sizeof(struct xfrm_replay_state))
1549 + nla_total_size(sizeof(struct xfrm_lifetime_cur)) 1560 + nla_total_size(sizeof(struct xfrm_lifetime_cur))
1561 + nla_total_size(sizeof(struct xfrm_mark))
1550 + nla_total_size(4) /* XFRM_AE_RTHR */ 1562 + nla_total_size(4) /* XFRM_AE_RTHR */
1551 + nla_total_size(4); /* XFRM_AE_ETHR */ 1563 + nla_total_size(4); /* XFRM_AE_ETHR */
1552} 1564}
@@ -1579,6 +1591,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
1579 NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, 1591 NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH,
1580 x->replay_maxage * 10 / HZ); 1592 x->replay_maxage * 10 / HZ);
1581 1593
1594 if (xfrm_mark_put(skb, &x->mark))
1595 goto nla_put_failure;
1596
1582 return nlmsg_end(skb, nlh); 1597 return nlmsg_end(skb, nlh);
1583 1598
1584nla_put_failure: 1599nla_put_failure:
@@ -1594,6 +1609,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1594 struct sk_buff *r_skb; 1609 struct sk_buff *r_skb;
1595 int err; 1610 int err;
1596 struct km_event c; 1611 struct km_event c;
1612 u32 mark;
1613 struct xfrm_mark m;
1597 struct xfrm_aevent_id *p = nlmsg_data(nlh); 1614 struct xfrm_aevent_id *p = nlmsg_data(nlh);
1598 struct xfrm_usersa_id *id = &p->sa_id; 1615 struct xfrm_usersa_id *id = &p->sa_id;
1599 1616
@@ -1601,7 +1618,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1601 if (r_skb == NULL) 1618 if (r_skb == NULL)
1602 return -ENOMEM; 1619 return -ENOMEM;
1603 1620
1604 x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family); 1621 mark = xfrm_mark_get(attrs, &m);
1622
1623 x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1605 if (x == NULL) { 1624 if (x == NULL) {
1606 kfree_skb(r_skb); 1625 kfree_skb(r_skb);
1607 return -ESRCH; 1626 return -ESRCH;
@@ -1632,6 +1651,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1632 struct xfrm_state *x; 1651 struct xfrm_state *x;
1633 struct km_event c; 1652 struct km_event c;
1634 int err = - EINVAL; 1653 int err = - EINVAL;
1654 u32 mark = 0;
1655 struct xfrm_mark m;
1635 struct xfrm_aevent_id *p = nlmsg_data(nlh); 1656 struct xfrm_aevent_id *p = nlmsg_data(nlh);
1636 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; 1657 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1637 struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; 1658 struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
@@ -1643,7 +1664,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1643 if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) 1664 if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
1644 return err; 1665 return err;
1645 1666
1646 x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); 1667 mark = xfrm_mark_get(attrs, &m);
1668
1669 x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
1647 if (x == NULL) 1670 if (x == NULL)
1648 return -ESRCH; 1671 return -ESRCH;
1649 1672
@@ -1729,7 +1752,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1729 if (err) 1752 if (err)
1730 return err; 1753 return err;
1731 } 1754 }
1732 xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err); 1755 xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
1756 &p->sel, ctx, 0, &err);
1733 security_xfrm_policy_free(ctx); 1757 security_xfrm_policy_free(ctx);
1734 } 1758 }
1735 if (xp == NULL) 1759 if (xp == NULL)
@@ -1769,8 +1793,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1769 int err; 1793 int err;
1770 struct xfrm_user_expire *ue = nlmsg_data(nlh); 1794 struct xfrm_user_expire *ue = nlmsg_data(nlh);
1771 struct xfrm_usersa_info *p = &ue->state; 1795 struct xfrm_usersa_info *p = &ue->state;
1796 struct xfrm_mark m;
1797 u32 mark = xfrm_mark_get(attrs, &m);;
1772 1798
1773 x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family); 1799 x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
1774 1800
1775 err = -ENOENT; 1801 err = -ENOENT;
1776 if (x == NULL) 1802 if (x == NULL)
@@ -1804,6 +1830,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1804 struct xfrm_user_tmpl *ut; 1830 struct xfrm_user_tmpl *ut;
1805 int i; 1831 int i;
1806 struct nlattr *rt = attrs[XFRMA_TMPL]; 1832 struct nlattr *rt = attrs[XFRMA_TMPL];
1833 struct xfrm_mark mark;
1807 1834
1808 struct xfrm_user_acquire *ua = nlmsg_data(nlh); 1835 struct xfrm_user_acquire *ua = nlmsg_data(nlh);
1809 struct xfrm_state *x = xfrm_state_alloc(net); 1836 struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1812,6 +1839,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1812 if (!x) 1839 if (!x)
1813 goto nomem; 1840 goto nomem;
1814 1841
1842 xfrm_mark_get(attrs, &mark);
1843
1815 err = verify_newpolicy_info(&ua->policy); 1844 err = verify_newpolicy_info(&ua->policy);
1816 if (err) 1845 if (err)
1817 goto bad_policy; 1846 goto bad_policy;
@@ -1824,7 +1853,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1824 memcpy(&x->id, &ua->id, sizeof(ua->id)); 1853 memcpy(&x->id, &ua->id, sizeof(ua->id));
1825 memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); 1854 memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));
1826 memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); 1855 memcpy(&x->sel, &ua->sel, sizeof(ua->sel));
1827 1856 xp->mark.m = x->mark.m = mark.m;
1857 xp->mark.v = x->mark.v = mark.v;
1828 ut = nla_data(rt); 1858 ut = nla_data(rt);
1829 /* extract the templates and for each call km_key */ 1859 /* extract the templates and for each call km_key */
1830 for (i = 0; i < xp->xfrm_nr; i++, ut++) { 1860 for (i = 0; i < xp->xfrm_nr; i++, ut++) {
@@ -2084,6 +2114,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
2084 [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, 2114 [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)},
2085 [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, 2115 [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
2086 [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, 2116 [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
2117 [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
2087}; 2118};
2088 2119
2089static struct xfrm_link { 2120static struct xfrm_link {
@@ -2163,7 +2194,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
2163 2194
2164static inline size_t xfrm_expire_msgsize(void) 2195static inline size_t xfrm_expire_msgsize(void)
2165{ 2196{
2166 return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)); 2197 return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
2198 + nla_total_size(sizeof(struct xfrm_mark));
2167} 2199}
2168 2200
2169static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) 2201static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
@@ -2179,7 +2211,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
2179 copy_to_user_state(x, &ue->state); 2211 copy_to_user_state(x, &ue->state);
2180 ue->hard = (c->data.hard != 0) ? 1 : 0; 2212 ue->hard = (c->data.hard != 0) ? 1 : 0;
2181 2213
2214 if (xfrm_mark_put(skb, &x->mark))
2215 goto nla_put_failure;
2216
2182 return nlmsg_end(skb, nlh); 2217 return nlmsg_end(skb, nlh);
2218
2219nla_put_failure:
2220 return -EMSGSIZE;
2183} 2221}
2184 2222
2185static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) 2223static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
@@ -2191,8 +2229,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
2191 if (skb == NULL) 2229 if (skb == NULL)
2192 return -ENOMEM; 2230 return -ENOMEM;
2193 2231
2194 if (build_expire(skb, x, c) < 0) 2232 if (build_expire(skb, x, c) < 0) {
2195 BUG(); 2233 kfree_skb(skb);
2234 return -EMSGSIZE;
2235 }
2196 2236
2197 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); 2237 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
2198} 2238}
@@ -2280,6 +2320,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
2280 if (c->event == XFRM_MSG_DELSA) { 2320 if (c->event == XFRM_MSG_DELSA) {
2281 len += nla_total_size(headlen); 2321 len += nla_total_size(headlen);
2282 headlen = sizeof(*id); 2322 headlen = sizeof(*id);
2323 len += nla_total_size(sizeof(struct xfrm_mark));
2283 } 2324 }
2284 len += NLMSG_ALIGN(headlen); 2325 len += NLMSG_ALIGN(headlen);
2285 2326
@@ -2350,6 +2391,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
2350{ 2391{
2351 return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) 2392 return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))
2352 + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) 2393 + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
2394 + nla_total_size(sizeof(struct xfrm_mark))
2353 + nla_total_size(xfrm_user_sec_ctx_size(x->security)) 2395 + nla_total_size(xfrm_user_sec_ctx_size(x->security))
2354 + userpolicy_type_attrsize(); 2396 + userpolicy_type_attrsize();
2355} 2397}