diff options
author | Duan Jiong <duanj.fnst@cn.fujitsu.com> | 2014-07-31 05:54:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-01 01:04:18 -0400 |
commit | 7304fe4681634a8e0511a5922c972aa132ffb43d (patch) | |
tree | 97d39043b738e7cd135efcd242dc2430919da2da | |
parent | 299ee123e19889d511092347f5fc14db0f10e3a6 (diff) |
net: fix the counter ICMP_MIB_INERRORS/ICMP6_MIB_INERRORS
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>
-rw-r--r-- | net/ipv4/icmp.c | 4 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 13 | ||||
-rw-r--r-- | net/ipv6/udp.c | 8 | ||||
-rw-r--r-- | net/sctp/input.c | 5 |
5 files changed, 17 insertions, 18 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 42b7bcf8045b..092400ef88d0 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -663,8 +663,10 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) | |||
663 | /* Checkin full IP header plus 8 bytes of protocol to | 663 | /* Checkin full IP header plus 8 bytes of protocol to |
664 | * avoid additional coding at protocol handlers. | 664 | * avoid additional coding at protocol handlers. |
665 | */ | 665 | */ |
666 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) | 666 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { |
667 | ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); | ||
667 | return; | 668 | return; |
669 | } | ||
668 | 670 | ||
669 | raw_icmp_error(skb, protocol, info); | 671 | raw_icmp_error(skb, protocol, info); |
670 | 672 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1edc739b9da5..d0ba39537d5c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -344,11 +344,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
344 | int err; | 344 | int err; |
345 | struct net *net = dev_net(icmp_skb->dev); | 345 | struct net *net = dev_net(icmp_skb->dev); |
346 | 346 | ||
347 | if (icmp_skb->len < (iph->ihl << 2) + 8) { | ||
348 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | ||
349 | return; | ||
350 | } | ||
351 | |||
352 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, | 347 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, |
353 | iph->saddr, th->source, inet_iif(icmp_skb)); | 348 | iph->saddr, th->source, inet_iif(icmp_skb)); |
354 | if (!sk) { | 349 | if (!sk) { |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f6c84a6eb238..06ba3e58320b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -626,9 +626,10 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
626 | int inner_offset; | 626 | int inner_offset; |
627 | __be16 frag_off; | 627 | __be16 frag_off; |
628 | u8 nexthdr; | 628 | u8 nexthdr; |
629 | struct net *net = dev_net(skb->dev); | ||
629 | 630 | ||
630 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 631 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
631 | return; | 632 | goto out; |
632 | 633 | ||
633 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; | 634 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; |
634 | if (ipv6_ext_hdr(nexthdr)) { | 635 | if (ipv6_ext_hdr(nexthdr)) { |
@@ -636,14 +637,14 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
636 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), | 637 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), |
637 | &nexthdr, &frag_off); | 638 | &nexthdr, &frag_off); |
638 | if (inner_offset<0) | 639 | if (inner_offset<0) |
639 | return; | 640 | goto out; |
640 | } else { | 641 | } else { |
641 | inner_offset = sizeof(struct ipv6hdr); | 642 | inner_offset = sizeof(struct ipv6hdr); |
642 | } | 643 | } |
643 | 644 | ||
644 | /* Checkin header including 8 bytes of inner protocol header. */ | 645 | /* Checkin header including 8 bytes of inner protocol header. */ |
645 | if (!pskb_may_pull(skb, inner_offset+8)) | 646 | if (!pskb_may_pull(skb, inner_offset+8)) |
646 | return; | 647 | goto out; |
647 | 648 | ||
648 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 649 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
649 | Without this we will not able f.e. to make source routed | 650 | 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) | |||
652 | --ANK (980726) | 653 | --ANK (980726) |
653 | */ | 654 | */ |
654 | 655 | ||
655 | rcu_read_lock(); | ||
656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); | 656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); |
657 | if (ipprot && ipprot->err_handler) | 657 | if (ipprot && ipprot->err_handler) |
658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); | 658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); |
659 | rcu_read_unlock(); | ||
660 | 659 | ||
661 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); | 660 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); |
661 | return; | ||
662 | |||
663 | out: | ||
664 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | ||
662 | } | 665 | } |
663 | 666 | ||
664 | /* | 667 | /* |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5b6091de5868..c6941a1ac977 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -533,11 +533,15 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
533 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 533 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
534 | struct sock *sk; | 534 | struct sock *sk; |
535 | int err; | 535 | int err; |
536 | struct net *net = dev_net(skb->dev); | ||
536 | 537 | ||
537 | sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, | 538 | sk = __udp6_lib_lookup(net, daddr, uh->dest, |
538 | saddr, uh->source, inet6_iif(skb), udptable); | 539 | saddr, uh->source, inet6_iif(skb), udptable); |
539 | if (sk == NULL) | 540 | if (sk == NULL) { |
541 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), | ||
542 | ICMP6_MIB_INERRORS); | ||
540 | return; | 543 | return; |
544 | } | ||
541 | 545 | ||
542 | if (type == ICMPV6_PKT_TOOBIG) { | 546 | if (type == ICMPV6_PKT_TOOBIG) { |
543 | if (!ip6_sk_accept_pmtu(sk)) | 547 | if (!ip6_sk_accept_pmtu(sk)) |
diff --git a/net/sctp/input.c b/net/sctp/input.c index f2e2cbd2d750..c1b991294516 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -575,11 +575,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
575 | int err; | 575 | int err; |
576 | struct net *net = dev_net(skb->dev); | 576 | struct net *net = dev_net(skb->dev); |
577 | 577 | ||
578 | if (skb->len < ihlen + 8) { | ||
579 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | /* Fix up skb to look at the embedded net header. */ | 578 | /* Fix up skb to look at the embedded net header. */ |
584 | saveip = skb->network_header; | 579 | saveip = skb->network_header; |
585 | savesctp = skb->transport_header; | 580 | savesctp = skb->transport_header; |