diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/route.c | 1 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 76 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 1 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 2 |
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 | } |
68 | EXPORT_SYMBOL(xfrm4_prepare_output); | 68 | EXPORT_SYMBOL(xfrm4_prepare_output); |
69 | 69 | ||
70 | static 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 | |||
81 | out_exit: | ||
82 | return err; | ||
83 | error_nolock: | ||
84 | kfree_skb(skb); | ||
85 | goto out_exit; | ||
86 | } | ||
87 | |||
88 | static 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 | |||
111 | static int xfrm4_output_finish(struct sk_buff *skb) | 70 | static 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 | ||
153 | int xfrm4_output(struct sk_buff *skb) | 85 | int 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 | ||
15 | static struct xfrm_state_afinfo xfrm4_state_afinfo; | 16 | static 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, |