diff options
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r-- | net/ipv4/esp4.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 10e809b296ec..fb065a8937ea 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto) | |||
226 | tail[plen - 1] = proto; | 226 | tail[plen - 1] = proto; |
227 | } | 227 | } |
228 | 228 | ||
229 | static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) | 229 | static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) |
230 | { | 230 | { |
231 | int encap_type; | 231 | int encap_type; |
232 | struct udphdr *uh; | 232 | struct udphdr *uh; |
@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru | |||
234 | __be16 sport, dport; | 234 | __be16 sport, dport; |
235 | struct xfrm_encap_tmpl *encap = x->encap; | 235 | struct xfrm_encap_tmpl *encap = x->encap; |
236 | struct ip_esp_hdr *esph = esp->esph; | 236 | struct ip_esp_hdr *esph = esp->esph; |
237 | unsigned int len; | ||
237 | 238 | ||
238 | spin_lock_bh(&x->lock); | 239 | spin_lock_bh(&x->lock); |
239 | sport = encap->encap_sport; | 240 | sport = encap->encap_sport; |
@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru | |||
241 | encap_type = encap->encap_type; | 242 | encap_type = encap->encap_type; |
242 | spin_unlock_bh(&x->lock); | 243 | spin_unlock_bh(&x->lock); |
243 | 244 | ||
245 | len = skb->len + esp->tailen - skb_transport_offset(skb); | ||
246 | if (len + sizeof(struct iphdr) >= IP_MAX_MTU) | ||
247 | return -EMSGSIZE; | ||
248 | |||
244 | uh = (struct udphdr *)esph; | 249 | uh = (struct udphdr *)esph; |
245 | uh->source = sport; | 250 | uh->source = sport; |
246 | uh->dest = dport; | 251 | uh->dest = dport; |
247 | uh->len = htons(skb->len + esp->tailen | 252 | uh->len = htons(len); |
248 | - skb_transport_offset(skb)); | ||
249 | uh->check = 0; | 253 | uh->check = 0; |
250 | 254 | ||
251 | switch (encap_type) { | 255 | switch (encap_type) { |
@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru | |||
262 | 266 | ||
263 | *skb_mac_header(skb) = IPPROTO_UDP; | 267 | *skb_mac_header(skb) = IPPROTO_UDP; |
264 | esp->esph = esph; | 268 | esp->esph = esph; |
269 | |||
270 | return 0; | ||
265 | } | 271 | } |
266 | 272 | ||
267 | int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) | 273 | int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) |
@@ -275,8 +281,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * | |||
275 | int tailen = esp->tailen; | 281 | int tailen = esp->tailen; |
276 | 282 | ||
277 | /* this is non-NULL only with UDP Encapsulation */ | 283 | /* this is non-NULL only with UDP Encapsulation */ |
278 | if (x->encap) | 284 | if (x->encap) { |
279 | esp_output_udp_encap(x, skb, esp); | 285 | int err = esp_output_udp_encap(x, skb, esp); |
286 | |||
287 | if (err < 0) | ||
288 | return err; | ||
289 | } | ||
280 | 290 | ||
281 | if (!skb_cloned(skb)) { | 291 | if (!skb_cloned(skb)) { |
282 | if (tailen <= skb_tailroom(skb)) { | 292 | if (tailen <= skb_tailroom(skb)) { |