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

Commit f203b76d authored by Steffen Klassert's avatar Steffen Klassert
Browse files

xfrm: Add virtual xfrm interfaces



This patch adds support for virtual xfrm interfaces.
Packets that are routed through such an interface
are guaranteed to be IPsec transformed or dropped.
It is a generic virtual interface that ensures IPsec
transformation, no need to know what happens behind
the interface. This means that we can tunnel IPv4 and
IPv6 through the same interface and support all xfrm
modes (tunnel, transport and beet) on it.

Co-developed-by: default avatarLorenzo Colitti <lorenzo@google.com>
Co-developed-by: default avatarBenedict Wong <benedictwong@google.com>
Signed-off-by: default avatarLorenzo Colitti <lorenzo@google.com>
Signed-off-by: default avatarBenedict Wong <benedictwong@google.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Acked-by: default avatarShannon Nelson <shannon.nelson@oracle.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 7e652640
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/flow.h>
#include <net/gro_cells.h>

#include <linux/interrupt.h>

@@ -293,6 +294,13 @@ struct xfrm_replay {
	int	(*overflow)(struct xfrm_state *x, struct sk_buff *skb);
};

struct xfrm_if_cb {
	struct xfrm_if	*(*decode_session)(struct sk_buff *skb);
};

void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
void xfrm_if_unregister_cb(void);

struct net_device;
struct xfrm_type;
struct xfrm_dst;
@@ -1039,6 +1047,22 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)

void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);

struct xfrm_if_parms {
	char name[IFNAMSIZ];	/* name of XFRM device */
	int link;		/* ifindex of underlying L2 interface */
	u32 if_id;		/* interface identifyer */
};

struct xfrm_if {
	struct xfrm_if __rcu *next;	/* next interface in list */
	struct net_device *dev;		/* virtual device associated with interface */
	struct net_device *phydev;	/* physical device */
	struct net *net;		/* netns for packet i/o */
	struct xfrm_if_parms p;		/* interface parms */

	struct gro_cells gro_cells;
};

struct xfrm_offload {
	/* Output sequence number for replay protection on offloading. */
	struct {
+10 −0
Original line number Diff line number Diff line
@@ -459,6 +459,16 @@ enum {

#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)

/* XFRM section */
enum {
	IFLA_XFRM_UNSPEC,
	IFLA_XFRM_LINK,
	IFLA_XFRM_IF_ID,
	__IFLA_XFRM_MAX
};

#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)

enum macsec_validation_type {
	MACSEC_VALIDATE_DISABLED = 0,
	MACSEC_VALIDATE_CHECK = 1,
+8 −0
Original line number Diff line number Diff line
@@ -25,6 +25,14 @@ config XFRM_USER

	  If unsure, say Y.

config XFRM_INTERFACE
	tristate "Transformation virtual interface"
	depends on XFRM && IPV6
	---help---
	  This provides a virtual interface to route IPsec traffic.

	  If unsure, say N.

config XFRM_SUB_POLICY
	bool "Transformation sub policy support"
	depends on XFRM
+1 −0
Original line number Diff line number Diff line
@@ -10,3 +10,4 @@ obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
obj-$(CONFIG_XFRM_INTERFACE) += xfrm_interface.o
+3 −0
Original line number Diff line number Diff line
@@ -320,6 +320,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)

	seq = 0;
	if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
		secpath_reset(skb);
		XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
		goto drop;
	}
@@ -328,12 +329,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
				   XFRM_SPI_SKB_CB(skb)->daddroff);
	do {
		if (skb->sp->len == XFRM_MAX_DEPTH) {
			secpath_reset(skb);
			XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
			goto drop;
		}

		x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family);
		if (x == NULL) {
			secpath_reset(skb);
			XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
			xfrm_audit_state_notfound(skb, family, spi, seq);
			goto drop;
Loading