Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e652640 authored by Steffen Klassert's avatar Steffen Klassert
Browse files

xfrm: Add a new lookup key to match xfrm interfaces.



This patch adds the xfrm interface id as a lookup key
for xfrm states and policies. With this we can assign
states and policies to virtual xfrm interfaces.

Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Acked-by: default avatarShannon Nelson <shannon.nelson@oracle.com>
Acked-by: default avatarBenedict Wong <benedictwong@google.com>
Tested-by: default avatarBenedict Wong <benedictwong@google.com>
Tested-by: default avatarAntony Antony <antony@phenome.org>
Reviewed-by: default avatarEyal Birger <eyal.birger@gmail.com>
parent d159ce79
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ struct xfrm_state {
	struct xfrm_id		id;
	struct xfrm_selector	sel;
	struct xfrm_mark	mark;
	u32			if_id;
	u32			tfcpad;

	u32			genid;
@@ -574,6 +575,7 @@ struct xfrm_policy {
	atomic_t		genid;
	u32			priority;
	u32			index;
	u32			if_id;
	struct xfrm_mark	mark;
	struct xfrm_selector	selector;
	struct xfrm_lifetime_cfg lft;
@@ -1533,7 +1535,7 @@ struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
				   struct xfrm_tmpl *tmpl,
				   struct xfrm_policy *pol, int *err,
				   unsigned short family);
struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark, u32 if_id,
				       xfrm_address_t *daddr,
				       xfrm_address_t *saddr,
				       unsigned short family,
@@ -1690,20 +1692,20 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
		     void *);
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
					  u8 type, int dir,
					  struct xfrm_selector *sel,
					  struct xfrm_sec_ctx *ctx, int delete,
					  int *err);
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
				     u32 id, int delete, int *err);
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id, u8,
				     int dir, u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
void xfrm_policy_hash_rebuild(struct net *net);
u32 xfrm_get_acqseq(void);
int verify_spi_info(u8 proto, u32 min, u32 max);
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
				 u8 mode, u32 reqid, u8 proto,
				 u8 mode, u32 reqid, u32 if_id, u8 proto,
				 const xfrm_address_t *daddr,
				 const xfrm_address_t *saddr, int create,
				 unsigned short family);
@@ -2019,6 +2021,15 @@ static inline __u32 xfrm_smark_get(__u32 mark, struct xfrm_state *x)
	return (m->v & m->m) | (mark & ~m->m);
}

static inline int xfrm_if_id_put(struct sk_buff *skb, __u32 if_id)
{
	int ret = 0;

	if (if_id)
		ret = nla_put_u32(skb, XFRMA_IF_ID, if_id);
	return ret;
}

static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
				    unsigned int family)
{
+1 −0
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ enum xfrm_attr_type_t {
	XFRMA_OFFLOAD_DEV,	/* struct xfrm_state_offload */
	XFRMA_SET_MARK,		/* __u32 */
	XFRMA_SET_MARK_MASK,	/* __u32 */
	XFRMA_IF_ID,		/* __u32 */
	__XFRMA_MAX

#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK	/* Compatibility */
+1 −1
Original line number Diff line number Diff line
@@ -2255,7 +2255,7 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
			x = xfrm_state_lookup_byspi(pn->net, htonl(pkt_dev->spi), AF_INET);
		} else {
			/* slow path: we dont already have xfrm_state */
			x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
			x = xfrm_stateonly_find(pn->net, DUMMY_MARK, 0,
						(xfrm_address_t *)&pkt_dev->cur_daddr,
						(xfrm_address_t *)&pkt_dev->cur_saddr,
						AF_INET,
+3 −3
Original line number Diff line number Diff line
@@ -1383,7 +1383,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
	}

	if (!x)
		x = xfrm_find_acq(net, &dummy_mark, mode, reqid, proto, xdaddr, xsaddr, 1, family);
		x = xfrm_find_acq(net, &dummy_mark, mode, reqid, 0, proto, xdaddr, xsaddr, 1, family);

	if (x == NULL)
		return -ENOENT;
@@ -2414,7 +2414,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
			return err;
	}

	xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
	xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
				   pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
				   1, &err);
	security_xfrm_policy_free(pol_ctx);
@@ -2663,7 +2663,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
		return -EINVAL;

	delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
	xp = xfrm_policy_byid(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN,
	xp = xfrm_policy_byid(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
			      dir, pol->sadb_x_policy_id, delete, &err);
	if (xp == NULL)
		return -ENOENT;
+13 −5
Original line number Diff line number Diff line
@@ -747,6 +747,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
	newpos = NULL;
	hlist_for_each_entry(pol, chain, bydst) {
		if (pol->type == policy->type &&
		    pol->if_id == policy->if_id &&
		    !selector_cmp(&pol->selector, &policy->selector) &&
		    xfrm_policy_mark_match(policy, pol) &&
		    xfrm_sec_ctx_match(pol->security, policy->security) &&
@@ -798,8 +799,9 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
}
EXPORT_SYMBOL(xfrm_policy_insert);

struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
					  int dir, struct xfrm_selector *sel,
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
					  u8 type, int dir,
					  struct xfrm_selector *sel,
					  struct xfrm_sec_ctx *ctx, int delete,
					  int *err)
{
@@ -812,6 +814,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
	ret = NULL;
	hlist_for_each_entry(pol, chain, bydst) {
		if (pol->type == type &&
		    pol->if_id == if_id &&
		    (mark & pol->mark.m) == pol->mark.v &&
		    !selector_cmp(sel, &pol->selector) &&
		    xfrm_sec_ctx_match(ctx, pol->security)) {
@@ -837,8 +840,9 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
}
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);

struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
				     int dir, u32 id, int delete, int *err)
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
				     u8 type, int dir, u32 id, int delete,
				     int *err)
{
	struct xfrm_policy *pol, *ret;
	struct hlist_head *chain;
@@ -853,6 +857,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
	ret = NULL;
	hlist_for_each_entry(pol, chain, byidx) {
		if (pol->type == type && pol->index == id &&
		    pol->if_id == if_id &&
		    (mark & pol->mark.m) == pol->mark.v) {
			xfrm_pol_hold(pol);
			if (delete) {
@@ -1063,6 +1068,7 @@ static int xfrm_policy_match(const struct xfrm_policy *pol,
	bool match;

	if (pol->family != family ||
	    pol->if_id != fl->flowi_xfrm.if_id ||
	    (fl->flowi_mark & pol->mark.m) != pol->mark.v ||
	    pol->type != type)
		return ret;
@@ -1177,7 +1183,8 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,

		match = xfrm_selector_match(&pol->selector, fl, family);
		if (match) {
			if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
			if ((sk->sk_mark & pol->mark.m) != pol->mark.v ||
			    pol->if_id != fl->flowi_xfrm.if_id) {
				pol = NULL;
				goto out;
			}
@@ -1305,6 +1312,7 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
		newp->lft = old->lft;
		newp->curlft = old->curlft;
		newp->mark = old->mark;
		newp->if_id = old->if_id;
		newp->action = old->action;
		newp->flags = old->flags;
		newp->xfrm_nr = old->xfrm_nr;
Loading