aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/route.c1
-rw-r--r--net/ipv4/xfrm4_output.c76
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv4/xfrm4_state.c2
4 files changed, 8 insertions, 72 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 137b8eb666b7..94ef788a2ac6 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -166,6 +166,7 @@ static struct dst_ops ipv4_dst_ops = {
166 .negative_advice = ipv4_negative_advice, 166 .negative_advice = ipv4_negative_advice,
167 .link_failure = ipv4_link_failure, 167 .link_failure = ipv4_link_failure,
168 .update_pmtu = ip_rt_update_pmtu, 168 .update_pmtu = ip_rt_update_pmtu,
169 .local_out = ip_local_out,
169 .entry_size = sizeof(struct rtable), 170 .entry_size = sizeof(struct rtable),
170}; 171};
171 172
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 0ffc3d078489..2fb4efa3ff2c 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -59,7 +59,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
59 return err; 59 return err;
60 60
61 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 61 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
62 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; 62 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
63 63
64 skb->protocol = htons(ETH_P_IP); 64 skb->protocol = htons(ETH_P_IP);
65 65
@@ -67,87 +67,19 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
67} 67}
68EXPORT_SYMBOL(xfrm4_prepare_output); 68EXPORT_SYMBOL(xfrm4_prepare_output);
69 69
70static inline int xfrm4_output_one(struct sk_buff *skb)
71{
72 int err;
73
74 err = xfrm_output(skb);
75 if (err)
76 goto error_nolock;
77
78 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
79 err = 0;
80
81out_exit:
82 return err;
83error_nolock:
84 kfree_skb(skb);
85 goto out_exit;
86}
87
88static int xfrm4_output_finish2(struct sk_buff *skb)
89{
90 int err;
91
92 while (likely((err = xfrm4_output_one(skb)) == 0)) {
93 nf_reset(skb);
94
95 err = __ip_local_out(skb);
96 if (unlikely(err != 1))
97 break;
98
99 if (!skb->dst->xfrm)
100 return dst_output(skb);
101
102 err = nf_hook(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
103 skb->dst->dev, xfrm4_output_finish2);
104 if (unlikely(err != 1))
105 break;
106 }
107
108 return err;
109}
110
111static int xfrm4_output_finish(struct sk_buff *skb) 70static int xfrm4_output_finish(struct sk_buff *skb)
112{ 71{
113 struct sk_buff *segs;
114
115#ifdef CONFIG_NETFILTER 72#ifdef CONFIG_NETFILTER
116 if (!skb->dst->xfrm) { 73 if (!skb->dst->xfrm) {
117 IPCB(skb)->flags |= IPSKB_REROUTED; 74 IPCB(skb)->flags |= IPSKB_REROUTED;
118 return dst_output(skb); 75 return dst_output(skb);
119 } 76 }
120#endif
121 77
122 if (!skb_is_gso(skb)) 78 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
123 return xfrm4_output_finish2(skb); 79#endif
124 80
125 skb->protocol = htons(ETH_P_IP); 81 skb->protocol = htons(ETH_P_IP);
126 segs = skb_gso_segment(skb, 0); 82 return xfrm_output(skb);
127 kfree_skb(skb);
128 if (unlikely(IS_ERR(segs)))
129 return PTR_ERR(segs);
130
131 do {
132 struct sk_buff *nskb = segs->next;
133 int err;
134
135 segs->next = NULL;
136 err = xfrm4_output_finish2(segs);
137
138 if (unlikely(err)) {
139 while ((segs = nskb)) {
140 nskb = segs->next;
141 segs->next = NULL;
142 kfree_skb(segs);
143 }
144 return err;
145 }
146
147 segs = nskb;
148 } while (segs);
149
150 return 0;
151} 83}
152 84
153int xfrm4_output(struct sk_buff *skb) 85int xfrm4_output(struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 1d7524375b49..b4948c170b3e 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -237,6 +237,7 @@ static struct dst_ops xfrm4_dst_ops = {
237 .update_pmtu = xfrm4_update_pmtu, 237 .update_pmtu = xfrm4_update_pmtu,
238 .destroy = xfrm4_dst_destroy, 238 .destroy = xfrm4_dst_destroy,
239 .ifdown = xfrm4_dst_ifdown, 239 .ifdown = xfrm4_dst_ifdown,
240 .local_out = __ip_local_out,
240 .gc_thresh = 1024, 241 .gc_thresh = 1024,
241 .entry_size = sizeof(struct xfrm_dst), 242 .entry_size = sizeof(struct xfrm_dst),
242}; 243};
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 85f04b7b237f..80292fbf221a 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -11,6 +11,7 @@
11#include <net/xfrm.h> 11#include <net/xfrm.h>
12#include <linux/pfkeyv2.h> 12#include <linux/pfkeyv2.h>
13#include <linux/ipsec.h> 13#include <linux/ipsec.h>
14#include <linux/netfilter_ipv4.h>
14 15
15static struct xfrm_state_afinfo xfrm4_state_afinfo; 16static struct xfrm_state_afinfo xfrm4_state_afinfo;
16 17
@@ -66,6 +67,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
66 .family = AF_INET, 67 .family = AF_INET,
67 .proto = IPPROTO_IPIP, 68 .proto = IPPROTO_IPIP,
68 .eth_proto = htons(ETH_P_IP), 69 .eth_proto = htons(ETH_P_IP),
70 .nf_post_routing = NF_IP_POST_ROUTING,
69 .owner = THIS_MODULE, 71 .owner = THIS_MODULE,
70 .init_flags = xfrm4_init_flags, 72 .init_flags = xfrm4_init_flags,
71 .init_tempsel = __xfrm4_init_tempsel, 73 .init_tempsel = __xfrm4_init_tempsel,