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

Commit 42a7b32b authored by David Ahern's avatar David Ahern Committed by Steffen Klassert
Browse files

xfrm: Add oif to dst lookups



Rules can be installed that direct route lookups to specific tables based
on oif. Plumb the oif through the xfrm lookups so it gets set in the flow
struct and passed to the resolver routines.

Signed-off-by: default avatarDavid Ahern <dsa@cumulusnetworks.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent df367561
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -285,10 +285,13 @@ struct xfrm_policy_afinfo {
	unsigned short		family;
	unsigned short		family;
	struct dst_ops		*dst_ops;
	struct dst_ops		*dst_ops;
	void			(*garbage_collect)(struct net *net);
	void			(*garbage_collect)(struct net *net);
	struct dst_entry	*(*dst_lookup)(struct net *net, int tos,
	struct dst_entry	*(*dst_lookup)(struct net *net,
					       int tos, int oif,
					       const xfrm_address_t *saddr,
					       const xfrm_address_t *saddr,
					       const xfrm_address_t *daddr);
					       const xfrm_address_t *daddr);
	int			(*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
	int			(*get_saddr)(struct net *net, int oif,
					     xfrm_address_t *saddr,
					     xfrm_address_t *daddr);
	void			(*decode_session)(struct sk_buff *skb,
	void			(*decode_session)(struct sk_buff *skb,
						  struct flowi *fl,
						  struct flowi *fl,
						  int reverse);
						  int reverse);
+6 −5
Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@
static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
static struct xfrm_policy_afinfo xfrm4_policy_afinfo;


static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
					    int tos,
					    int tos, int oif,
					    const xfrm_address_t *saddr,
					    const xfrm_address_t *saddr,
					    const xfrm_address_t *daddr)
					    const xfrm_address_t *daddr)
{
{
@@ -28,6 +28,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
	memset(fl4, 0, sizeof(*fl4));
	memset(fl4, 0, sizeof(*fl4));
	fl4->daddr = daddr->a4;
	fl4->daddr = daddr->a4;
	fl4->flowi4_tos = tos;
	fl4->flowi4_tos = tos;
	fl4->flowi4_oif = oif;
	if (saddr)
	if (saddr)
		fl4->saddr = saddr->a4;
		fl4->saddr = saddr->a4;


@@ -38,22 +39,22 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
	return ERR_CAST(rt);
	return ERR_CAST(rt);
}
}


static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *daddr)
					  const xfrm_address_t *daddr)
{
{
	struct flowi4 fl4;
	struct flowi4 fl4;


	return __xfrm4_dst_lookup(net, &fl4, tos, saddr, daddr);
	return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr);
}
}


static int xfrm4_get_saddr(struct net *net,
static int xfrm4_get_saddr(struct net *net, int oif,
			   xfrm_address_t *saddr, xfrm_address_t *daddr)
			   xfrm_address_t *saddr, xfrm_address_t *daddr)
{
{
	struct dst_entry *dst;
	struct dst_entry *dst;
	struct flowi4 fl4;
	struct flowi4 fl4;


	dst = __xfrm4_dst_lookup(net, &fl4, 0, NULL, daddr);
	dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr);
	if (IS_ERR(dst))
	if (IS_ERR(dst))
		return -EHOSTUNREACH;
		return -EHOSTUNREACH;


+4 −3
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@


static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
static struct xfrm_policy_afinfo xfrm6_policy_afinfo;


static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *daddr)
					  const xfrm_address_t *daddr)
{
{
@@ -35,6 +35,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
	int err;
	int err;


	memset(&fl6, 0, sizeof(fl6));
	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_oif = oif;
	memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
	memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
	if (saddr)
	if (saddr)
		memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
		memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -50,13 +51,13 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
	return dst;
	return dst;
}
}


static int xfrm6_get_saddr(struct net *net,
static int xfrm6_get_saddr(struct net *net, int oif,
			   xfrm_address_t *saddr, xfrm_address_t *daddr)
			   xfrm_address_t *saddr, xfrm_address_t *daddr)
{
{
	struct dst_entry *dst;
	struct dst_entry *dst;
	struct net_device *dev;
	struct net_device *dev;


	dst = xfrm6_dst_lookup(net, 0, NULL, daddr);
	dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);
	if (IS_ERR(dst))
	if (IS_ERR(dst))
		return -EHOSTUNREACH;
		return -EHOSTUNREACH;


+14 −10
Original line number Original line Diff line number Diff line
@@ -115,7 +115,8 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
	rcu_read_unlock();
	rcu_read_unlock();
}
}


static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
static inline struct dst_entry *__xfrm_dst_lookup(struct net *net,
						  int tos, int oif,
						  const xfrm_address_t *saddr,
						  const xfrm_address_t *saddr,
						  const xfrm_address_t *daddr,
						  const xfrm_address_t *daddr,
						  int family)
						  int family)
@@ -127,14 +128,15 @@ static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
	if (unlikely(afinfo == NULL))
	if (unlikely(afinfo == NULL))
		return ERR_PTR(-EAFNOSUPPORT);
		return ERR_PTR(-EAFNOSUPPORT);


	dst = afinfo->dst_lookup(net, tos, saddr, daddr);
	dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);


	xfrm_policy_put_afinfo(afinfo);
	xfrm_policy_put_afinfo(afinfo);


	return dst;
	return dst;
}
}


static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
						int tos, int oif,
						xfrm_address_t *prev_saddr,
						xfrm_address_t *prev_saddr,
						xfrm_address_t *prev_daddr,
						xfrm_address_t *prev_daddr,
						int family)
						int family)
@@ -153,7 +155,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
		daddr = x->coaddr;
		daddr = x->coaddr;
	}
	}


	dst = __xfrm_dst_lookup(net, tos, saddr, daddr, family);
	dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);


	if (!IS_ERR(dst)) {
	if (!IS_ERR(dst)) {
		if (prev_saddr != saddr)
		if (prev_saddr != saddr)
@@ -1373,15 +1375,15 @@ int __xfrm_sk_clone_policy(struct sock *sk)
}
}


static int
static int
xfrm_get_saddr(struct net *net, xfrm_address_t *local, xfrm_address_t *remote,
xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
	       unsigned short family)
	       xfrm_address_t *remote, unsigned short family)
{
{
	int err;
	int err;
	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);


	if (unlikely(afinfo == NULL))
	if (unlikely(afinfo == NULL))
		return -EINVAL;
		return -EINVAL;
	err = afinfo->get_saddr(net, local, remote);
	err = afinfo->get_saddr(net, oif, local, remote);
	xfrm_policy_put_afinfo(afinfo);
	xfrm_policy_put_afinfo(afinfo);
	return err;
	return err;
}
}
@@ -1410,7 +1412,9 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
			remote = &tmpl->id.daddr;
			remote = &tmpl->id.daddr;
			local = &tmpl->saddr;
			local = &tmpl->saddr;
			if (xfrm_addr_any(local, tmpl->encap_family)) {
			if (xfrm_addr_any(local, tmpl->encap_family)) {
				error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family);
				error = xfrm_get_saddr(net, fl->flowi_oif,
						       &tmp, remote,
						       tmpl->encap_family);
				if (error)
				if (error)
					goto fail;
					goto fail;
				local = &tmp;
				local = &tmp;
@@ -1690,8 +1694,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,


		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
			family = xfrm[i]->props.family;
			family = xfrm[i]->props.family;
			dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr,
			dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
					      family);
					      &saddr, &daddr, family);
			err = PTR_ERR(dst);
			err = PTR_ERR(dst);
			if (IS_ERR(dst))
			if (IS_ERR(dst))
				goto put_states;
				goto put_states;