/* Checkin full IP header plus 8 bytes of protocol to
         * avoid additional coding at protocol handlers.
         */
-       if (!pskb_may_pull(skb, iph->ihl * 4 + 8))
+       if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) {
+               ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
                return;
+       }
 
        raw_icmp_error(skb, protocol, info);
 
 
        int err;
        struct net *net = dev_net(icmp_skb->dev);
 
-       if (icmp_skb->len < (iph->ihl << 2) + 8) {
-               ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
-               return;
-       }
-
        sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest,
                        iph->saddr, th->source, inet_iif(icmp_skb));
        if (!sk) {
 
        int inner_offset;
        __be16 frag_off;
        u8 nexthdr;
+       struct net *net = dev_net(skb->dev);
 
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-               return;
+               goto out;
 
        nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
        if (ipv6_ext_hdr(nexthdr)) {
                inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
                                                &nexthdr, &frag_off);
                if (inner_offset<0)
-                       return;
+                       goto out;
        } else {
                inner_offset = sizeof(struct ipv6hdr);
        }
 
        /* Checkin header including 8 bytes of inner protocol header. */
        if (!pskb_may_pull(skb, inner_offset+8))
-               return;
+               goto out;
 
        /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
           Without this we will not able f.e. to make source routed
           --ANK (980726)
         */
 
-       rcu_read_lock();
        ipprot = rcu_dereference(inet6_protos[nexthdr]);
        if (ipprot && ipprot->err_handler)
                ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
-       rcu_read_unlock();
 
        raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
+       return;
+
+out:
+       ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
 }
 
 /*
 
        struct udphdr *uh = (struct udphdr*)(skb->data+offset);
        struct sock *sk;
        int err;
+       struct net *net = dev_net(skb->dev);
 
-       sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest,
+       sk = __udp6_lib_lookup(net, daddr, uh->dest,
                               saddr, uh->source, inet6_iif(skb), udptable);
-       if (sk == NULL)
+       if (sk == NULL) {
+               ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
+                                  ICMP6_MIB_INERRORS);
                return;
+       }
 
        if (type == ICMPV6_PKT_TOOBIG) {
                if (!ip6_sk_accept_pmtu(sk))
 
        int err;
        struct net *net = dev_net(skb->dev);
 
-       if (skb->len < ihlen + 8) {
-               ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
-               return;
-       }
-
        /* Fix up skb to look at the embedded net header. */
        saveip = skb->network_header;
        savesctp = skb->transport_header;