提交 9b42c1f1 编写于 作者: S Steffen Klassert

xfrm: Extend the output_mark to support input direction and masking.

We already support setting an output mark at the xfrm_state,
unfortunately this does not support the input direction and
masking the marks that will be applied to the skb. This change
adds support applying a masked value in both directions.

The existing XFRMA_OUTPUT_MARK number is reused for this purpose
and as it is now bi-directional, it is renamed to XFRMA_SET_MARK.

An additional XFRMA_SET_MARK_MASK attribute is added for setting the
mask. If the attribute mask not provided, it is set to 0xffffffff,
keeping the XFRMA_OUTPUT_MARK existing 'full mask' semantics.
Co-developed-by: NTobias Brunner <tobias@strongswan.org>
Co-developed-by: NEyal Birger <eyal.birger@gmail.com>
Co-developed-by: NLorenzo Colitti <lorenzo@google.com>
Signed-off-by: NSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: NTobias Brunner <tobias@strongswan.org>
Signed-off-by: NEyal Birger <eyal.birger@gmail.com>
Signed-off-by: NLorenzo Colitti <lorenzo@google.com>
上级 dd55c4ea
...@@ -166,7 +166,7 @@ struct xfrm_state { ...@@ -166,7 +166,7 @@ struct xfrm_state {
int header_len; int header_len;
int trailer_len; int trailer_len;
u32 extra_flags; u32 extra_flags;
u32 output_mark; struct xfrm_mark smark;
} props; } props;
struct xfrm_lifetime_cfg lft; struct xfrm_lifetime_cfg lft;
...@@ -2012,6 +2012,13 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m) ...@@ -2012,6 +2012,13 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
return ret; return ret;
} }
static inline __u32 xfrm_smark_get(__u32 mark, struct xfrm_state *x)
{
struct xfrm_mark *m = &x->props.smark;
return (m->v & m->m) | (mark & ~m->m);
}
static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x, static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
unsigned int family) unsigned int family)
{ {
......
...@@ -305,9 +305,11 @@ enum xfrm_attr_type_t { ...@@ -305,9 +305,11 @@ enum xfrm_attr_type_t {
XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
XFRMA_PAD, XFRMA_PAD,
XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */ XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
XFRMA_OUTPUT_MARK, /* __u32 */ XFRMA_SET_MARK, /* __u32 */
XFRMA_SET_MARK_MASK, /* __u32 */
__XFRMA_MAX __XFRMA_MAX
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
#define XFRMA_MAX (__XFRMA_MAX - 1) #define XFRMA_MAX (__XFRMA_MAX - 1)
}; };
......
...@@ -162,7 +162,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, ...@@ -162,7 +162,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
} }
dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
x->props.family, x->props.output_mark); x->props.family,
xfrm_smark_get(0, x));
if (IS_ERR(dst)) if (IS_ERR(dst))
return 0; return 0;
......
...@@ -339,6 +339,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -339,6 +339,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop; goto drop;
} }
skb->mark = xfrm_smark_get(skb->mark, x);
skb->sp->xvec[skb->sp->len++] = x; skb->sp->xvec[skb->sp->len++] = x;
lock: lock:
......
...@@ -66,8 +66,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) ...@@ -66,8 +66,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
goto error_nolock; goto error_nolock;
} }
if (x->props.output_mark) skb->mark = xfrm_smark_get(skb->mark, x);
skb->mark = x->props.output_mark;
err = x->outer_mode->output(x, skb); err = x->outer_mode->output(x, skb);
if (err) { if (err) {
......
...@@ -1607,10 +1607,11 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, ...@@ -1607,10 +1607,11 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
dst_copy_metrics(dst1, dst); dst_copy_metrics(dst1, dst);
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
__u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
family = xfrm[i]->props.family; family = xfrm[i]->props.family;
dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
&saddr, &daddr, family, &saddr, &daddr, family, mark);
xfrm[i]->props.output_mark);
err = PTR_ERR(dst); err = PTR_ERR(dst);
if (IS_ERR(dst)) if (IS_ERR(dst))
goto put_states; goto put_states;
......
...@@ -527,6 +527,19 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, ...@@ -527,6 +527,19 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
x->replay_maxdiff = nla_get_u32(rt); x->replay_maxdiff = nla_get_u32(rt);
} }
static void xfrm_smark_init(struct nlattr **attrs, struct xfrm_mark *m)
{
if (attrs[XFRMA_SET_MARK]) {
m->v = nla_get_u32(attrs[XFRMA_SET_MARK]);
if (attrs[XFRMA_SET_MARK_MASK])
m->m = nla_get_u32(attrs[XFRMA_SET_MARK_MASK]);
else
m->m = 0xffffffff;
} else {
m->v = m->m = 0;
}
}
static struct xfrm_state *xfrm_state_construct(struct net *net, static struct xfrm_state *xfrm_state_construct(struct net *net,
struct xfrm_usersa_info *p, struct xfrm_usersa_info *p,
struct nlattr **attrs, struct nlattr **attrs,
...@@ -579,8 +592,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -579,8 +592,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
xfrm_mark_get(attrs, &x->mark); xfrm_mark_get(attrs, &x->mark);
if (attrs[XFRMA_OUTPUT_MARK]) xfrm_smark_init(attrs, &x->props.smark);
x->props.output_mark = nla_get_u32(attrs[XFRMA_OUTPUT_MARK]);
err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]); err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
if (err) if (err)
...@@ -824,6 +836,18 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) ...@@ -824,6 +836,18 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
return 0; return 0;
} }
static int xfrm_smark_put(struct sk_buff *skb, struct xfrm_mark *m)
{
int ret = 0;
if (m->v | m->m) {
ret = nla_put_u32(skb, XFRMA_SET_MARK, m->v);
if (!ret)
ret = nla_put_u32(skb, XFRMA_SET_MARK_MASK, m->m);
}
return ret;
}
/* Don't change this without updating xfrm_sa_len! */ /* Don't change this without updating xfrm_sa_len! */
static int copy_to_user_state_extra(struct xfrm_state *x, static int copy_to_user_state_extra(struct xfrm_state *x,
struct xfrm_usersa_info *p, struct xfrm_usersa_info *p,
...@@ -887,6 +911,11 @@ static int copy_to_user_state_extra(struct xfrm_state *x, ...@@ -887,6 +911,11 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
ret = xfrm_mark_put(skb, &x->mark); ret = xfrm_mark_put(skb, &x->mark);
if (ret) if (ret)
goto out; goto out;
ret = xfrm_smark_put(skb, &x->props.smark);
if (ret)
goto out;
if (x->replay_esn) if (x->replay_esn)
ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL, ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
xfrm_replay_state_esn_len(x->replay_esn), xfrm_replay_state_esn_len(x->replay_esn),
...@@ -900,11 +929,7 @@ static int copy_to_user_state_extra(struct xfrm_state *x, ...@@ -900,11 +929,7 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
ret = copy_user_offload(&x->xso, skb); ret = copy_user_offload(&x->xso, skb);
if (ret) if (ret)
goto out; goto out;
if (x->props.output_mark) {
ret = nla_put_u32(skb, XFRMA_OUTPUT_MARK, x->props.output_mark);
if (ret)
goto out;
}
if (x->security) if (x->security)
ret = copy_sec_ctx(x->security, skb); ret = copy_sec_ctx(x->security, skb);
out: out:
...@@ -2493,7 +2518,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { ...@@ -2493,7 +2518,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_PROTO] = { .type = NLA_U8 }, [XFRMA_PROTO] = { .type = NLA_U8 },
[XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) }, [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },
[XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) }, [XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) },
[XFRMA_OUTPUT_MARK] = { .type = NLA_U32 }, [XFRMA_SET_MARK] = { .type = NLA_U32 },
[XFRMA_SET_MARK_MASK] = { .type = NLA_U32 },
}; };
static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
...@@ -2719,8 +2745,10 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) ...@@ -2719,8 +2745,10 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
l += nla_total_size(sizeof(x->props.extra_flags)); l += nla_total_size(sizeof(x->props.extra_flags));
if (x->xso.dev) if (x->xso.dev)
l += nla_total_size(sizeof(x->xso)); l += nla_total_size(sizeof(x->xso));
if (x->props.output_mark) if (x->props.smark.v | x->props.smark.m) {
l += nla_total_size(sizeof(x->props.output_mark)); l += nla_total_size(sizeof(x->props.smark.v));
l += nla_total_size(sizeof(x->props.smark.m));
}
/* Must count x->lastused as it may become non-zero behind our back. */ /* Must count x->lastused as it may become non-zero behind our back. */
l += nla_total_size_64bit(sizeof(u64)); l += nla_total_size_64bit(sizeof(u64));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册