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

Commit b59f45d0 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[IPSEC] xfrm: Abstract out encapsulation modes



This patch adds the structure xfrm_mode.  It is meant to represent
the operations carried out by transport/tunnel modes.

By doing this we allow additional encapsulation modes to be added
without clogging up the xfrm_input/xfrm_output paths.

Candidate modes include 4-to-6 tunnel mode, 6-to-4 tunnel mode, and
BEET modes.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 546be240
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -118,6 +118,10 @@ enum
	XFRM_SHARE_UNIQUE	/* Use once */
};

#define XFRM_MODE_TRANSPORT 0
#define XFRM_MODE_TUNNEL 1
#define XFRM_MODE_MAX 2

/* Netlink configuration messages.  */
enum {
	XFRM_MSG_BASE = 0x10,
+17 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <net/ip6_fib.h>

#define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
#define MODULE_ALIAS_XFRM_MODE(family, encap) \
	MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))

extern struct sock *xfrm_nl;
extern u32 sysctl_xfrm_aevent_etime;
@@ -164,6 +166,7 @@ struct xfrm_state
	/* Reference to data common to all the instances of this
	 * transformer. */
	struct xfrm_type	*type;
	struct xfrm_mode	*mode;

	/* Security context */
	struct xfrm_sec_ctx	*security;
@@ -205,6 +208,7 @@ struct xfrm_dst;
struct xfrm_policy_afinfo {
	unsigned short		family;
	struct xfrm_type	*type_map[256];
	struct xfrm_mode	*mode_map[XFRM_MODE_MAX];
	struct dst_ops		*dst_ops;
	void			(*garbage_collect)(void);
	int			(*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -267,6 +271,19 @@ extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
extern void xfrm_put_type(struct xfrm_type *type);

struct xfrm_mode {
	int (*input)(struct xfrm_state *x, struct sk_buff *skb);
	int (*output)(struct sk_buff *skb);

	struct module *owner;
	unsigned int encap;
};

extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
extern void xfrm_put_mode(struct xfrm_mode *mode);

struct xfrm_tmpl
{
/* id in template is interpreted as:
+18 −0
Original line number Diff line number Diff line
@@ -414,6 +414,24 @@ config INET_TUNNEL
	tristate
	default n

config INET_XFRM_MODE_TRANSPORT
	tristate "IP: IPsec transport mode"
	default y
	select XFRM
	---help---
	  Support for IPsec transport mode.

	  If unsure, say Y.

config INET_XFRM_MODE_TUNNEL
	tristate "IP: IPsec tunnel mode"
	default y
	select XFRM
	---help---
	  Support for IPsec tunnel mode.

	  If unsure, say Y.

config INET_DIAG
	tristate "INET: socket monitoring interface"
	default y
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
+2 −26
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
#include <linux/string.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>

@@ -24,15 +23,6 @@ int xfrm4_rcv(struct sk_buff *skb)

EXPORT_SYMBOL(xfrm4_rcv);

static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
{
	struct iphdr *outer_iph = skb->nh.iph;
	struct iphdr *inner_iph = skb->h.ipiph;

	if (INET_ECN_is_ce(outer_iph->tos))
		IP_ECN_set_ce(inner_iph);
}

static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
	switch (nexthdr) {
@@ -113,24 +103,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)

		xfrm_vec[xfrm_nr++] = x;

		iph = skb->nh.iph;
		if (x->mode->input(x, skb))
			goto drop;

		if (x->props.mode) {
			if (iph->protocol != IPPROTO_IPIP)
				goto drop;
			if (!pskb_may_pull(skb, sizeof(struct iphdr)))
				goto drop;
			if (skb_cloned(skb) &&
			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
				goto drop;
			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
				ipv4_copy_dscp(iph, skb->h.ipiph);
			if (!(x->props.flags & XFRM_STATE_NOECN))
				ipip_ecn_decapsulate(skb);
			skb->mac.raw = memmove(skb->data - skb->mac_len,
					       skb->mac.raw, skb->mac_len);
			skb->nh.raw = skb->data;
			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
			decaps = 1;
			break;
		}
Loading