Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 78102
b: refs/heads/master
c: 227620e
h: refs/heads/master
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jan 28, 2008
1 parent 1c95177 commit 7a58f04
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 100 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: 36cf9acf93e8561d9faec24849e57688a81eb9c5
refs/heads/master: 227620e295090629fcb2c46ad3828222ab65438d
27 changes: 27 additions & 0 deletions trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ extern int __xfrm_state_delete(struct xfrm_state *x);
struct xfrm_state_afinfo {
unsigned int family;
unsigned int proto;
unsigned int eth_proto;
struct module *owner;
struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
Expand All @@ -268,6 +269,8 @@ struct xfrm_state_afinfo {
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
int (*output)(struct sk_buff *skb);
int (*extract_input)(struct xfrm_state *x,
struct sk_buff *skb);
int (*extract_output)(struct xfrm_state *x,
struct sk_buff *skb);
};
Expand Down Expand Up @@ -302,6 +305,27 @@ extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);

struct xfrm_mode {
/*
* Remove encapsulation header.
*
* The IP header will be moved over the top of the encapsulation
* header.
*
* On entry, the transport header shall point to where the IP header
* should be and the network header shall be set to where the IP
* header currently is. skb->data shall point to the start of the
* payload.
*/
int (*input2)(struct xfrm_state *x, struct sk_buff *skb);

/*
* This is the actual input entry point.
*
* For transport mode and equivalent this would be identical to
* input2 (which does not need to be set). While tunnel mode
* and equivalent would set this to the tunnel encapsulation function
* xfrm4_prepare_input that would in turn call input2.
*/
int (*input)(struct xfrm_state *x, struct sk_buff *skb);

/*
Expand Down Expand Up @@ -1093,8 +1117,10 @@ extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_notify(struct xfrm_state *x, int event);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm_output(struct sk_buff *skb);
extern int xfrm4_extract_header(struct sk_buff *skb);
extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
int encap_type);
extern int xfrm4_rcv(struct sk_buff *skb);
Expand All @@ -1110,6 +1136,7 @@ extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm6_extract_header(struct sk_buff *skb);
extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
extern int xfrm6_rcv(struct sk_buff *skb);
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
Expand Down
7 changes: 6 additions & 1 deletion trunk/net/ipv4/xfrm4_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#include <net/ip.h>
#include <net/xfrm.h>

int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb)
{
return xfrm4_extract_header(skb);
}

#ifdef CONFIG_NETFILTER
static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
{
Expand Down Expand Up @@ -91,7 +96,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,

xfrm_vec[xfrm_nr++] = x;

if (x->outer_mode->input(x, skb))
if (x->inner_mode->input(x, skb))
goto drop;

if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
Expand Down
67 changes: 39 additions & 28 deletions trunk/net/ipv4/xfrm4_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
#include <net/ip.h>
#include <net/xfrm.h>

static void xfrm4_beet_make_header(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);

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

iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
iph->tos = XFRM_MODE_SKB_CB(skb)->tos;

iph->id = XFRM_MODE_SKB_CB(skb)->id;
iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
}

/* Add encapsulation header.
*
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
Expand All @@ -40,20 +55,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
offsetof(struct iphdr, protocol);
skb->transport_header = skb->network_header + sizeof(*iph);

xfrm4_beet_make_header(skb);

ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);

top_iph = ip_hdr(skb);

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

top_iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;

top_iph->id = XFRM_MODE_SKB_CB(skb)->id;
top_iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
top_iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;

if (unlikely(optlen)) {
BUG_ON(optlen < 0);

Expand All @@ -75,43 +82,46 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)

static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
int phlen = 0;
struct iphdr *iph;
int optlen = 0;
u8 ph_nexthdr = 0;
int err = -EINVAL;

if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
struct ip_beet_phdr *ph;
int phlen;

if (!pskb_may_pull(skb, sizeof(*ph)))
goto out;
ph = (struct ip_beet_phdr *)(ipip_hdr(skb) + 1);

ph = (struct ip_beet_phdr *)skb->data;

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

if (!pskb_may_pull(skb, phlen + optlen))
goto out;
skb->len -= phlen + optlen;
XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;

ph_nexthdr = ph->nexthdr;
if (!pskb_may_pull(skb, phlen));
goto out;
__skb_pull(skb, phlen);
}

skb_set_network_header(skb, phlen - sizeof(*iph));
memmove(skb_network_header(skb), iph, sizeof(*iph));
skb_set_transport_header(skb, phlen + optlen);
skb->data = skb_transport_header(skb);
skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);

memmove(skb->data - skb->mac_len, skb_mac_header(skb),
skb->mac_len);
skb_set_mac_header(skb, -skb->mac_len);

xfrm4_beet_make_header(skb);

iph = ip_hdr(skb);
iph->ihl = (sizeof(*iph) + optlen) / 4;
iph->tot_len = htons(skb->len + iph->ihl * 4);

iph->ihl += 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;
iph->check = 0;
iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
err = 0;
Expand All @@ -120,7 +130,8 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
}

static struct xfrm_mode xfrm4_beet_mode = {
.input = xfrm4_beet_input,
.input2 = xfrm4_beet_input,
.input = xfrm_prepare_input,
.output2 = xfrm4_beet_output,
.output = xfrm4_prepare_output,
.owner = THIS_MODULE,
Expand Down
44 changes: 10 additions & 34 deletions trunk/net/ipv4/xfrm4_mode_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@

static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
{
struct iphdr *outer_iph = ip_hdr(skb);
struct iphdr *inner_iph = ipip_hdr(skb);

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

static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
{
if (INET_ECN_is_ce(iph->tos))
IP6_ECN_set_ce(ipv6_hdr(skb));
}

/* Add encapsulation header.
*
* The top IP header will be constructed per RFC 2401.
Expand Down Expand Up @@ -72,20 +65,11 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)

static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
const unsigned char *old_mac;
int err = -EINVAL;

switch (iph->protocol){
case IPPROTO_IPIP:
break;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
case IPPROTO_IPV6:
break;
#endif
default:
goto out;
}
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
goto out;

if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto out;
Expand All @@ -94,20 +78,11 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
(err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto out;

iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_IPIP) {
if (x->props.flags & XFRM_STATE_DECAP_DSCP)
ipv4_copy_dscp(ipv4_get_dsfield(iph), ipip_hdr(skb));
if (!(x->props.flags & XFRM_STATE_NOECN))
ipip_ecn_decapsulate(skb);
}
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
else {
if (!(x->props.flags & XFRM_STATE_NOECN))
ipip6_ecn_decapsulate(iph, skb);
skb->protocol = htons(ETH_P_IPV6);
}
#endif
if (x->props.flags & XFRM_STATE_DECAP_DSCP)
ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb));
if (!(x->props.flags & XFRM_STATE_NOECN))
ipip_ecn_decapsulate(skb);

old_mac = skb_mac_header(skb);
skb_set_mac_header(skb, -skb->mac_len);
memmove(skb_mac_header(skb), old_mac, skb->mac_len);
Expand All @@ -119,7 +94,8 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
}

static struct xfrm_mode xfrm4_tunnel_mode = {
.input = xfrm4_tunnel_input,
.input2 = xfrm4_tunnel_input,
.input = xfrm_prepare_input,
.output2 = xfrm4_tunnel_output,
.output = xfrm4_prepare_output,
.owner = THIS_MODULE,
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/ipv4/xfrm4_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ int xfrm4_extract_header(struct sk_buff *skb)
static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
.proto = IPPROTO_IPIP,
.eth_proto = htons(ETH_P_IP),
.owner = THIS_MODULE,
.init_flags = xfrm4_init_flags,
.init_tempsel = __xfrm4_init_tempsel,
.output = xfrm4_output,
.extract_input = xfrm4_extract_input,
.extract_output = xfrm4_extract_output,
};

Expand Down
7 changes: 6 additions & 1 deletion trunk/net/ipv6/xfrm6_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#include <net/ipv6.h>
#include <net/xfrm.h>

int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
{
return xfrm6_extract_header(skb);
}

int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
{
int err;
Expand Down Expand Up @@ -68,7 +73,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)

xfrm_vec[xfrm_nr++] = x;

if (x->outer_mode->input(x, skb))
if (x->inner_mode->input(x, skb))
goto drop;

if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
Expand Down
36 changes: 24 additions & 12 deletions trunk/net/ipv6/xfrm6_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
#include <net/ipv6.h>
#include <net/xfrm.h>

static void xfrm6_beet_make_header(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);

iph->version = 6;

memcpy(iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
sizeof(iph->flow_lbl));
iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;

ipv6_change_dsfield(iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
}

/* Add encapsulation header.
*
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
Expand All @@ -31,16 +45,11 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
top_iph = ipv6_hdr(skb);

top_iph->version = 6;
xfrm6_beet_make_header(skb);

memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
sizeof(top_iph->flow_lbl));
top_iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;
top_iph = ipv6_hdr(skb);

ipv6_change_dsfield(top_iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
top_iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
return 0;
Expand All @@ -51,19 +60,21 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
struct ipv6hdr *ip6h;
const unsigned char *old_mac;
int size = sizeof(struct ipv6hdr);
int err = -EINVAL;
int err;

if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
err = skb_cow_head(skb, size + skb->mac_len);
if (err)
goto out;

skb_push(skb, size);
memmove(skb->data, skb_network_header(skb), size);
__skb_push(skb, size);
skb_reset_network_header(skb);

old_mac = skb_mac_header(skb);
skb_set_mac_header(skb, -skb->mac_len);
memmove(skb_mac_header(skb), old_mac, skb->mac_len);

xfrm6_beet_make_header(skb);

ip6h = ipv6_hdr(skb);
ip6h->payload_len = htons(skb->len - size);
ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);
Expand All @@ -74,7 +85,8 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
}

static struct xfrm_mode xfrm6_beet_mode = {
.input = xfrm6_beet_input,
.input2 = xfrm6_beet_input,
.input = xfrm_prepare_input,
.output2 = xfrm6_beet_output,
.output = xfrm6_prepare_output,
.owner = THIS_MODULE,
Expand Down
Loading

0 comments on commit 7a58f04

Please sign in to comment.