Commit 3c2d19cb authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2020-07-30

Please note that I did the first time now --no-ff merges
of my testing branch into the master branch to include
the [PATCH 0/n] message of a patchset. Please let me
know if this is desirable, or if I should do it any
different.

1) Introduce a oseq-may-wrap flag to disable anti-replay
   protection for manually distributed ICVs as suggested
   in RFC 4303. From Petr Vaněk.

2) Patchset to fully support IPCOMP for vti4, vti6 and
   xfrm interfaces. From Xin Long.

3) Switch from a linear list to a hash list for xfrm interface
   lookups. From Eyal Birger.

4) Fixes to not register one xfrm(6)_tunnel object twice.
   From Xin Long.

5) Fix two compile errors that were introduced with the
   IPCOMP support for vti and xfrm interfaces.
   Also from Xin Long.

6) Make the policy hold queue work with VTI. This was
   forgotten when VTI was implemented.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 41d707b7 b328ecc4
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -374,7 +374,8 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family);

struct xfrm_input_afinfo {
	unsigned int		family;
	u8			family;
	bool			is_ipip;
	int			(*callback)(struct sk_buff *skb, u8 protocol,
					    int err);
};
@@ -1417,6 +1418,7 @@ struct xfrm6_protocol {
/* XFRM tunnel handlers.  */
struct xfrm_tunnel {
	int (*handler)(struct sk_buff *skb);
	int (*cb_handler)(struct sk_buff *skb, int err);
	int (*err_handler)(struct sk_buff *skb, u32 info);

	struct xfrm_tunnel __rcu *next;
@@ -1425,6 +1427,7 @@ struct xfrm_tunnel {

struct xfrm6_tunnel {
	int (*handler)(struct sk_buff *skb);
	int (*cb_handler)(struct sk_buff *skb, int err);
	int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
			   u8 type, u8 code, int offset, __be32 info);
	struct xfrm6_tunnel __rcu *next;
+1 −0
Original line number Diff line number Diff line
@@ -387,6 +387,7 @@ struct xfrm_usersa_info {
};

#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP	1
#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP	2

struct xfrm_usersa_id {
	xfrm_address_t			daddr;
+47 −33
Original line number Diff line number Diff line
@@ -91,32 +91,6 @@ static int vti_rcv_proto(struct sk_buff *skb)
	return vti_rcv(skb, 0, false);
}

static int vti_rcv_tunnel(struct sk_buff *skb)
{
	struct ip_tunnel_net *itn = net_generic(dev_net(skb->dev), vti_net_id);
	const struct iphdr *iph = ip_hdr(skb);
	struct ip_tunnel *tunnel;

	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
				  iph->saddr, iph->daddr, 0);
	if (tunnel) {
		struct tnl_ptk_info tpi = {
			.proto = htons(ETH_P_IP),
		};

		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
			goto drop;
		if (iptunnel_pull_header(skb, 0, tpi.proto, false))
			goto drop;
		return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, false);
	}

	return -EINVAL;
drop:
	kfree_skb(skb);
	return 0;
}

static int vti_rcv_cb(struct sk_buff *skb, int err)
{
	unsigned short family;
@@ -244,12 +218,15 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
	}

	dst_hold(dst);
	dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0);
	dst = xfrm_lookup_route(tunnel->net, dst, fl, NULL, 0);
	if (IS_ERR(dst)) {
		dev->stats.tx_carrier_errors++;
		goto tx_error_icmp;
	}

	if (dst->flags & DST_XFRM_QUEUE)
		goto queued;

	if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) {
		dev->stats.tx_carrier_errors++;
		dst_release(dst);
@@ -281,6 +258,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
		goto tx_error;
	}

queued:
	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
	skb_dst_set(skb, dst);
	skb->dev = skb_dst(skb)->dev;
@@ -496,12 +474,30 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
	.priority	=	100,
};

static struct xfrm_tunnel ipip_handler __read_mostly = {
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
static int vti_rcv_tunnel(struct sk_buff *skb)
{
	XFRM_SPI_SKB_CB(skb)->family = AF_INET;
	XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);

	return vti_input(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr, 0, false);
}

static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
	.handler	=	vti_rcv_tunnel,
	.cb_handler	=	vti_rcv_cb,
	.err_handler	=	vti4_err,
	.priority	=	0,
};

static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
	.handler	=	vti_rcv_tunnel,
	.cb_handler	=	vti_rcv_cb,
	.err_handler	=	vti4_err,
	.priority	=	0,
};
#endif

static int __net_init vti_init_net(struct net *net)
{
	int err;
@@ -670,10 +666,17 @@ static int __init vti_init(void)
	if (err < 0)
		goto xfrm_proto_comp_failed;

#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
	msg = "ipip tunnel";
	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
	err = xfrm4_tunnel_register(&vti_ipip_handler, AF_INET);
	if (err < 0)
		goto xfrm_tunnel_ipip_failed;
#if IS_ENABLED(CONFIG_IPV6)
	err = xfrm4_tunnel_register(&vti_ipip6_handler, AF_INET6);
	if (err < 0)
		goto xfrm_tunnel_failed;
		goto xfrm_tunnel_ipip6_failed;
#endif
#endif

	msg = "netlink interface";
	err = rtnl_link_register(&vti_link_ops);
@@ -683,8 +686,14 @@ static int __init vti_init(void)
	return err;

rtnl_link_failed:
	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
xfrm_tunnel_failed:
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
#if IS_ENABLED(CONFIG_IPV6)
	xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
xfrm_tunnel_ipip6_failed:
#endif
	xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
xfrm_tunnel_ipip_failed:
#endif
	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
xfrm_proto_comp_failed:
	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
@@ -700,7 +709,12 @@ pernet_dev_failed:
static void __exit vti_fini(void)
{
	rtnl_link_unregister(&vti_link_ops);
	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
#if IS_ENABLED(CONFIG_IPV6)
	xfrm4_tunnel_deregister(&vti_ipip6_handler, AF_INET6);
#endif
	xfrm4_tunnel_deregister(&vti_ipip_handler, AF_INET);
#endif
	xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
	xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
	xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP);
+1 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
	t->props.flags = x->props.flags;
	t->props.extra_flags = x->props.extra_flags;
	memcpy(&t->mark, &x->mark, sizeof(t->mark));
	t->if_id = x->if_id;

	if (xfrm_init_state(t))
		goto error;
+43 −0
Original line number Diff line number Diff line
@@ -110,6 +110,33 @@ drop:
	return 0;
}

#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
static int tunnel4_rcv_cb(struct sk_buff *skb, u8 proto, int err)
{
	struct xfrm_tunnel __rcu *head;
	struct xfrm_tunnel *handler;
	int ret;

	head = (proto == IPPROTO_IPIP) ? tunnel4_handlers : tunnel64_handlers;

	for_each_tunnel_rcu(head, handler) {
		if (handler->cb_handler) {
			ret = handler->cb_handler(skb, err);
			if (ret <= 0)
				return ret;
		}
	}

	return 0;
}

static const struct xfrm_input_afinfo tunnel4_input_afinfo = {
	.family		=	AF_INET,
	.is_ipip	=	true,
	.callback	=	tunnel4_rcv_cb,
};
#endif

#if IS_ENABLED(CONFIG_IPV6)
static int tunnel64_rcv(struct sk_buff *skb)
{
@@ -230,6 +257,18 @@ static int __init tunnel4_init(void)
#endif
		goto err;
	}
#endif
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
	if (xfrm_input_register_afinfo(&tunnel4_input_afinfo)) {
		inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
#if IS_ENABLED(CONFIG_IPV6)
		inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6);
#endif
#if IS_ENABLED(CONFIG_MPLS)
		inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS);
#endif
		goto err;
	}
#endif
	return 0;

@@ -240,6 +279,10 @@ err:

static void __exit tunnel4_fini(void)
{
#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
	if (xfrm_input_unregister_afinfo(&tunnel4_input_afinfo))
		pr_err("tunnel4 close: can't remove input afinfo\n");
#endif
#if IS_ENABLED(CONFIG_MPLS)
	if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
		pr_err("tunnelmpls4 close: can't remove protocol\n");
Loading