Merge tag 'for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[firefly-linux-kernel-4.4.55.git] / net / ipv6 / sit.c
index 60415711563f36ffc21a4ebed82349751c62bae4..3bd1bfc01f8523c9ad0e9698f24974fbf1cc5171 100644 (file)
@@ -527,9 +527,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                case ICMP_PORT_UNREACH:
                        /* Impossible event. */
                        return 0;
-               case ICMP_FRAG_NEEDED:
-                       /* Soft state for pmtu is maintained by IP core. */
-                       return 0;
                default:
                        /* All others are translated to HOST_UNREACH.
                           rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -542,6 +539,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                if (code != ICMP_EXC_TTL)
                        return 0;
                break;
+       case ICMP_REDIRECT:
+               break;
        }
 
        err = -ENOENT;
@@ -551,7 +550,23 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                                skb->dev,
                                iph->daddr,
                                iph->saddr);
-       if (t == NULL || t->parms.iph.daddr == 0)
+       if (t == NULL)
+               goto out;
+
+       if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
+               ipv4_update_pmtu(skb, dev_net(skb->dev), info,
+                                t->dev->ifindex, 0, IPPROTO_IPV6, 0);
+               err = 0;
+               goto out;
+       }
+       if (type == ICMP_REDIRECT) {
+               ipv4_redirect(skb, dev_net(skb->dev), t->dev->ifindex, 0,
+                             IPPROTO_IPV6, 0);
+               err = 0;
+               goto out;
+       }
+
+       if (t->parms.iph.daddr == 0)
                goto out;
 
        err = 0;
@@ -792,7 +807,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                }
 
                if (tunnel->parms.iph.daddr && skb_dst(skb))
-                       skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
+                       skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
                if (skb->len > mtu) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);