Blame view
net/ipv4/xfrm4_mode_tunnel.c
3.77 KB
b59f45d0b [IPSEC] xfrm: Abs... |
1 2 3 4 5 |
/* * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4. * * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> */ |
5a0e3ad6a include cleanup: ... |
6 |
#include <linux/gfp.h> |
b59f45d0b [IPSEC] xfrm: Abs... |
7 8 9 10 11 12 13 14 15 16 17 18 |
#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) { |
b0061ce49 [SK_BUFF]: Introd... |
19 |
struct iphdr *inner_iph = ipip_hdr(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
20 |
|
227620e29 [IPSEC]: Separate... |
21 |
if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos)) |
b59f45d0b [IPSEC] xfrm: Abs... |
22 23 24 25 26 |
IP_ECN_set_ce(inner_iph); } /* Add encapsulation header. * |
ceb1eec82 [IPSEC]: Move IP ... |
27 |
* The top IP header will be constructed per RFC 2401. |
b59f45d0b [IPSEC] xfrm: Abs... |
28 |
*/ |
195ad6a3a [IPSEC]: Rename t... |
29 |
static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) |
b59f45d0b [IPSEC] xfrm: Abs... |
30 |
{ |
adf30907d net: skb->dst acc... |
31 |
struct dst_entry *dst = skb_dst(skb); |
36cf9acf9 [IPSEC]: Separate... |
32 |
struct iphdr *top_iph; |
b59f45d0b [IPSEC] xfrm: Abs... |
33 |
int flags; |
f1bd7d659 xfrm: Add encapsu... |
34 35 |
skb_set_inner_network_header(skb, skb_network_offset(skb)); skb_set_inner_transport_header(skb, skb_transport_offset(skb)); |
7b277b1a5 [IPSEC]: Set skb-... |
36 |
skb_set_network_header(skb, -x->props.header_len); |
37fedd3aa [IPSEC]: Use IPv6... |
37 38 |
skb->mac_header = skb->network_header + offsetof(struct iphdr, protocol); |
36cf9acf9 [IPSEC]: Separate... |
39 |
skb->transport_header = skb->network_header + sizeof(*top_iph); |
eddc9ec53 [SK_BUFF]: Introd... |
40 |
top_iph = ip_hdr(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
41 42 43 |
top_iph->ihl = 5; top_iph->version = 4; |
adf30907d net: skb->dst acc... |
44 |
top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family); |
c82f963ef [IPSEC]: IPv6 ove... |
45 |
|
a947b0a93 xfrm: allow to av... |
46 47 48 49 50 51 |
/* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */ if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP) top_iph->tos = 0; else top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos; top_iph->tos = INET_ECN_encapsulate(top_iph->tos, |
36cf9acf9 [IPSEC]: Separate... |
52 |
XFRM_MODE_SKB_CB(skb)->tos); |
b59f45d0b [IPSEC] xfrm: Abs... |
53 |
|
36cf9acf9 [IPSEC]: Separate... |
54 |
flags = x->props.flags; |
b59f45d0b [IPSEC] xfrm: Abs... |
55 56 |
if (flags & XFRM_STATE_NOECN) IP_ECN_clear(top_iph); |
36cf9acf9 [IPSEC]: Separate... |
57 |
top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? |
fe833fca2 xfrm: fix fragmen... |
58 |
0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); |
b59f45d0b [IPSEC] xfrm: Abs... |
59 |
|
323e126f0 ipv4: Don't pre-s... |
60 |
top_iph->ttl = ip4_dst_hoplimit(dst->child); |
b59f45d0b [IPSEC] xfrm: Abs... |
61 62 63 |
top_iph->saddr = x->props.saddr.a4; top_iph->daddr = x->id.daddr.a4; |
b6a7719ae ipv4: hash net pt... |
64 |
ip_select_ident(dev_net(dst->dev), skb, NULL); |
b59f45d0b [IPSEC] xfrm: Abs... |
65 |
|
b59f45d0b [IPSEC] xfrm: Abs... |
66 67 |
return 0; } |
195ad6a3a [IPSEC]: Rename t... |
68 |
static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
b59f45d0b [IPSEC] xfrm: Abs... |
69 |
{ |
b59f45d0b [IPSEC] xfrm: Abs... |
70 |
int err = -EINVAL; |
227620e29 [IPSEC]: Separate... |
71 72 |
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) goto out; |
c82f963ef [IPSEC]: IPv6 ove... |
73 |
|
b59f45d0b [IPSEC] xfrm: Abs... |
74 75 |
if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; |
9aac22deb ip: fix warning i... |
76 77 |
err = skb_unclone(skb, GFP_ATOMIC); if (err) |
b59f45d0b [IPSEC] xfrm: Abs... |
78 |
goto out; |
227620e29 [IPSEC]: Separate... |
79 80 81 82 |
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); |
c1d2bbe1c [SK_BUFF]: Introd... |
83 |
skb_reset_network_header(skb); |
03606895c ipsec: be careful... |
84 |
skb_mac_header_rebuild(skb); |
b59f45d0b [IPSEC] xfrm: Abs... |
85 86 87 88 89 |
err = 0; out: return err; } |
c35fe4106 xfrm: Add mode ha... |
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
static struct sk_buff *xfrm4_mode_tunnel_gso_segment(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features) { __skb_push(skb, skb->mac_len); return skb_mac_gso_segment(skb, features); } static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb) { struct xfrm_offload *xo = xfrm_offload(skb); if (xo->flags & XFRM_GSO_SEGMENT) { skb->network_header = skb->network_header - x->props.header_len; skb->transport_header = skb->network_header + sizeof(struct iphdr); } skb_reset_mac_len(skb); pskb_pull(skb, skb->mac_len + x->props.header_len); } |
b59f45d0b [IPSEC] xfrm: Abs... |
112 |
static struct xfrm_mode xfrm4_tunnel_mode = { |
195ad6a3a [IPSEC]: Rename t... |
113 |
.input2 = xfrm4_mode_tunnel_input, |
227620e29 [IPSEC]: Separate... |
114 |
.input = xfrm_prepare_input, |
195ad6a3a [IPSEC]: Rename t... |
115 |
.output2 = xfrm4_mode_tunnel_output, |
36cf9acf9 [IPSEC]: Separate... |
116 |
.output = xfrm4_prepare_output, |
c35fe4106 xfrm: Add mode ha... |
117 118 |
.gso_segment = xfrm4_mode_tunnel_gso_segment, .xmit = xfrm4_mode_tunnel_xmit, |
b59f45d0b [IPSEC] xfrm: Abs... |
119 120 |
.owner = THIS_MODULE, .encap = XFRM_MODE_TUNNEL, |
1bfcb10f6 [IPSEC]: Add miss... |
121 |
.flags = XFRM_MODE_FLAG_TUNNEL, |
b59f45d0b [IPSEC] xfrm: Abs... |
122 |
}; |
195ad6a3a [IPSEC]: Rename t... |
123 |
static int __init xfrm4_mode_tunnel_init(void) |
b59f45d0b [IPSEC] xfrm: Abs... |
124 125 126 |
{ return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET); } |
195ad6a3a [IPSEC]: Rename t... |
127 |
static void __exit xfrm4_mode_tunnel_exit(void) |
b59f45d0b [IPSEC] xfrm: Abs... |
128 129 130 131 132 133 |
{ int err; err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET); BUG_ON(err); } |
195ad6a3a [IPSEC]: Rename t... |
134 135 |
module_init(xfrm4_mode_tunnel_init); module_exit(xfrm4_mode_tunnel_exit); |
b59f45d0b [IPSEC] xfrm: Abs... |
136 137 |
MODULE_LICENSE("GPL"); MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL); |