Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 78101
b: refs/heads/master
c: 36cf9ac
h: refs/heads/master
i:
  78099: 10ec610
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jan 28, 2008
1 parent d867d5d commit 1c95177
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 85 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: 29bb43b4ec4e625b0659186fc8a7c8f8b7c81982
refs/heads/master: 36cf9acf93e8561d9faec24849e57688a81eb9c5
51 changes: 50 additions & 1 deletion trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ extern int __xfrm_state_delete(struct xfrm_state *x);

struct xfrm_state_afinfo {
unsigned int family;
unsigned int proto;
struct module *owner;
struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
Expand All @@ -267,6 +268,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_output)(struct xfrm_state *x,
struct sk_buff *skb);
};

extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
Expand Down Expand Up @@ -312,7 +315,18 @@ struct xfrm_mode {
* header. The value of the network header will always point
* to the top IP header while skb->data will point to the payload.
*/
int (*output)(struct xfrm_state *x,struct sk_buff *skb);
int (*output2)(struct xfrm_state *x,struct sk_buff *skb);

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

struct xfrm_state_afinfo *afinfo;
struct module *owner;
Expand Down Expand Up @@ -454,6 +468,35 @@ struct xfrm_skb_cb {

#define XFRM_SKB_CB(__skb) ((struct xfrm_skb_cb *)&((__skb)->cb[0]))

/*
* This structure is used by the afinfo prepare_input/prepare_output functions
* to transmit header information to the mode input/output functions.
*/
struct xfrm_mode_skb_cb {
union {
struct inet_skb_parm h4;
struct inet6_skb_parm h6;
} header;

/* Copied from header for IPv4, always set to zero and DF for IPv6. */
__be16 id;
__be16 frag_off;

/* TOS for IPv4, class for IPv6. */
u8 tos;

/* TTL for IPv4, hop limitfor IPv6. */
u8 ttl;

/* Protocol for IPv4, NH for IPv6. */
u8 protocol;

/* Used by IPv6 only, zero for IPv4. */
u8 flow_lbl[3];
};

#define XFRM_MODE_SKB_CB(__skb) ((struct xfrm_mode_skb_cb *)&((__skb)->cb[0]))

/* Audit Information */
struct xfrm_audit
{
Expand Down Expand Up @@ -1051,6 +1094,7 @@ 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_output(struct sk_buff *skb);
extern int xfrm4_extract_header(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 @@ -1060,9 +1104,12 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
}

extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
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_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 All @@ -1072,6 +1119,8 @@ extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short
extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm6_output(struct sk_buff *skb);
extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);
Expand Down
15 changes: 13 additions & 2 deletions trunk/net/ipv4/xfrm4_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,17 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);

top_iph = ip_hdr(skb);
memmove(top_iph, iph, sizeof(*iph));

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 Down Expand Up @@ -111,7 +121,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,
.output = xfrm4_beet_output,
.output2 = xfrm4_beet_output,
.output = xfrm4_prepare_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_BEET,
.flags = XFRM_MODE_FLAG_TUNNEL,
Expand Down
37 changes: 11 additions & 26 deletions trunk/net/ipv4/xfrm4_mode_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,53 +36,37 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
struct iphdr *iph, *top_iph;
struct iphdr *top_iph;
int flags;

iph = ip_hdr(skb);

skb_set_network_header(skb, -x->props.header_len);
skb->mac_header = skb->network_header +
offsetof(struct iphdr, protocol);
skb->transport_header = skb->network_header + sizeof(*iph);
skb->transport_header = skb->network_header + sizeof(*top_iph);
top_iph = ip_hdr(skb);

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

flags = x->props.flags;
top_iph->protocol = x->inner_mode->afinfo->proto;

/* DS disclosed */
if (xdst->route->ops->family == AF_INET) {
top_iph->protocol = IPPROTO_IPIP;
top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
0 : (iph->frag_off & htons(IP_DF));
}
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
else {
struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
top_iph->protocol = IPPROTO_IPV6;
top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
top_iph->frag_off = 0;
}
#endif
top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos,
XFRM_MODE_SKB_CB(skb)->tos);

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

if (!top_iph->frag_off)
__ip_select_ident(top_iph, dst->child, 0);
top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
0 : XFRM_MODE_SKB_CB(skb)->frag_off;
ip_select_ident(top_iph, dst->child, NULL);

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

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

skb->protocol = htons(ETH_P_IP);

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

Expand Down Expand Up @@ -136,7 +120,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,
.output = xfrm4_tunnel_output,
.output2 = xfrm4_tunnel_output,
.output = xfrm4_prepare_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_TUNNEL,
.flags = XFRM_MODE_FLAG_TUNNEL,
Expand Down
41 changes: 30 additions & 11 deletions trunk/net/ipv4/xfrm4_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
* 2 of the License, or (at your option) any later version.
*/

#include <linux/compiler.h>
#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4.h>
#include <net/dst.h>
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/icmp.h>
Expand All @@ -25,8 +26,6 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
goto out;

IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;

if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
goto out;

Expand All @@ -40,19 +39,39 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
return ret;
}

int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;

err = xfrm4_tunnel_check_size(skb);
if (err)
return err;

return xfrm4_extract_header(skb);
}

int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;

err = x->inner_mode->afinfo->extract_output(x, skb);
if (err)
return err;

memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;

skb->protocol = htons(ETH_P_IP);

return x->outer_mode->output2(x, skb);
}
EXPORT_SYMBOL(xfrm4_prepare_output);

static inline int xfrm4_output_one(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct iphdr *iph;
int err;

if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
err = xfrm4_tunnel_check_size(skb);
if (err)
goto error_nolock;
}

err = xfrm_output(skb);
if (err)
goto error_nolock;
Expand Down
17 changes: 17 additions & 0 deletions trunk/net/ipv4/xfrm4_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,29 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
x->props.family = AF_INET;
}

int xfrm4_extract_header(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);

XFRM_MODE_SKB_CB(skb)->id = iph->id;
XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
XFRM_MODE_SKB_CB(skb)->protocol = iph->protocol;
memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));

return 0;
}

static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
.proto = IPPROTO_IPIP,
.owner = THIS_MODULE,
.init_flags = xfrm4_init_flags,
.init_tempsel = __xfrm4_init_tempsel,
.output = xfrm4_output,
.extract_output = xfrm4_extract_output,
};

void __init xfrm4_state_init(void)
Expand Down
28 changes: 14 additions & 14 deletions trunk/net/ipv6/xfrm6_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,24 @@
*/
static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *iph, *top_iph;
u8 *prevhdr;
int hdr_len;
struct ipv6hdr *top_iph;

iph = ipv6_hdr(skb);

hdr_len = ip6_find_1stfragopt(skb, &prevhdr);

skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
skb->transport_header = skb->network_header + hdr_len;
__skb_pull(skb, hdr_len);

skb->mac_header = skb->network_header +
offsetof(struct ipv6hdr, nexthdr);
skb->transport_header = skb->network_header + sizeof(*top_iph);
top_iph = ipv6_hdr(skb);
memmove(top_iph, iph, hdr_len);

top_iph->version = 6;

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;

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 Down Expand Up @@ -76,7 +75,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,
.output = xfrm6_beet_output,
.output2 = xfrm6_beet_output,
.output = xfrm6_prepare_output,
.owner = THIS_MODULE,
.encap = XFRM_MODE_BEET,
.flags = XFRM_MODE_FLAG_TUNNEL,
Expand Down
Loading

0 comments on commit 1c95177

Please sign in to comment.