Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 27515
b: refs/heads/master
c: b59f45d
h: refs/heads/master
i:
  27513: ddda504
  27511: 4fa6069
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jun 18, 2006
1 parent 6b48546 commit ffda1cb
Show file tree
Hide file tree
Showing 18 changed files with 554 additions and 171 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 546be2405be119ef55467aace45f337a16e5d424
refs/heads/master: b59f45d0b2878ab76f8053b0973654e6621828ee
4 changes: 4 additions & 0 deletions trunk/include/linux/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions trunk/net/ipv4/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/ipv4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 2 additions & 26 deletions trunk/net/ipv4/xfrm4_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down
69 changes: 69 additions & 0 deletions trunk/net/ipv4/xfrm4_mode_transport.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
*
* Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
*/

#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 IP header will be moved forward to make space for the encapsulation
* header.
*
* 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_transport_output(struct sk_buff *skb)
{
struct xfrm_state *x;
struct iphdr *iph;
int ihl;

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

ihl = iph->ihl * 4;
skb->h.raw += ihl;

x = skb->dst->xfrm;
skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
return 0;
}

static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
{
return 0;
}

static struct xfrm_mode xfrm4_transport_mode = {
.input = xfrm4_transport_input,
.output = xfrm4_transport_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_TRANSPORT,
};

static int __init xfrm4_transport_init(void)
{
return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
}

static void __exit xfrm4_transport_exit(void)
{
int err;

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

module_init(xfrm4_transport_init);
module_exit(xfrm4_transport_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
125 changes: 125 additions & 0 deletions trunk/net/ipv4/xfrm4_mode_tunnel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
*
* Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
*/

#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/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>

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);
}

/* Add encapsulation header.
*
* The top IP header will be constructed per RFC 2401. 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_tunnel_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct iphdr *iph, *top_iph;
int flags;

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

skb->nh.raw = skb_push(skb, x->props.header_len);
top_iph = skb->nh.iph;

top_iph->ihl = 5;
top_iph->version = 4;

/* DS disclosed */
top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);

flags = x->props.flags;
if (flags & XFRM_STATE_NOECN)
IP_ECN_clear(top_iph);

top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
0 : (iph->frag_off & htons(IP_DF));
if (!top_iph->frag_off)
__ip_select_ident(top_iph, dst->child, 0);

top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);

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

memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
return 0;
}

static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = skb->nh.iph;
int err = -EINVAL;

if (iph->protocol != IPPROTO_IPIP)
goto out;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;

if (skb_cloned(skb) &&
(err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto out;

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));
err = 0;

out:
return err;
}

static struct xfrm_mode xfrm4_tunnel_mode = {
.input = xfrm4_tunnel_input,
.output = xfrm4_tunnel_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_TUNNEL,
};

static int __init xfrm4_tunnel_init(void)
{
return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
}

static void __exit xfrm4_tunnel_exit(void)
{
int err;

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

module_init(xfrm4_tunnel_init);
module_exit(xfrm4_tunnel_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
Loading

0 comments on commit ffda1cb

Please sign in to comment.