diff options
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r-- | net/ipv4/icmp.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 36b7bfa609d6..36f5584d93c5 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -190,7 +190,7 @@ EXPORT_SYMBOL(icmp_err_convert); | |||
190 | */ | 190 | */ |
191 | 191 | ||
192 | struct icmp_control { | 192 | struct icmp_control { |
193 | void (*handler)(struct sk_buff *skb); | 193 | bool (*handler)(struct sk_buff *skb); |
194 | short error; /* This ICMP is classed as an error message */ | 194 | short error; /* This ICMP is classed as an error message */ |
195 | }; | 195 | }; |
196 | 196 | ||
@@ -746,7 +746,7 @@ static bool icmp_tag_validation(int proto) | |||
746 | * ICMP_PARAMETERPROB. | 746 | * ICMP_PARAMETERPROB. |
747 | */ | 747 | */ |
748 | 748 | ||
749 | static void icmp_unreach(struct sk_buff *skb) | 749 | static bool icmp_unreach(struct sk_buff *skb) |
750 | { | 750 | { |
751 | const struct iphdr *iph; | 751 | const struct iphdr *iph; |
752 | struct icmphdr *icmph; | 752 | struct icmphdr *icmph; |
@@ -839,10 +839,10 @@ static void icmp_unreach(struct sk_buff *skb) | |||
839 | icmp_socket_deliver(skb, info); | 839 | icmp_socket_deliver(skb, info); |
840 | 840 | ||
841 | out: | 841 | out: |
842 | return; | 842 | return true; |
843 | out_err: | 843 | out_err: |
844 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | 844 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
845 | goto out; | 845 | return false; |
846 | } | 846 | } |
847 | 847 | ||
848 | 848 | ||
@@ -850,17 +850,20 @@ out_err: | |||
850 | * Handle ICMP_REDIRECT. | 850 | * Handle ICMP_REDIRECT. |
851 | */ | 851 | */ |
852 | 852 | ||
853 | static void icmp_redirect(struct sk_buff *skb) | 853 | static bool icmp_redirect(struct sk_buff *skb) |
854 | { | 854 | { |
855 | if (skb->len < sizeof(struct iphdr)) { | 855 | if (skb->len < sizeof(struct iphdr)) { |
856 | ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); | 856 | ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); |
857 | return; | 857 | return false; |
858 | } | 858 | } |
859 | 859 | ||
860 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 860 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) { |
861 | return; | 861 | /* there aught to be a stat */ |
862 | return false; | ||
863 | } | ||
862 | 864 | ||
863 | icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway); | 865 | icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway); |
866 | return true; | ||
864 | } | 867 | } |
865 | 868 | ||
866 | /* | 869 | /* |
@@ -875,7 +878,7 @@ static void icmp_redirect(struct sk_buff *skb) | |||
875 | * See also WRT handling of options once they are done and working. | 878 | * See also WRT handling of options once they are done and working. |
876 | */ | 879 | */ |
877 | 880 | ||
878 | static void icmp_echo(struct sk_buff *skb) | 881 | static bool icmp_echo(struct sk_buff *skb) |
879 | { | 882 | { |
880 | struct net *net; | 883 | struct net *net; |
881 | 884 | ||
@@ -891,6 +894,8 @@ static void icmp_echo(struct sk_buff *skb) | |||
891 | icmp_param.head_len = sizeof(struct icmphdr); | 894 | icmp_param.head_len = sizeof(struct icmphdr); |
892 | icmp_reply(&icmp_param, skb); | 895 | icmp_reply(&icmp_param, skb); |
893 | } | 896 | } |
897 | /* should there be an ICMP stat for ignored echos? */ | ||
898 | return true; | ||
894 | } | 899 | } |
895 | 900 | ||
896 | /* | 901 | /* |
@@ -900,7 +905,7 @@ static void icmp_echo(struct sk_buff *skb) | |||
900 | * MUST be accurate to a few minutes. | 905 | * MUST be accurate to a few minutes. |
901 | * MUST be updated at least at 15Hz. | 906 | * MUST be updated at least at 15Hz. |
902 | */ | 907 | */ |
903 | static void icmp_timestamp(struct sk_buff *skb) | 908 | static bool icmp_timestamp(struct sk_buff *skb) |
904 | { | 909 | { |
905 | struct timespec tv; | 910 | struct timespec tv; |
906 | struct icmp_bxm icmp_param; | 911 | struct icmp_bxm icmp_param; |
@@ -927,15 +932,17 @@ static void icmp_timestamp(struct sk_buff *skb) | |||
927 | icmp_param.data_len = 0; | 932 | icmp_param.data_len = 0; |
928 | icmp_param.head_len = sizeof(struct icmphdr) + 12; | 933 | icmp_param.head_len = sizeof(struct icmphdr) + 12; |
929 | icmp_reply(&icmp_param, skb); | 934 | icmp_reply(&icmp_param, skb); |
930 | out: | 935 | return true; |
931 | return; | 936 | |
932 | out_err: | 937 | out_err: |
933 | ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); | 938 | ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); |
934 | goto out; | 939 | return false; |
935 | } | 940 | } |
936 | 941 | ||
937 | static void icmp_discard(struct sk_buff *skb) | 942 | static bool icmp_discard(struct sk_buff *skb) |
938 | { | 943 | { |
944 | /* pretend it was a success */ | ||
945 | return true; | ||
939 | } | 946 | } |
940 | 947 | ||
941 | /* | 948 | /* |
@@ -946,6 +953,7 @@ int icmp_rcv(struct sk_buff *skb) | |||
946 | struct icmphdr *icmph; | 953 | struct icmphdr *icmph; |
947 | struct rtable *rt = skb_rtable(skb); | 954 | struct rtable *rt = skb_rtable(skb); |
948 | struct net *net = dev_net(rt->dst.dev); | 955 | struct net *net = dev_net(rt->dst.dev); |
956 | bool success; | ||
949 | 957 | ||
950 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 958 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
951 | struct sec_path *sp = skb_sec_path(skb); | 959 | struct sec_path *sp = skb_sec_path(skb); |
@@ -1012,7 +1020,12 @@ int icmp_rcv(struct sk_buff *skb) | |||
1012 | } | 1020 | } |
1013 | } | 1021 | } |
1014 | 1022 | ||
1015 | icmp_pointers[icmph->type].handler(skb); | 1023 | success = icmp_pointers[icmph->type].handler(skb); |
1024 | |||
1025 | if (success) { | ||
1026 | consume_skb(skb); | ||
1027 | return 0; | ||
1028 | } | ||
1016 | 1029 | ||
1017 | drop: | 1030 | drop: |
1018 | kfree_skb(skb); | 1031 | kfree_skb(skb); |