Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / net / ipv4 / esp4.c
index 10e809b296ec8644e108923c6faa1e4e2179bc20..fb065a8937ea28788f43a3906cbe08e3c0fc8c0d 100644 (file)
@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
        tail[plen - 1] = proto;
 }
 
-static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
+static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
 {
        int encap_type;
        struct udphdr *uh;
@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
        __be16 sport, dport;
        struct xfrm_encap_tmpl *encap = x->encap;
        struct ip_esp_hdr *esph = esp->esph;
+       unsigned int len;
 
        spin_lock_bh(&x->lock);
        sport = encap->encap_sport;
@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
        encap_type = encap->encap_type;
        spin_unlock_bh(&x->lock);
 
+       len = skb->len + esp->tailen - skb_transport_offset(skb);
+       if (len + sizeof(struct iphdr) >= IP_MAX_MTU)
+               return -EMSGSIZE;
+
        uh = (struct udphdr *)esph;
        uh->source = sport;
        uh->dest = dport;
-       uh->len = htons(skb->len + esp->tailen
-                 - skb_transport_offset(skb));
+       uh->len = htons(len);
        uh->check = 0;
 
        switch (encap_type) {
@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
 
        *skb_mac_header(skb) = IPPROTO_UDP;
        esp->esph = esph;
+
+       return 0;
 }
 
 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 *
        int tailen = esp->tailen;
 
        /* this is non-NULL only with UDP Encapsulation */
-       if (x->encap)
-               esp_output_udp_encap(x, skb, esp);
+       if (x->encap) {
+               int err = esp_output_udp_encap(x, skb, esp);
+
+               if (err < 0)
+                       return err;
+       }
 
        if (!skb_cloned(skb)) {
                if (tailen <= skb_tailroom(skb)) {