aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/icmp.c')
-rw-r--r--net/ipv4/icmp.c43
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
192struct icmp_control { 192struct 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
749static void icmp_unreach(struct sk_buff *skb) 749static 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
841out: 841out:
842 return; 842 return true;
843out_err: 843out_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
853static void icmp_redirect(struct sk_buff *skb) 853static 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
878static void icmp_echo(struct sk_buff *skb) 881static 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 */
903static void icmp_timestamp(struct sk_buff *skb) 908static 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);
930out: 935 return true;
931 return; 936
932out_err: 937out_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
937static void icmp_discard(struct sk_buff *skb) 942static 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
1017drop: 1030drop:
1018 kfree_skb(skb); 1031 kfree_skb(skb);