aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/xfrm4_mode_beet.c15
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c37
-rw-r--r--net/ipv4/xfrm4_output.c41
-rw-r--r--net/ipv4/xfrm4_state.c17
4 files changed, 71 insertions, 39 deletions
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index e42e122414be..94842adce144 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -43,7 +43,17 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
43 ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); 43 ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
44 44
45 top_iph = ip_hdr(skb); 45 top_iph = ip_hdr(skb);
46 memmove(top_iph, iph, sizeof(*iph)); 46
47 top_iph->ihl = 5;
48 top_iph->version = 4;
49
50 top_iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
51 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
52
53 top_iph->id = XFRM_MODE_SKB_CB(skb)->id;
54 top_iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
55 top_iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
56
47 if (unlikely(optlen)) { 57 if (unlikely(optlen)) {
48 BUG_ON(optlen < 0); 58 BUG_ON(optlen < 0);
49 59
@@ -111,7 +121,8 @@ out:
111 121
112static struct xfrm_mode xfrm4_beet_mode = { 122static struct xfrm_mode xfrm4_beet_mode = {
113 .input = xfrm4_beet_input, 123 .input = xfrm4_beet_input,
114 .output = xfrm4_beet_output, 124 .output2 = xfrm4_beet_output,
125 .output = xfrm4_prepare_output,
115 .owner = THIS_MODULE, 126 .owner = THIS_MODULE,
116 .encap = XFRM_MODE_BEET, 127 .encap = XFRM_MODE_BEET,
117 .flags = XFRM_MODE_FLAG_TUNNEL, 128 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 68a9f56ff09f..cc8bbb274e37 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -36,53 +36,37 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
36static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 36static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
37{ 37{
38 struct dst_entry *dst = skb->dst; 38 struct dst_entry *dst = skb->dst;
39 struct xfrm_dst *xdst = (struct xfrm_dst*)dst; 39 struct iphdr *top_iph;
40 struct iphdr *iph, *top_iph;
41 int flags; 40 int flags;
42 41
43 iph = ip_hdr(skb);
44
45 skb_set_network_header(skb, -x->props.header_len); 42 skb_set_network_header(skb, -x->props.header_len);
46 skb->mac_header = skb->network_header + 43 skb->mac_header = skb->network_header +
47 offsetof(struct iphdr, protocol); 44 offsetof(struct iphdr, protocol);
48 skb->transport_header = skb->network_header + sizeof(*iph); 45 skb->transport_header = skb->network_header + sizeof(*top_iph);
49 top_iph = ip_hdr(skb); 46 top_iph = ip_hdr(skb);
50 47
51 top_iph->ihl = 5; 48 top_iph->ihl = 5;
52 top_iph->version = 4; 49 top_iph->version = 4;
53 50
54 flags = x->props.flags; 51 top_iph->protocol = x->inner_mode->afinfo->proto;
55 52
56 /* DS disclosed */ 53 /* DS disclosed */
57 if (xdst->route->ops->family == AF_INET) { 54 top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos,
58 top_iph->protocol = IPPROTO_IPIP; 55 XFRM_MODE_SKB_CB(skb)->tos);
59 top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
60 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
61 0 : (iph->frag_off & htons(IP_DF));
62 }
63#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
64 else {
65 struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
66 top_iph->protocol = IPPROTO_IPV6;
67 top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
68 top_iph->frag_off = 0;
69 }
70#endif
71 56
57 flags = x->props.flags;
72 if (flags & XFRM_STATE_NOECN) 58 if (flags & XFRM_STATE_NOECN)
73 IP_ECN_clear(top_iph); 59 IP_ECN_clear(top_iph);
74 60
75 if (!top_iph->frag_off) 61 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
76 __ip_select_ident(top_iph, dst->child, 0); 62 0 : XFRM_MODE_SKB_CB(skb)->frag_off;
63 ip_select_ident(top_iph, dst->child, NULL);
77 64
78 top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); 65 top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
79 66
80 top_iph->saddr = x->props.saddr.a4; 67 top_iph->saddr = x->props.saddr.a4;
81 top_iph->daddr = x->id.daddr.a4; 68 top_iph->daddr = x->id.daddr.a4;
82 69
83 skb->protocol = htons(ETH_P_IP);
84
85 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
86 return 0; 70 return 0;
87} 71}
88 72
@@ -136,7 +120,8 @@ out:
136 120
137static struct xfrm_mode xfrm4_tunnel_mode = { 121static struct xfrm_mode xfrm4_tunnel_mode = {
138 .input = xfrm4_tunnel_input, 122 .input = xfrm4_tunnel_input,
139 .output = xfrm4_tunnel_output, 123 .output2 = xfrm4_tunnel_output,
124 .output = xfrm4_prepare_output,
140 .owner = THIS_MODULE, 125 .owner = THIS_MODULE,
141 .encap = XFRM_MODE_TUNNEL, 126 .encap = XFRM_MODE_TUNNEL,
142 .flags = XFRM_MODE_FLAG_TUNNEL, 127 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index c4a7156962bd..13fd11335e28 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -8,11 +8,12 @@
8 * 2 of the License, or (at your option) any later version. 8 * 2 of the License, or (at your option) any later version.
9 */ 9 */
10 10
11#include <linux/compiler.h>
12#include <linux/if_ether.h> 11#include <linux/if_ether.h>
13#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/netfilter_ipv4.h> 15#include <linux/netfilter_ipv4.h>
16#include <net/dst.h>
16#include <net/ip.h> 17#include <net/ip.h>
17#include <net/xfrm.h> 18#include <net/xfrm.h>
18#include <net/icmp.h> 19#include <net/icmp.h>
@@ -25,8 +26,6 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
25 if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE) 26 if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
26 goto out; 27 goto out;
27 28
28 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
29
30 if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df) 29 if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
31 goto out; 30 goto out;
32 31
@@ -40,19 +39,39 @@ out:
40 return ret; 39 return ret;
41} 40}
42 41
42int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
43{
44 int err;
45
46 err = xfrm4_tunnel_check_size(skb);
47 if (err)
48 return err;
49
50 return xfrm4_extract_header(skb);
51}
52
53int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
54{
55 int err;
56
57 err = x->inner_mode->afinfo->extract_output(x, skb);
58 if (err)
59 return err;
60
61 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
62 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
63
64 skb->protocol = htons(ETH_P_IP);
65
66 return x->outer_mode->output2(x, skb);
67}
68EXPORT_SYMBOL(xfrm4_prepare_output);
69
43static inline int xfrm4_output_one(struct sk_buff *skb) 70static inline int xfrm4_output_one(struct sk_buff *skb)
44{ 71{
45 struct dst_entry *dst = skb->dst;
46 struct xfrm_state *x = dst->xfrm;
47 struct iphdr *iph; 72 struct iphdr *iph;
48 int err; 73 int err;
49 74
50 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
51 err = xfrm4_tunnel_check_size(skb);
52 if (err)
53 goto error_nolock;
54 }
55
56 err = xfrm_output(skb); 75 err = xfrm_output(skb);
57 if (err) 76 if (err)
58 goto error_nolock; 77 goto error_nolock;
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 13d54a1c3337..e6030e74ff65 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -47,12 +47,29 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
47 x->props.family = AF_INET; 47 x->props.family = AF_INET;
48} 48}
49 49
50int xfrm4_extract_header(struct sk_buff *skb)
51{
52 struct iphdr *iph = ip_hdr(skb);
53
54 XFRM_MODE_SKB_CB(skb)->id = iph->id;
55 XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
56 XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
57 XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
58 XFRM_MODE_SKB_CB(skb)->protocol = iph->protocol;
59 memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
60 sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
61
62 return 0;
63}
64
50static struct xfrm_state_afinfo xfrm4_state_afinfo = { 65static struct xfrm_state_afinfo xfrm4_state_afinfo = {
51 .family = AF_INET, 66 .family = AF_INET,
67 .proto = IPPROTO_IPIP,
52 .owner = THIS_MODULE, 68 .owner = THIS_MODULE,
53 .init_flags = xfrm4_init_flags, 69 .init_flags = xfrm4_init_flags,
54 .init_tempsel = __xfrm4_init_tempsel, 70 .init_tempsel = __xfrm4_init_tempsel,
55 .output = xfrm4_output, 71 .output = xfrm4_output,
72 .extract_output = xfrm4_extract_output,
56}; 73};
57 74
58void __init xfrm4_state_init(void) 75void __init xfrm4_state_init(void)