aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid L Stevens <dlstevens@us.ibm.com>2007-09-17 12:57:33 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:28 -0400
commit96793b482540f3a26e2188eaf75cb56b7829d3e3 (patch)
tree3dfc2871b69cc358ed55dc2adc3bfeef47382cb3
parent14878f75abd5bf1d38becb405801cd491ee215dc (diff)
[IPV4]: Add ICMPMsgStats MIB (RFC 4293)
Background: RFC 4293 deprecates existing individual, named ICMP type counters to be replaced with the ICMPMsgStatsTable. This table includes entries for both IPv4 and IPv6, and requires counting of all ICMP types, whether or not the machine implements the type. These patches "remove" (but not really) the existing counters, and replace them with the ICMPMsgStats tables for v4 and v6. It includes the named counters in the /proc places they were, but gets the values for them from the new tables. It also counts packets generated from raw socket output (e.g., OutEchoes, MLD queries, RA's from radvd, etc). Changes: 1) create icmpmsg_statistics mib 2) create icmpv6msg_statistics mib 3) modify existing counters to use these 4) modify /proc/net/snmp to add "IcmpMsg" with all ICMP types listed by number for easy SNMP parsing 5) modify /proc/net/snmp printing for "Icmp" to get the named data from new counters. Signed-off-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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 86977e31548a..d8fd3ec4148a 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 dc09474efcf3..9f7ef3c8baef 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 a566e11d2f98..ea206bff0dc4 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 e594a2c89661..621b128897d7 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 68a22670f597..272c69e106e9 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 0f1d7beacf78..77f67b7cb9bf 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 95a8f8f2de71..2015148b41a8 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 216e01b0f44a..07070c7067f3 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);