Commit 6f26b61e authored by Jamal Hadi Salim's avatar Jamal Hadi Salim Committed by David S. Miller

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: default avatarJamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 34f8d884
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#endif #endif
#define DUMMY_MARK 0 #define DUMMY_MARK 0
static struct xfrm_mark dummy_mark = {0, 0};
static inline int aead_len(struct xfrm_algo_aead *alg) static inline int aead_len(struct xfrm_algo_aead *alg)
{ {
...@@ -449,6 +448,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -449,6 +448,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error; goto error;
} }
xfrm_mark_get(attrs, &x->mark);
err = xfrm_init_state(x); err = xfrm_init_state(x);
if (err) if (err)
goto error; goto error;
...@@ -529,11 +530,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, ...@@ -529,11 +530,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
int *errp) int *errp)
{ {
struct xfrm_state *x = NULL; struct xfrm_state *x = NULL;
struct xfrm_mark m;
int err; int err;
u32 mark = xfrm_mark_get(attrs, &m);
if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
err = -ESRCH; err = -ESRCH;
x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family); x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
} else { } else {
xfrm_address_t *saddr = NULL; xfrm_address_t *saddr = NULL;
...@@ -544,7 +547,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, ...@@ -544,7 +547,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
} }
err = -ESRCH; err = -ESRCH;
x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr, x = xfrm_state_lookup_byaddr(net, mark,
&p->daddr, saddr,
p->proto, p->family); p->proto, p->family);
} }
...@@ -686,6 +690,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x, ...@@ -686,6 +690,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
if (x->encap) if (x->encap)
NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
if (xfrm_mark_put(skb, &x->mark))
goto nla_put_failure;
if (x->security && copy_sec_ctx(x->security, skb) < 0) if (x->security && copy_sec_ctx(x->security, skb) < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -950,6 +957,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -950,6 +957,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
xfrm_address_t *daddr; xfrm_address_t *daddr;
int family; int family;
int err; int err;
u32 mark;
struct xfrm_mark m;
p = nlmsg_data(nlh); p = nlmsg_data(nlh);
err = verify_userspi_info(p); err = verify_userspi_info(p);
...@@ -960,8 +969,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -960,8 +969,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
daddr = &p->info.id.daddr; daddr = &p->info.id.daddr;
x = NULL; x = NULL;
mark = xfrm_mark_get(attrs, &m);
if (p->info.seq) { if (p->info.seq) {
x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq); x = xfrm_find_acq_byseq(net, mark, p->info.seq);
if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
xfrm_state_put(x); xfrm_state_put(x);
x = NULL; x = NULL;
...@@ -969,7 +980,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -969,7 +980,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
if (!x) if (!x)
x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid, x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
p->info.id.proto, daddr, p->info.id.proto, daddr,
&p->info.saddr, 1, &p->info.saddr, 1,
family); family);
...@@ -1474,8 +1485,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1474,8 +1485,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err) if (err)
return err; return err;
} }
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel,
&p->sel, ctx, delete, &err); ctx, delete, &err);
security_xfrm_policy_free(ctx); security_xfrm_policy_free(ctx);
} }
if (xp == NULL) if (xp == NULL)
...@@ -1547,6 +1558,7 @@ static inline size_t xfrm_aevent_msgsize(void) ...@@ -1547,6 +1558,7 @@ static inline size_t xfrm_aevent_msgsize(void)
return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
+ nla_total_size(sizeof(struct xfrm_replay_state)) + nla_total_size(sizeof(struct xfrm_replay_state))
+ nla_total_size(sizeof(struct xfrm_lifetime_cur)) + nla_total_size(sizeof(struct xfrm_lifetime_cur))
+ nla_total_size(sizeof(struct xfrm_mark))
+ nla_total_size(4) /* XFRM_AE_RTHR */ + nla_total_size(4) /* XFRM_AE_RTHR */
+ nla_total_size(4); /* XFRM_AE_ETHR */ + nla_total_size(4); /* XFRM_AE_ETHR */
} }
...@@ -1579,6 +1591,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve ...@@ -1579,6 +1591,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH,
x->replay_maxage * 10 / HZ); x->replay_maxage * 10 / HZ);
if (xfrm_mark_put(skb, &x->mark))
goto nla_put_failure;
return nlmsg_end(skb, nlh); return nlmsg_end(skb, nlh);
nla_put_failure: nla_put_failure:
...@@ -1594,6 +1609,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1594,6 +1609,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct sk_buff *r_skb; struct sk_buff *r_skb;
int err; int err;
struct km_event c; struct km_event c;
u32 mark;
struct xfrm_mark m;
struct xfrm_aevent_id *p = nlmsg_data(nlh); struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct xfrm_usersa_id *id = &p->sa_id; struct xfrm_usersa_id *id = &p->sa_id;
...@@ -1601,7 +1618,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1601,7 +1618,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (r_skb == NULL) if (r_skb == NULL)
return -ENOMEM; return -ENOMEM;
x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family); mark = xfrm_mark_get(attrs, &m);
x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
if (x == NULL) { if (x == NULL) {
kfree_skb(r_skb); kfree_skb(r_skb);
return -ESRCH; return -ESRCH;
...@@ -1632,6 +1651,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1632,6 +1651,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_state *x; struct xfrm_state *x;
struct km_event c; struct km_event c;
int err = - EINVAL; int err = - EINVAL;
u32 mark = 0;
struct xfrm_mark m;
struct xfrm_aevent_id *p = nlmsg_data(nlh); struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
...@@ -1643,7 +1664,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1643,7 +1664,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
return err; return err;
x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); mark = xfrm_mark_get(attrs, &m);
x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
if (x == NULL) if (x == NULL)
return -ESRCH; return -ESRCH;
...@@ -1729,7 +1752,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1729,7 +1752,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err) if (err)
return err; return err;
} }
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err); xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir,
&p->sel, ctx, 0, &err);
security_xfrm_policy_free(ctx); security_xfrm_policy_free(ctx);
} }
if (xp == NULL) if (xp == NULL)
...@@ -1769,8 +1793,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1769,8 +1793,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
int err; int err;
struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_user_expire *ue = nlmsg_data(nlh);
struct xfrm_usersa_info *p = &ue->state; struct xfrm_usersa_info *p = &ue->state;
struct xfrm_mark m;
u32 mark = xfrm_mark_get(attrs, &m);;
x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family); x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
err = -ENOENT; err = -ENOENT;
if (x == NULL) if (x == NULL)
...@@ -1804,6 +1830,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1804,6 +1830,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_user_tmpl *ut; struct xfrm_user_tmpl *ut;
int i; int i;
struct nlattr *rt = attrs[XFRMA_TMPL]; struct nlattr *rt = attrs[XFRMA_TMPL];
struct xfrm_mark mark;
struct xfrm_user_acquire *ua = nlmsg_data(nlh); struct xfrm_user_acquire *ua = nlmsg_data(nlh);
struct xfrm_state *x = xfrm_state_alloc(net); 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,6 +1839,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!x) if (!x)
goto nomem; goto nomem;
xfrm_mark_get(attrs, &mark);
err = verify_newpolicy_info(&ua->policy); err = verify_newpolicy_info(&ua->policy);
if (err) if (err)
goto bad_policy; goto bad_policy;
...@@ -1824,7 +1853,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1824,7 +1853,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
memcpy(&x->id, &ua->id, sizeof(ua->id)); memcpy(&x->id, &ua->id, sizeof(ua->id));
memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));
memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); memcpy(&x->sel, &ua->sel, sizeof(ua->sel));
xp->mark.m = x->mark.m = mark.m;
xp->mark.v = x->mark.v = mark.v;
ut = nla_data(rt); ut = nla_data(rt);
/* extract the templates and for each call km_key */ /* extract the templates and for each call km_key */
for (i = 0; i < xp->xfrm_nr; i++, ut++) { for (i = 0; i < xp->xfrm_nr; i++, ut++) {
...@@ -2084,6 +2114,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { ...@@ -2084,6 +2114,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)},
[XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
[XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
}; };
static struct xfrm_link { static struct xfrm_link {
...@@ -2163,7 +2194,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb) ...@@ -2163,7 +2194,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
static inline size_t xfrm_expire_msgsize(void) static inline size_t xfrm_expire_msgsize(void)
{ {
return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)); return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
+ nla_total_size(sizeof(struct xfrm_mark));
} }
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) static 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,7 +2211,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
copy_to_user_state(x, &ue->state); copy_to_user_state(x, &ue->state);
ue->hard = (c->data.hard != 0) ? 1 : 0; ue->hard = (c->data.hard != 0) ? 1 : 0;
if (xfrm_mark_put(skb, &x->mark))
goto nla_put_failure;
return nlmsg_end(skb, nlh); return nlmsg_end(skb, nlh);
nla_put_failure:
return -EMSGSIZE;
} }
static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) static 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,8 +2229,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
if (skb == NULL) if (skb == NULL)
return -ENOMEM; return -ENOMEM;
if (build_expire(skb, x, c) < 0) if (build_expire(skb, x, c) < 0) {
BUG(); kfree_skb(skb);
return -EMSGSIZE;
}
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
} }
...@@ -2280,6 +2320,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) ...@@ -2280,6 +2320,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
if (c->event == XFRM_MSG_DELSA) { if (c->event == XFRM_MSG_DELSA) {
len += nla_total_size(headlen); len += nla_total_size(headlen);
headlen = sizeof(*id); headlen = sizeof(*id);
len += nla_total_size(sizeof(struct xfrm_mark));
} }
len += NLMSG_ALIGN(headlen); len += NLMSG_ALIGN(headlen);
...@@ -2350,6 +2391,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, ...@@ -2350,6 +2391,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
{ {
return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))
+ nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
+ nla_total_size(sizeof(struct xfrm_mark))
+ nla_total_size(xfrm_user_sec_ctx_size(x->security)) + nla_total_size(xfrm_user_sec_ctx_size(x->security))
+ userpolicy_type_attrsize(); + userpolicy_type_attrsize();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment