net: fix the counter ICMP_MIB_INERRORS/ICMP6_MIB_INERRORS
authorDuan Jiong <duanj.fnst@cn.fujitsu.com>
Thu, 31 Jul 2014 09:54:32 +0000 (17:54 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Aug 2014 05:04:18 +0000 (22:04 -0700)
When dealing with ICMPv[46] Error Message, function icmp_socket_deliver()
and icmpv6_notify() do some valid checks on packet's length, but then some
protocols check packet's length redaudantly. So remove those duplicated
statements, and increase counter ICMP_MIB_INERRORS/ICMP6_MIB_INERRORS in
function icmp_socket_deliver() and icmpv6_notify() respectively.

In addition, add missed counter in udp6/udplite6 when socket is NULL.

Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/icmp.c
net/ipv4/tcp_ipv4.c
net/ipv6/icmp.c
net/ipv6/udp.c
net/sctp/input.c

index 42b7bcf8045be90924d31ab26b7d4ff49b87cad9..092400ef88d08f85e6c3a2bfe4ff1ce7f15557c5 100644 (file)
@@ -663,8 +663,10 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
        /* 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);
 
index 1edc739b9da59e29decbc304e9c5dd037634bf09..d0ba39537d5cd9c5987046c6ff847b83145413a5 100644 (file)
@@ -344,11 +344,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 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) {
index f6c84a6eb2389c55f4abd55fefbd073c73743a2a..06ba3e58320ba45fc3856659e43afd952495db35 100644 (file)
@@ -626,9 +626,10 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
        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)) {
@@ -636,14 +637,14 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
                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
@@ -652,13 +653,15 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
           --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);
 }
 
 /*
index 5b6091de5868493c9beb6a160877a18e86ecf755..c6941a1ac97768b2b35bca68f8ac74531c855700 100644 (file)
@@ -533,11 +533,15 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        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))
index f2e2cbd2d7509503e2f677db654c2528d3de4849..c1b991294516fd1ef29de13cf24f06c1d63c8be2 100644 (file)
@@ -575,11 +575,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
        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;