Blame view
net/ipv6/xfrm6_mode_tunnel.c
3.07 KB
b59f45d0b [IPSEC] xfrm: Abs... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6. * * Copyright (C) 2002 USAGI/WIDE Project * 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/dsfield.h> #include <net/dst.h> #include <net/inet_ecn.h> #include <net/ipv6.h> #include <net/xfrm.h> static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) { |
0660e03f6 [SK_BUFF]: Introd... |
21 |
struct ipv6hdr *outer_iph = ipv6_hdr(skb); |
39b89160d [SK_BUFF]: Introd... |
22 |
struct ipv6hdr *inner_iph = ipipv6_hdr(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
23 24 25 26 27 28 29 |
if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) IP6_ECN_set_ce(inner_iph); } /* Add encapsulation header. * |
ceb1eec82 [IPSEC]: Move IP ... |
30 |
* The top IP header will be constructed per RFC 2401. |
b59f45d0b [IPSEC] xfrm: Abs... |
31 |
*/ |
195ad6a3a [IPSEC]: Rename t... |
32 |
static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) |
b59f45d0b [IPSEC] xfrm: Abs... |
33 34 |
{ struct dst_entry *dst = skb->dst; |
36cf9acf9 [IPSEC]: Separate... |
35 |
struct ipv6hdr *top_iph; |
b59f45d0b [IPSEC] xfrm: Abs... |
36 |
int dsfield; |
7b277b1a5 [IPSEC]: Set skb-... |
37 |
skb_set_network_header(skb, -x->props.header_len); |
37fedd3aa [IPSEC]: Use IPv6... |
38 39 |
skb->mac_header = skb->network_header + offsetof(struct ipv6hdr, nexthdr); |
36cf9acf9 [IPSEC]: Separate... |
40 |
skb->transport_header = skb->network_header + sizeof(*top_iph); |
0660e03f6 [SK_BUFF]: Introd... |
41 |
top_iph = ipv6_hdr(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
42 43 |
top_iph->version = 6; |
36cf9acf9 [IPSEC]: Separate... |
44 45 46 |
memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl, sizeof(top_iph->flow_lbl)); |
df9dcb458 [IPSEC]: Fix inte... |
47 |
top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family); |
36cf9acf9 [IPSEC]: Separate... |
48 49 |
dsfield = XFRM_MODE_SKB_CB(skb)->tos; |
b59f45d0b [IPSEC] xfrm: Abs... |
50 51 52 53 |
dsfield = INET_ECN_encapsulate(dsfield, dsfield); if (x->props.flags & XFRM_STATE_NOECN) dsfield &= ~INET_ECN_MASK; ipv6_change_dsfield(top_iph, 0, dsfield); |
b59f45d0b [IPSEC] xfrm: Abs... |
54 55 56 57 58 |
top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); 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; } |
195ad6a3a [IPSEC]: Rename t... |
59 |
static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
b59f45d0b [IPSEC] xfrm: Abs... |
60 61 |
{ int err = -EINVAL; |
39f69c6f9 [SK_BUFF] xfrm: U... |
62 |
const unsigned char *old_mac; |
b59f45d0b [IPSEC] xfrm: Abs... |
63 |
|
227620e29 [IPSEC]: Separate... |
64 |
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
b59f45d0b [IPSEC] xfrm: Abs... |
65 66 67 68 69 70 71 |
goto out; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto out; if (skb_cloned(skb) && (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) goto out; |
227620e29 [IPSEC]: Separate... |
72 73 74 75 76 |
if (x->props.flags & XFRM_STATE_DECAP_DSCP) ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)), ipipv6_hdr(skb)); if (!(x->props.flags & XFRM_STATE_NOECN)) ipip6_ecn_decapsulate(skb); |
98e399f82 [SK_BUFF]: Introd... |
77 |
old_mac = skb_mac_header(skb); |
39f69c6f9 [SK_BUFF] xfrm: U... |
78 |
skb_set_mac_header(skb, -skb->mac_len); |
98e399f82 [SK_BUFF]: Introd... |
79 |
memmove(skb_mac_header(skb), old_mac, skb->mac_len); |
c1d2bbe1c [SK_BUFF]: Introd... |
80 |
skb_reset_network_header(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
81 82 83 84 85 86 87 |
err = 0; out: return err; } static struct xfrm_mode xfrm6_tunnel_mode = { |
195ad6a3a [IPSEC]: Rename t... |
88 |
.input2 = xfrm6_mode_tunnel_input, |
227620e29 [IPSEC]: Separate... |
89 |
.input = xfrm_prepare_input, |
195ad6a3a [IPSEC]: Rename t... |
90 |
.output2 = xfrm6_mode_tunnel_output, |
36cf9acf9 [IPSEC]: Separate... |
91 |
.output = xfrm6_prepare_output, |
b59f45d0b [IPSEC] xfrm: Abs... |
92 93 |
.owner = THIS_MODULE, .encap = XFRM_MODE_TUNNEL, |
1bfcb10f6 [IPSEC]: Add miss... |
94 |
.flags = XFRM_MODE_FLAG_TUNNEL, |
b59f45d0b [IPSEC] xfrm: Abs... |
95 |
}; |
195ad6a3a [IPSEC]: Rename t... |
96 |
static int __init xfrm6_mode_tunnel_init(void) |
b59f45d0b [IPSEC] xfrm: Abs... |
97 98 99 |
{ return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6); } |
195ad6a3a [IPSEC]: Rename t... |
100 |
static void __exit xfrm6_mode_tunnel_exit(void) |
b59f45d0b [IPSEC] xfrm: Abs... |
101 102 103 104 105 106 |
{ int err; err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6); BUG_ON(err); } |
195ad6a3a [IPSEC]: Rename t... |
107 108 |
module_init(xfrm6_mode_tunnel_init); module_exit(xfrm6_mode_tunnel_exit); |
b59f45d0b [IPSEC] xfrm: Abs... |
109 110 |
MODULE_LICENSE("GPL"); MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL); |