]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv6/sit.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / net / ipv6 / sit.c
index 0619ac70836d4ea5ed4e43a1f5c3ac1f870979c4..917a5cd4b8fc79bb129ba8a004d1a877decef354 100644 (file)
@@ -479,47 +479,12 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
        dev_put(dev);
 }
 
-/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
- * if sufficient data bytes are available
- */
-static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb)
-{
-       int ihl = ((const struct iphdr *)skb->data)->ihl*4;
-       struct rt6_info *rt;
-       struct sk_buff *skb2;
-
-       if (!pskb_may_pull(skb, ihl + sizeof(struct ipv6hdr) + 8))
-               return 1;
-
-       skb2 = skb_clone(skb, GFP_ATOMIC);
-
-       if (!skb2)
-               return 1;
-
-       skb_dst_drop(skb2);
-       skb_pull(skb2, ihl);
-       skb_reset_network_header(skb2);
-
-       rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
-
-       if (rt && rt->dst.dev)
-               skb2->dev = rt->dst.dev;
-
-       icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
-
-       if (rt)
-               ip6_rt_put(rt);
-
-       kfree_skb(skb2);
-
-       return 0;
-}
-
 static int ipip6_err(struct sk_buff *skb, u32 info)
 {
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
+       unsigned int data_len = 0;
        struct ip_tunnel *t;
        int err;
 
@@ -544,6 +509,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        case ICMP_TIME_EXCEEDED:
                if (code != ICMP_EXC_TTL)
                        return 0;
+               data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
                break;
        case ICMP_REDIRECT:
                break;
@@ -571,11 +537,11 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                goto out;
        }
 
-       if (t->parms.iph.daddr == 0)
+       err = 0;
+       if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
                goto out;
 
-       err = 0;
-       if (!ipip6_err_gen_icmpv6_unreach(skb))
+       if (t->parms.iph.daddr == 0)
                goto out;
 
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
@@ -825,9 +791,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        u8 protocol = IPPROTO_IPV6;
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
-       if (skb->protocol != htons(ETH_P_IPV6))
-               goto tx_error;
-
        if (tos == 1)
                tos = ipv6_get_dsfield(iph6);