Skip to content

Commit f203b76

Browse files
committed
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: Lorenzo Colitti <lorenzo@google.com> Co-developed-by: Benedict Wong <benedictwong@google.com> Signed-off-by: Lorenzo Colitti <lorenzo@google.com> Signed-off-by: Benedict Wong <benedictwong@google.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Acked-by: Shannon Nelson <shannon.nelson@oracle.com> Tested-by: Benedict Wong <benedictwong@google.com> Tested-by: Antony Antony <antony@phenome.org> Reviewed-by: Eyal Birger <eyal.birger@gmail.com>
1 parent 7e65264 commit f203b76

File tree

7 files changed

+1061
-0
lines changed

7 files changed

+1061
-0
lines changed

include/net/xfrm.h

+24
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <net/ipv6.h>
2424
#include <net/ip6_fib.h>
2525
#include <net/flow.h>
26+
#include <net/gro_cells.h>
2627

2728
#include <linux/interrupt.h>
2829

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

297+
struct xfrm_if_cb {
298+
struct xfrm_if *(*decode_session)(struct sk_buff *skb);
299+
};
300+
301+
void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
302+
void xfrm_if_unregister_cb(void);
303+
296304
struct net_device;
297305
struct xfrm_type;
298306
struct xfrm_dst;
@@ -1039,6 +1047,22 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
10391047

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

1050+
struct xfrm_if_parms {
1051+
char name[IFNAMSIZ]; /* name of XFRM device */
1052+
int link; /* ifindex of underlying L2 interface */
1053+
u32 if_id; /* interface identifyer */
1054+
};
1055+
1056+
struct xfrm_if {
1057+
struct xfrm_if __rcu *next; /* next interface in list */
1058+
struct net_device *dev; /* virtual device associated with interface */
1059+
struct net_device *phydev; /* physical device */
1060+
struct net *net; /* netns for packet i/o */
1061+
struct xfrm_if_parms p; /* interface parms */
1062+
1063+
struct gro_cells gro_cells;
1064+
};
1065+
10421066
struct xfrm_offload {
10431067
/* Output sequence number for replay protection on offloading. */
10441068
struct {

include/uapi/linux/if_link.h

+10
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,16 @@ enum {
459459

460460
#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)
461461

462+
/* XFRM section */
463+
enum {
464+
IFLA_XFRM_UNSPEC,
465+
IFLA_XFRM_LINK,
466+
IFLA_XFRM_IF_ID,
467+
__IFLA_XFRM_MAX
468+
};
469+
470+
#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
471+
462472
enum macsec_validation_type {
463473
MACSEC_VALIDATE_DISABLED = 0,
464474
MACSEC_VALIDATE_CHECK = 1,

net/xfrm/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ config XFRM_USER
2525

2626
If unsure, say Y.
2727

28+
config XFRM_INTERFACE
29+
tristate "Transformation virtual interface"
30+
depends on XFRM && IPV6
31+
---help---
32+
This provides a virtual interface to route IPsec traffic.
33+
34+
If unsure, say N.
35+
2836
config XFRM_SUB_POLICY
2937
bool "Transformation sub policy support"
3038
depends on XFRM

net/xfrm/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
1010
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
1111
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
1212
obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
13+
obj-$(CONFIG_XFRM_INTERFACE) += xfrm_interface.o

net/xfrm/xfrm_input.c

+3
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
320320

321321
seq = 0;
322322
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
323+
secpath_reset(skb);
323324
XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR);
324325
goto drop;
325326
}
@@ -328,12 +329,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
328329
XFRM_SPI_SKB_CB(skb)->daddroff);
329330
do {
330331
if (skb->sp->len == XFRM_MAX_DEPTH) {
332+
secpath_reset(skb);
331333
XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
332334
goto drop;
333335
}
334336

335337
x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family);
336338
if (x == NULL) {
339+
secpath_reset(skb);
337340
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
338341
xfrm_audit_state_notfound(skb, family, spi, seq);
339342
goto drop;

0 commit comments

Comments
 (0)