]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv6/ip6_output.c
ipv6: don't increase size when refragmenting forwarded ipv6 skbs
[karo-tx-linux.git] / net / ipv6 / ip6_output.c
index 61741676b987eb196b167a33acb25739403ed169..d5f7716662dbc361e93ebc443e72ee5fb7343b10 100644 (file)
@@ -564,18 +564,17 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
        /* We must not fragment if the socket is set to force MTU discovery
         * or if the skb it not generated by a local socket.
         */
-       if (unlikely(!skb->ignore_df && skb->len > mtu) ||
-                    (IP6CB(skb)->frag_max_size &&
-                     IP6CB(skb)->frag_max_size > mtu)) {
-               if (skb->sk && dst_allfrag(skb_dst(skb)))
-                       sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK);
+       if (unlikely(!skb->ignore_df && skb->len > mtu))
+               goto fail_toobig;
 
-               skb->dev = skb_dst(skb)->dev;
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-               IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
-                             IPSTATS_MIB_FRAGFAILS);
-               kfree_skb(skb);
-               return -EMSGSIZE;
+       if (IP6CB(skb)->frag_max_size) {
+               if (IP6CB(skb)->frag_max_size > mtu)
+                       goto fail_toobig;
+
+               /* don't send fragments larger than what we received */
+               mtu = IP6CB(skb)->frag_max_size;
+               if (mtu < IPV6_MIN_MTU)
+                       mtu = IPV6_MIN_MTU;
        }
 
        if (np && np->frag_size < mtu) {
@@ -813,6 +812,14 @@ slow_path:
        consume_skb(skb);
        return err;
 
+fail_toobig:
+       if (skb->sk && dst_allfrag(skb_dst(skb)))
+               sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK);
+
+       skb->dev = skb_dst(skb)->dev;
+       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+       err = -EMSGSIZE;
+
 fail:
        IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
                      IPSTATS_MIB_FRAGFAILS);