Skip to content

Commit

Permalink
[XFRM]: BEET mode
Browse files Browse the repository at this point in the history
This patch introduces the BEET mode (Bound End-to-End Tunnel) with as
specified by the ietf draft at the following link:

http://www.ietf.org/internet-drafts/draft-nikander-esp-beet-mode-06.txt

The patch provides only single family support (i.e. inner family =
outer family).

Signed-off-by: Diego Beltrami <[email protected]>
Signed-off-by: Miika Komu     <[email protected]>
Signed-off-by: Herbert Xu     <[email protected]>
Signed-off-by: Abhinav Pathak <[email protected]>
Signed-off-by: Jeff Ahrenholz <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
dbeltram authored and David S. Miller committed Oct 4, 2006
1 parent 80246ab commit 0a69452
Show file tree
Hide file tree
Showing 14 changed files with 309 additions and 11 deletions.
1 change: 1 addition & 0 deletions include/linux/in.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum {

IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
IPPROTO_AH = 51, /* Authentication Header protocol */
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */
IPPROTO_PIM = 103, /* Protocol Independent Multicast */

IPPROTO_COMP = 108, /* Compression Header protocol */
Expand Down
9 changes: 9 additions & 0 deletions include/linux/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */

#define IPV4_BEET_PHMAXLEN 8

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
Expand Down Expand Up @@ -123,4 +125,11 @@ struct ip_comp_hdr {
__be16 cpi;
};

struct ip_beet_phdr {
__u8 nexthdr;
__u8 hdrlen;
__u8 padlen;
__u8 reserved;
};

#endif /* _LINUX_IP_H */
3 changes: 2 additions & 1 deletion include/linux/ipsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
enum {
IPSEC_MODE_ANY = 0, /* We do not support this for SA */
IPSEC_MODE_TRANSPORT = 1,
IPSEC_MODE_TUNNEL = 2
IPSEC_MODE_TUNNEL = 2,
IPSEC_MODE_BEET = 3
};

enum {
Expand Down
3 changes: 2 additions & 1 deletion include/linux/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ enum
#define XFRM_MODE_TUNNEL 1
#define XFRM_MODE_ROUTEOPTIMIZATION 2
#define XFRM_MODE_IN_TRIGGER 3
#define XFRM_MODE_MAX 4
#define XFRM_MODE_BEET 4
#define XFRM_MODE_MAX 5

/* Netlink configuration messages. */
enum {
Expand Down
9 changes: 9 additions & 0 deletions net/ipv4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,15 @@ config INET_XFRM_MODE_TUNNEL

If unsure, say Y.

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

If unsure, say Y.

config INET_DIAG
tristate "INET: socket monitoring interface"
default y
Expand Down
1 change: 1 addition & 0 deletions net/ipv4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ obj-$(CONFIG_INET_AH) += ah4.o
obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.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
Expand Down
26 changes: 19 additions & 7 deletions net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
* as per draft-ietf-ipsec-udp-encaps-06,
* section 3.1.2
*/
if (x->props.mode == XFRM_MODE_TRANSPORT)
if (x->props.mode == XFRM_MODE_TRANSPORT ||
x->props.mode == XFRM_MODE_BEET)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}

Expand All @@ -271,17 +272,28 @@ static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
{
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);

if (x->props.mode == XFRM_MODE_TUNNEL) {
mtu = ALIGN(mtu + 2, blksize);
} else {
/* The worst case. */
int enclen = 0;

switch (x->props.mode) {
case XFRM_MODE_TUNNEL:
mtu = ALIGN(mtu +2, blksize);
break;
default:
case XFRM_MODE_TRANSPORT:
/* The worst case */
mtu = ALIGN(mtu + 2, 4) + blksize - 4;
break;
case XFRM_MODE_BEET:
/* The worst case. */
enclen = IPV4_BEET_PHMAXLEN;
mtu = ALIGN(mtu + enclen + 2, blksize);
break;
}

if (esp->conf.padlen)
mtu = ALIGN(mtu, esp->conf.padlen);

return mtu + x->props.header_len + esp->auth.icv_trunc_len;
return mtu + x->props.header_len + esp->auth.icv_trunc_len - enclen;
}

static void esp4_err(struct sk_buff *skb, u32 info)
Expand Down
5 changes: 4 additions & 1 deletion net/ipv4/ipcomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
{
struct xfrm_state *t;
u8 mode = XFRM_MODE_TUNNEL;

t = xfrm_state_alloc();
if (t == NULL)
Expand All @@ -216,7 +217,9 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t->id.daddr.a4 = x->id.daddr.a4;
memcpy(&t->sel, &x->sel, sizeof(t->sel));
t->props.family = AF_INET;
t->props.mode = XFRM_MODE_TUNNEL;
if (x->props.mode == XFRM_MODE_BEET)
mode = x->props.mode;
t->props.mode = mode;
t->props.saddr.a4 = x->props.saddr.a4;
t->props.flags = x->props.flags;

Expand Down
139 changes: 139 additions & 0 deletions net/ipv4/xfrm4_mode_beet.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* xfrm4_mode_beet.c - BEET mode encapsulation for IPv4.
*
* Copyright (c) 2006 Diego Beltrami <[email protected]>
* Miika Komu <[email protected]>
* Herbert Xu <[email protected]>
* Abhinav Pathak <[email protected]>
* Jeff Ahrenholz <[email protected]>
*/

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/stringify.h>
#include <net/dst.h>
#include <net/ip.h>
#include <net/xfrm.h>

/* Add encapsulation header.
*
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
* The following fields in it shall be filled in by x->type->output:
* tot_len
* check
*
* On exit, skb->h will be set to the start of the payload to be processed
* by x->type->output and skb->nh will be set to the top IP header.
*/
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph, *top_iph = NULL;
int hdrlen, optlen;

iph = skb->nh.iph;
skb->h.ipiph = iph;

hdrlen = 0;
optlen = iph->ihl * 4 - sizeof(*iph);
if (unlikely(optlen))
hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);

skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
top_iph = skb->nh.iph;
hdrlen = iph->ihl * 4 - optlen;
skb->h.raw += hdrlen;

memmove(top_iph, iph, hdrlen);
if (unlikely(optlen)) {
struct ip_beet_phdr *ph;

BUG_ON(optlen < 0);

ph = (struct ip_beet_phdr *)skb->h.raw;
ph->padlen = 4 - (optlen & 4);
ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
ph->nexthdr = top_iph->protocol;

top_iph->protocol = IPPROTO_BEETPH;
top_iph->ihl = sizeof(struct iphdr) / 4;
}

top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4;

return 0;
}

static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
int phlen = 0;
int optlen = 0;
__u8 ph_nexthdr = 0, protocol = 0;
int err = -EINVAL;

protocol = iph->protocol;

if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);

if (!pskb_may_pull(skb, sizeof(*ph)))
goto out;

phlen = ph->hdrlen * 8;
optlen = phlen - ph->padlen - sizeof(*ph);
if (optlen < 0 || optlen & 3 || optlen > 250)
goto out;

if (!pskb_may_pull(skb, phlen))
goto out;

ph_nexthdr = ph->nexthdr;
}

skb_push(skb, sizeof(*iph) - phlen + optlen);
memmove(skb->data, skb->nh.raw, sizeof(*iph));
skb->nh.raw = skb->data;

iph = skb->nh.iph;
iph->ihl = (sizeof(*iph) + optlen) / 4;
iph->tot_len = htons(skb->len);
iph->daddr = x->sel.daddr.a4;
iph->saddr = x->sel.saddr.a4;
if (ph_nexthdr)
iph->protocol = ph_nexthdr;
else
iph->protocol = protocol;
iph->check = 0;
iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
err = 0;
out:
return err;
}

static struct xfrm_mode xfrm4_beet_mode = {
.input = xfrm4_beet_input,
.output = xfrm4_beet_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_BEET,
};

static int __init xfrm4_beet_init(void)
{
return xfrm_register_mode(&xfrm4_beet_mode, AF_INET);
}

static void __exit xfrm4_beet_exit(void)
{
int err;

err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET);
BUG_ON(err);
}

module_init(xfrm4_beet_init);
module_exit(xfrm4_beet_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET);
10 changes: 10 additions & 0 deletions net/ipv6/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ config INET6_XFRM_MODE_TUNNEL

If unsure, say Y.

config INET6_XFRM_MODE_BEET
tristate "IPv6: IPsec BEET mode"
depends on IPV6
default IPV6
select XFRM
---help---
Support for IPsec BEET mode.

If unsure, say Y.

config INET6_XFRM_MODE_ROUTEOPTIMIZATION
tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
depends on IPV6 && EXPERIMENTAL
Expand Down
1 change: 1 addition & 0 deletions net/ipv6/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
obj-$(CONFIG_NETFILTER) += netfilter/

obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
Expand Down
5 changes: 4 additions & 1 deletion net/ipv6/ipcomp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
{
struct xfrm_state *t = NULL;
u8 mode = XFRM_MODE_TUNNEL;

t = xfrm_state_alloc();
if (!t)
Expand All @@ -212,7 +213,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
memcpy(&t->sel, &x->sel, sizeof(t->sel));
t->props.family = AF_INET6;
t->props.mode = XFRM_MODE_TUNNEL;
if (x->props.mode == XFRM_MODE_BEET)
mode = x->props.mode;
t->props.mode = mode;
memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));

if (xfrm_init_state(t))
Expand Down
Loading

0 comments on commit 0a69452

Please sign in to comment.