aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/snmp.h2
-rw-r--r--include/net/icmp.h8
-rw-r--r--include/net/snmp.h5
-rw-r--r--net/ipv4/af_inet.c6
-rw-r--r--net/ipv4/icmp.c53
-rw-r--r--net/ipv4/ip_output.c4
-rw-r--r--net/ipv4/proc.c120
-rw-r--r--net/ipv4/raw.c3
8 files changed, 123 insertions, 78 deletions
diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index 86977e31548..d8fd3ec4148 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -82,6 +82,8 @@ enum
82 __ICMP_MIB_MAX 82 __ICMP_MIB_MAX
83}; 83};
84 84
85#define __ICMPMSG_MIB_MAX 512 /* Out+In for all 8-bit ICMP types */
86
85/* icmp6 mib definitions */ 87/* icmp6 mib definitions */
86/* 88/*
87 * RFC 2466: ICMPv6-MIB 89 * RFC 2466: ICMPv6-MIB
diff --git a/include/net/icmp.h b/include/net/icmp.h
index dc09474efcf..9f7ef3c8bae 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -30,9 +30,16 @@ struct icmp_err {
30 30
31extern struct icmp_err icmp_err_convert[]; 31extern struct icmp_err icmp_err_convert[];
32DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics); 32DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics);
33DECLARE_SNMP_STAT(struct icmpmsg_mib, icmpmsg_statistics);
33#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field) 34#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
34#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field) 35#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
35#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field) 36#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)
37#define ICMPMSGOUT_INC_STATS(field) SNMP_INC_STATS(icmpmsg_statistics, field+256)
38#define ICMPMSGOUT_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpmsg_statistics, field+256)
39#define ICMPMSGOUT_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpmsg_statistics, field+256)
40#define ICMPMSGIN_INC_STATS(field) SNMP_INC_STATS(icmpmsg_statistics, field)
41#define ICMPMSGIN_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpmsg_statistics, field)
42#define ICMPMSGIN_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpmsg_statistics, field)
36 43
37struct dst_entry; 44struct dst_entry;
38struct net_proto_family; 45struct net_proto_family;
@@ -42,6 +49,7 @@ extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
42extern int icmp_rcv(struct sk_buff *skb); 49extern int icmp_rcv(struct sk_buff *skb);
43extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg); 50extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
44extern void icmp_init(struct net_proto_family *ops); 51extern void icmp_init(struct net_proto_family *ops);
52extern void icmp_out_count(unsigned char type);
45 53
46/* Move into dst.h ? */ 54/* Move into dst.h ? */
47extern int xrlim_allow(struct dst_entry *dst, int timeout); 55extern int xrlim_allow(struct dst_entry *dst, int timeout);
diff --git a/include/net/snmp.h b/include/net/snmp.h
index a566e11d2f9..ea206bff0dc 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -82,6 +82,11 @@ struct icmp_mib {
82 unsigned long mibs[ICMP_MIB_MAX]; 82 unsigned long mibs[ICMP_MIB_MAX];
83} __SNMP_MIB_ALIGN__; 83} __SNMP_MIB_ALIGN__;
84 84
85#define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX
86struct icmpmsg_mib {
87 unsigned long mibs[ICMPMSG_MIB_MAX];
88} __SNMP_MIB_ALIGN__;
89
85/* ICMP6 (IPv6-ICMP) */ 90/* ICMP6 (IPv6-ICMP) */
86#define ICMP6_MIB_MAX __ICMP6_MIB_MAX 91#define ICMP6_MIB_MAX __ICMP6_MIB_MAX
87struct icmpv6_mib { 92struct icmpv6_mib {
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e594a2c8966..621b128897d 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1302,6 +1302,10 @@ static int __init init_ipv4_mibs(void)
1302 sizeof(struct icmp_mib), 1302 sizeof(struct icmp_mib),
1303 __alignof__(struct icmp_mib)) < 0) 1303 __alignof__(struct icmp_mib)) < 0)
1304 goto err_icmp_mib; 1304 goto err_icmp_mib;
1305 if (snmp_mib_init((void **)icmpmsg_statistics,
1306 sizeof(struct icmpmsg_mib),
1307 __alignof__(struct icmpmsg_mib)) < 0)
1308 goto err_icmpmsg_mib;
1305 if (snmp_mib_init((void **)tcp_statistics, 1309 if (snmp_mib_init((void **)tcp_statistics,
1306 sizeof(struct tcp_mib), 1310 sizeof(struct tcp_mib),
1307 __alignof__(struct tcp_mib)) < 0) 1311 __alignof__(struct tcp_mib)) < 0)
@@ -1324,6 +1328,8 @@ err_udplite_mib:
1324err_udp_mib: 1328err_udp_mib:
1325 snmp_mib_free((void **)tcp_statistics); 1329 snmp_mib_free((void **)tcp_statistics);
1326err_tcp_mib: 1330err_tcp_mib:
1331 snmp_mib_free((void **)icmpmsg_statistics);
1332err_icmpmsg_mib:
1327 snmp_mib_free((void **)icmp_statistics); 1333 snmp_mib_free((void **)icmp_statistics);
1328err_icmp_mib: 1334err_icmp_mib:
1329 snmp_mib_free((void **)ip_statistics); 1335 snmp_mib_free((void **)ip_statistics);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 68a22670f59..272c69e106e 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -115,6 +115,7 @@ struct icmp_bxm {
115 * Statistics 115 * Statistics
116 */ 116 */
117DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics) __read_mostly; 117DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics) __read_mostly;
118DEFINE_SNMP_STAT(struct icmpmsg_mib, icmpmsg_statistics) __read_mostly;
118 119
119/* An array of errno for error messages from dest unreach. */ 120/* An array of errno for error messages from dest unreach. */
120/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */ 121/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
@@ -214,8 +215,6 @@ int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
214 */ 215 */
215 216
216struct icmp_control { 217struct icmp_control {
217 int output_entry; /* Field for increment on output */
218 int input_entry; /* Field for increment on input */
219 void (*handler)(struct sk_buff *skb); 218 void (*handler)(struct sk_buff *skb);
220 short error; /* This ICMP is classed as an error message */ 219 short error; /* This ICMP is classed as an error message */
221}; 220};
@@ -316,12 +315,10 @@ out:
316/* 315/*
317 * Maintain the counters used in the SNMP statistics for outgoing ICMP 316 * Maintain the counters used in the SNMP statistics for outgoing ICMP
318 */ 317 */
319static void icmp_out_count(int type) 318void icmp_out_count(unsigned char type)
320{ 319{
321 if (type <= NR_ICMP_TYPES) { 320 ICMPMSGOUT_INC_STATS(type);
322 ICMP_INC_STATS(icmp_pointers[type].output_entry); 321 ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
323 ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
324 }
325} 322}
326 323
327/* 324/*
@@ -390,7 +387,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
390 return; 387 return;
391 388
392 icmp_param->data.icmph.checksum = 0; 389 icmp_param->data.icmph.checksum = 0;
393 icmp_out_count(icmp_param->data.icmph.type);
394 390
395 inet->tos = ip_hdr(skb)->tos; 391 inet->tos = ip_hdr(skb)->tos;
396 daddr = ipc.addr = rt->rt_src; 392 daddr = ipc.addr = rt->rt_src;
@@ -952,6 +948,7 @@ int icmp_rcv(struct sk_buff *skb)
952 948
953 icmph = icmp_hdr(skb); 949 icmph = icmp_hdr(skb);
954 950
951 ICMPMSGIN_INC_STATS_BH(icmph->type);
955 /* 952 /*
956 * 18 is the highest 'known' ICMP type. Anything else is a mystery 953 * 18 is the highest 'known' ICMP type. Anything else is a mystery
957 * 954 *
@@ -986,7 +983,6 @@ int icmp_rcv(struct sk_buff *skb)
986 } 983 }
987 } 984 }
988 985
989 ICMP_INC_STATS_BH(icmp_pointers[icmph->type].input_entry);
990 icmp_pointers[icmph->type].handler(skb); 986 icmp_pointers[icmph->type].handler(skb);
991 987
992drop: 988drop:
@@ -1002,109 +998,71 @@ error:
1002 */ 998 */
1003static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { 999static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
1004 [ICMP_ECHOREPLY] = { 1000 [ICMP_ECHOREPLY] = {
1005 .output_entry = ICMP_MIB_OUTECHOREPS,
1006 .input_entry = ICMP_MIB_INECHOREPS,
1007 .handler = icmp_discard, 1001 .handler = icmp_discard,
1008 }, 1002 },
1009 [1] = { 1003 [1] = {
1010 .output_entry = ICMP_MIB_DUMMY,
1011 .input_entry = ICMP_MIB_INERRORS,
1012 .handler = icmp_discard, 1004 .handler = icmp_discard,
1013 .error = 1, 1005 .error = 1,
1014 }, 1006 },
1015 [2] = { 1007 [2] = {
1016 .output_entry = ICMP_MIB_DUMMY,
1017 .input_entry = ICMP_MIB_INERRORS,
1018 .handler = icmp_discard, 1008 .handler = icmp_discard,
1019 .error = 1, 1009 .error = 1,
1020 }, 1010 },
1021 [ICMP_DEST_UNREACH] = { 1011 [ICMP_DEST_UNREACH] = {
1022 .output_entry = ICMP_MIB_OUTDESTUNREACHS,
1023 .input_entry = ICMP_MIB_INDESTUNREACHS,
1024 .handler = icmp_unreach, 1012 .handler = icmp_unreach,
1025 .error = 1, 1013 .error = 1,
1026 }, 1014 },
1027 [ICMP_SOURCE_QUENCH] = { 1015 [ICMP_SOURCE_QUENCH] = {
1028 .output_entry = ICMP_MIB_OUTSRCQUENCHS,
1029 .input_entry = ICMP_MIB_INSRCQUENCHS,
1030 .handler = icmp_unreach, 1016 .handler = icmp_unreach,
1031 .error = 1, 1017 .error = 1,
1032 }, 1018 },
1033 [ICMP_REDIRECT] = { 1019 [ICMP_REDIRECT] = {
1034 .output_entry = ICMP_MIB_OUTREDIRECTS,
1035 .input_entry = ICMP_MIB_INREDIRECTS,
1036 .handler = icmp_redirect, 1020 .handler = icmp_redirect,
1037 .error = 1, 1021 .error = 1,
1038 }, 1022 },
1039 [6] = { 1023 [6] = {
1040 .output_entry = ICMP_MIB_DUMMY,
1041 .input_entry = ICMP_MIB_INERRORS,
1042 .handler = icmp_discard, 1024 .handler = icmp_discard,
1043 .error = 1, 1025 .error = 1,
1044 }, 1026 },
1045 [7] = { 1027 [7] = {
1046 .output_entry = ICMP_MIB_DUMMY,
1047 .input_entry = ICMP_MIB_INERRORS,
1048 .handler = icmp_discard, 1028 .handler = icmp_discard,
1049 .error = 1, 1029 .error = 1,
1050 }, 1030 },
1051 [ICMP_ECHO] = { 1031 [ICMP_ECHO] = {
1052 .output_entry = ICMP_MIB_OUTECHOS,
1053 .input_entry = ICMP_MIB_INECHOS,
1054 .handler = icmp_echo, 1032 .handler = icmp_echo,
1055 }, 1033 },
1056 [9] = { 1034 [9] = {
1057 .output_entry = ICMP_MIB_DUMMY,
1058 .input_entry = ICMP_MIB_INERRORS,
1059 .handler = icmp_discard, 1035 .handler = icmp_discard,
1060 .error = 1, 1036 .error = 1,
1061 }, 1037 },
1062 [10] = { 1038 [10] = {
1063 .output_entry = ICMP_MIB_DUMMY,
1064 .input_entry = ICMP_MIB_INERRORS,
1065 .handler = icmp_discard, 1039 .handler = icmp_discard,
1066 .error = 1, 1040 .error = 1,
1067 }, 1041 },
1068 [ICMP_TIME_EXCEEDED] = { 1042 [ICMP_TIME_EXCEEDED] = {
1069 .output_entry = ICMP_MIB_OUTTIMEEXCDS,
1070 .input_entry = ICMP_MIB_INTIMEEXCDS,
1071 .handler = icmp_unreach, 1043 .handler = icmp_unreach,
1072 .error = 1, 1044 .error = 1,
1073 }, 1045 },
1074 [ICMP_PARAMETERPROB] = { 1046 [ICMP_PARAMETERPROB] = {
1075 .output_entry = ICMP_MIB_OUTPARMPROBS,
1076 .input_entry = ICMP_MIB_INPARMPROBS,
1077 .handler = icmp_unreach, 1047 .handler = icmp_unreach,
1078 .error = 1, 1048 .error = 1,
1079 }, 1049 },
1080 [ICMP_TIMESTAMP] = { 1050 [ICMP_TIMESTAMP] = {
1081 .output_entry = ICMP_MIB_OUTTIMESTAMPS,
1082 .input_entry = ICMP_MIB_INTIMESTAMPS,
1083 .handler = icmp_timestamp, 1051 .handler = icmp_timestamp,
1084 }, 1052 },
1085 [ICMP_TIMESTAMPREPLY] = { 1053 [ICMP_TIMESTAMPREPLY] = {
1086 .output_entry = ICMP_MIB_OUTTIMESTAMPREPS,
1087 .input_entry = ICMP_MIB_INTIMESTAMPREPS,
1088 .handler = icmp_discard, 1054 .handler = icmp_discard,
1089 }, 1055 },
1090 [ICMP_INFO_REQUEST] = { 1056 [ICMP_INFO_REQUEST] = {
1091 .output_entry = ICMP_MIB_DUMMY,
1092 .input_entry = ICMP_MIB_DUMMY,
1093 .handler = icmp_discard, 1057 .handler = icmp_discard,
1094 }, 1058 },
1095 [ICMP_INFO_REPLY] = { 1059 [ICMP_INFO_REPLY] = {
1096 .output_entry = ICMP_MIB_DUMMY,
1097 .input_entry = ICMP_MIB_DUMMY,
1098 .handler = icmp_discard, 1060 .handler = icmp_discard,
1099 }, 1061 },
1100 [ICMP_ADDRESS] = { 1062 [ICMP_ADDRESS] = {
1101 .output_entry = ICMP_MIB_OUTADDRMASKS,
1102 .input_entry = ICMP_MIB_INADDRMASKS,
1103 .handler = icmp_address, 1063 .handler = icmp_address,
1104 }, 1064 },
1105 [ICMP_ADDRESSREPLY] = { 1065 [ICMP_ADDRESSREPLY] = {
1106 .output_entry = ICMP_MIB_OUTADDRMASKREPS,
1107 .input_entry = ICMP_MIB_INADDRMASKREPS,
1108 .handler = icmp_address_reply, 1066 .handler = icmp_address_reply,
1109 }, 1067 },
1110}; 1068};
@@ -1146,4 +1104,5 @@ void __init icmp_init(struct net_proto_family *ops)
1146EXPORT_SYMBOL(icmp_err_convert); 1104EXPORT_SYMBOL(icmp_err_convert);
1147EXPORT_SYMBOL(icmp_send); 1105EXPORT_SYMBOL(icmp_send);
1148EXPORT_SYMBOL(icmp_statistics); 1106EXPORT_SYMBOL(icmp_statistics);
1107EXPORT_SYMBOL(icmpmsg_statistics);
1149EXPORT_SYMBOL(xrlim_allow); 1108EXPORT_SYMBOL(xrlim_allow);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 0f1d7beacf7..77f67b7cb9b 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1261,6 +1261,10 @@ int ip_push_pending_frames(struct sock *sk)
1261 skb->priority = sk->sk_priority; 1261 skb->priority = sk->sk_priority;
1262 skb->dst = dst_clone(&rt->u.dst); 1262 skb->dst = dst_clone(&rt->u.dst);
1263 1263
1264 if (iph->protocol == IPPROTO_ICMP)
1265 icmp_out_count(((struct icmphdr *)
1266 skb_transport_header(skb))->type);
1267
1264 /* Netfilter gets whole the not fragmented skb. */ 1268 /* Netfilter gets whole the not fragmented skb. */
1265 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 1269 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1266 skb->dst->dev, dst_output); 1270 skb->dst->dev, dst_output);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 95a8f8f2de7..2015148b41a 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -124,33 +124,30 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
124static const struct snmp_mib snmp4_icmp_list[] = { 124static const struct snmp_mib snmp4_icmp_list[] = {
125 SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS), 125 SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS),
126 SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS), 126 SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS),
127 SNMP_MIB_ITEM("InDestUnreachs", ICMP_MIB_INDESTUNREACHS),
128 SNMP_MIB_ITEM("InTimeExcds", ICMP_MIB_INTIMEEXCDS),
129 SNMP_MIB_ITEM("InParmProbs", ICMP_MIB_INPARMPROBS),
130 SNMP_MIB_ITEM("InSrcQuenchs", ICMP_MIB_INSRCQUENCHS),
131 SNMP_MIB_ITEM("InRedirects", ICMP_MIB_INREDIRECTS),
132 SNMP_MIB_ITEM("InEchos", ICMP_MIB_INECHOS),
133 SNMP_MIB_ITEM("InEchoReps", ICMP_MIB_INECHOREPS),
134 SNMP_MIB_ITEM("InTimestamps", ICMP_MIB_INTIMESTAMPS),
135 SNMP_MIB_ITEM("InTimestampReps", ICMP_MIB_INTIMESTAMPREPS),
136 SNMP_MIB_ITEM("InAddrMasks", ICMP_MIB_INADDRMASKS),
137 SNMP_MIB_ITEM("InAddrMaskReps", ICMP_MIB_INADDRMASKREPS),
138 SNMP_MIB_ITEM("OutMsgs", ICMP_MIB_OUTMSGS), 127 SNMP_MIB_ITEM("OutMsgs", ICMP_MIB_OUTMSGS),
139 SNMP_MIB_ITEM("OutErrors", ICMP_MIB_OUTERRORS), 128 SNMP_MIB_ITEM("OutErrors", ICMP_MIB_OUTERRORS),
140 SNMP_MIB_ITEM("OutDestUnreachs", ICMP_MIB_OUTDESTUNREACHS),
141 SNMP_MIB_ITEM("OutTimeExcds", ICMP_MIB_OUTTIMEEXCDS),
142 SNMP_MIB_ITEM("OutParmProbs", ICMP_MIB_OUTPARMPROBS),
143 SNMP_MIB_ITEM("OutSrcQuenchs", ICMP_MIB_OUTSRCQUENCHS),
144 SNMP_MIB_ITEM("OutRedirects", ICMP_MIB_OUTREDIRECTS),
145 SNMP_MIB_ITEM("OutEchos", ICMP_MIB_OUTECHOS),
146 SNMP_MIB_ITEM("OutEchoReps", ICMP_MIB_OUTECHOREPS),
147 SNMP_MIB_ITEM("OutTimestamps", ICMP_MIB_OUTTIMESTAMPS),
148 SNMP_MIB_ITEM("OutTimestampReps", ICMP_MIB_OUTTIMESTAMPREPS),
149 SNMP_MIB_ITEM("OutAddrMasks", ICMP_MIB_OUTADDRMASKS),
150 SNMP_MIB_ITEM("OutAddrMaskReps", ICMP_MIB_OUTADDRMASKREPS),
151 SNMP_MIB_SENTINEL 129 SNMP_MIB_SENTINEL
152}; 130};
153 131
132static struct {
133 char *name;
134 int index;
135} icmpmibmap[] = {
136 { "DestUnreachs", ICMP_DEST_UNREACH },
137 { "TimeExcds", ICMP_TIME_EXCEEDED },
138 { "ParmProbs", ICMP_PARAMETERPROB },
139 { "SrcQuenchs", ICMP_SOURCE_QUENCH },
140 { "Redirects", ICMP_REDIRECT },
141 { "Echos", ICMP_ECHO },
142 { "EchoReps", ICMP_ECHOREPLY },
143 { "Timestamps", ICMP_TIMESTAMP },
144 { "TimestampReps", ICMP_TIMESTAMPREPLY },
145 { "AddrMasks", ICMP_ADDRESS },
146 { "AddrMaskReps", ICMP_ADDRESSREPLY },
147 { 0, 0 }
148};
149
150
154static const struct snmp_mib snmp4_tcp_list[] = { 151static const struct snmp_mib snmp4_tcp_list[] = {
155 SNMP_MIB_ITEM("RtoAlgorithm", TCP_MIB_RTOALGORITHM), 152 SNMP_MIB_ITEM("RtoAlgorithm", TCP_MIB_RTOALGORITHM),
156 SNMP_MIB_ITEM("RtoMin", TCP_MIB_RTOMIN), 153 SNMP_MIB_ITEM("RtoMin", TCP_MIB_RTOMIN),
@@ -251,6 +248,72 @@ static const struct snmp_mib snmp4_net_list[] = {
251 SNMP_MIB_SENTINEL 248 SNMP_MIB_SENTINEL
252}; 249};
253 250
251static void icmpmsg_put(struct seq_file *seq)
252{
253#define PERLINE 16
254
255 int j, i, count;
256 static int out[PERLINE];
257
258 count = 0;
259 for (i = 0; i < ICMPMSG_MIB_MAX; i++) {
260
261 if (snmp_fold_field((void **) icmpmsg_statistics, i))
262 out[count++] = i;
263 if (count < PERLINE)
264 continue;
265
266 seq_printf(seq, "\nIcmpMsg:");
267 for (j = 0; j < PERLINE; ++j)
268 seq_printf(seq, " %sType%u", i & 0x100 ? "Out" : "In",
269 i & 0xff);
270 seq_printf(seq, "\nIcmpMsg: ");
271 for (j = 0; j < PERLINE; ++j)
272 seq_printf(seq, " %lu",
273 snmp_fold_field((void **) icmpmsg_statistics,
274 out[j]));
275 seq_putc(seq, '\n');
276 }
277 if (count) {
278 seq_printf(seq, "\nIcmpMsg:");
279 for (j = 0; j < count; ++j)
280 seq_printf(seq, " %sType%u", out[j] & 0x100 ? "Out" :
281 "In", out[j] & 0xff);
282 seq_printf(seq, "\nIcmpMsg:");
283 for (j = 0; j < count; ++j)
284 seq_printf(seq, " %lu", snmp_fold_field((void **)
285 icmpmsg_statistics, out[j]));
286 }
287
288#undef PERLINE
289}
290
291static void icmp_put(struct seq_file *seq)
292{
293 int i;
294
295 seq_puts(seq, "\nIcmp: InMsgs InErrors");
296 for (i=0; icmpmibmap[i].name != NULL; i++)
297 seq_printf(seq, " In%s", icmpmibmap[i].name);
298 seq_printf(seq, " OutMsgs OutErrors");
299 for (i=0; icmpmibmap[i].name != NULL; i++)
300 seq_printf(seq, " Out%s", icmpmibmap[i].name);
301 seq_printf(seq, "\nIcmp: %lu %lu",
302 snmp_fold_field((void **) icmp_statistics, ICMP_MIB_INMSGS),
303 snmp_fold_field((void **) icmp_statistics, ICMP_MIB_INERRORS));
304 for (i=0; icmpmibmap[i].name != NULL; i++)
305 seq_printf(seq, " %lu",
306 snmp_fold_field((void **) icmpmsg_statistics,
307 icmpmibmap[i].index));
308 seq_printf(seq, " %lu %lu",
309 snmp_fold_field((void **) icmp_statistics, ICMP_MIB_OUTMSGS),
310 snmp_fold_field((void **) icmp_statistics, ICMP_MIB_OUTERRORS));
311 for (i=0; icmpmibmap[i].name != NULL; i++)
312 seq_printf(seq, " %lu",
313 snmp_fold_field((void **) icmpmsg_statistics,
314 icmpmibmap[i].index));
315}
316
254/* 317/*
255 * Called from the PROCfs module. This outputs /proc/net/snmp. 318 * Called from the PROCfs module. This outputs /proc/net/snmp.
256 */ 319 */
@@ -271,15 +334,8 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
271 snmp_fold_field((void **)ip_statistics, 334 snmp_fold_field((void **)ip_statistics,
272 snmp4_ipstats_list[i].entry)); 335 snmp4_ipstats_list[i].entry));
273 336
274 seq_puts(seq, "\nIcmp:"); 337 icmp_put(seq); /* RFC 2011 compatibility */
275 for (i = 0; snmp4_icmp_list[i].name != NULL; i++) 338 icmpmsg_put(seq);
276 seq_printf(seq, " %s", snmp4_icmp_list[i].name);
277
278 seq_puts(seq, "\nIcmp:");
279 for (i = 0; snmp4_icmp_list[i].name != NULL; i++)
280 seq_printf(seq, " %lu",
281 snmp_fold_field((void **)icmp_statistics,
282 snmp4_icmp_list[i].entry));
283 339
284 seq_puts(seq, "\nTcp:"); 340 seq_puts(seq, "\nTcp:");
285 for (i = 0; snmp4_tcp_list[i].name != NULL; i++) 341 for (i = 0; snmp4_tcp_list[i].name != NULL; i++)
@@ -336,6 +392,8 @@ static const struct file_operations snmp_seq_fops = {
336 .release = single_release, 392 .release = single_release,
337}; 393};
338 394
395
396
339/* 397/*
340 * Output /proc/net/netstat 398 * Output /proc/net/netstat
341 */ 399 */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 216e01b0f44..07070c7067f 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -314,6 +314,9 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
314 314
315 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); 315 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
316 } 316 }
317 if (iph->protocol == IPPROTO_ICMP)
318 icmp_out_count(((struct icmphdr *)
319 skb_transport_header(skb))->type);
317 320
318 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, 321 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
319 dst_output); 322 dst_output);