Maik Broemme contributed gcc warning fixes (break after default: label)
[oss-qm-packages.git] / statistics.c
blobe88a159c2b7d4f97e7e0a7cd519ac6b95291f0d5
1 /*
2 * Copyright 1997,1999,2000 Andi Kleen. Subject to the GPL.
3 * $Id: statistics.c,v 1.18 2003/02/12 03:30:57 ak Exp $
4 * 19980630 - i18n - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5 * 19981113 - i18n fixes - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 * 19990101 - added net/netstat, -t, -u, -w supprt - Bernd Eckenfels
7 */
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "config.h"
13 #include "intl.h"
15 /* #define WARN 1 */
17 #ifdef WARN
18 #define UFWARN(x) x
19 #else
20 #define UFWARN(x)
21 #endif
23 int print_static,f_raw,f_tcp,f_udp,f_unknown = 1;
25 enum State {
26 number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
27 MaxState
30 #define normal number
32 struct entry {
33 char *title;
34 char *out;
35 enum State type;
38 struct statedesc {
39 int indent;
40 char *title;
41 };
43 struct statedesc states[] = {
44 [number] = { 4, NULL },
45 [opt_number] = { 4, NULL },
46 [i_forward] = { 4, NULL },
47 [i_inp_icmp] = { 8, N_("ICMP input histogram:") },
48 [i_outp_icmp] = { 8, N_("ICMP output histogram:") },
49 [MaxState] = {0},
50 };
52 static enum State state;
54 #define I_STATIC (1<<16) /* static configuration option. */
55 #define I_TITLE (1<<17)
57 /*
58 * XXX check against the snmp mib rfc.
60 * Don't mark the first field as translatable! It's a snmp MIB standard.
61 * - acme
63 struct entry Iptab[] =
65 {"Forwarding", N_("Forwarding is %s"), i_forward | I_STATIC},
66 {"DefaultTTL", N_("Default TTL is %u"), number | I_STATIC},
67 {"InReceives", N_("%u total packets received"), number},
68 {"InHdrErrors", N_("%u with invalid headers"), opt_number},
69 {"InAddrErrors", N_("%u with invalid addresses"), opt_number},
70 {"ForwDatagrams", N_("%u forwarded"), number},
71 {"InUnknownProtos", N_("%u with unknown protocol"), opt_number},
72 {"InDiscards", N_("%u incoming packets discarded"), number},
73 {"InDelivers", N_("%u incoming packets delivered"), number},
74 {"OutRequests", N_("%u requests sent out"), number}, /*? */
75 {"OutDiscards", N_("%u outgoing packets dropped"), opt_number},
76 {"OutNoRoutes", N_("%u dropped because of missing route"), opt_number},
77 {"ReasmTimeout", N_("%u fragments dropped after timeout"), opt_number},
78 {"ReasmReqds", N_("%u reassemblies required"), opt_number}, /* ? */
79 {"ReasmOKs", N_("%u packets reassembled ok"), opt_number},
80 {"ReasmFails", N_("%u packet reassembles failed"), opt_number},
81 {"FragOKs", N_("%u fragments received ok"), opt_number},
82 {"FragFails", N_("%u fragments failed"), opt_number},
83 {"FragCreates", N_("%u fragments created"), opt_number}
86 struct entry Icmptab[] =
88 {"InMsgs", N_("%u ICMP messages received"), number},
89 {"InErrors", N_("%u input ICMP message failed."), number},
90 {"InDestUnreachs", N_("destination unreachable: %u"), i_inp_icmp | I_TITLE},
91 {"InTimeExcds", N_("timeout in transit: %u"), i_inp_icmp | I_TITLE},
92 {"InParmProbs", N_("wrong parameters: %u"), i_inp_icmp | I_TITLE}, /*? */
93 {"InSrcQuenchs", N_("source quenches: %u"), i_inp_icmp | I_TITLE},
94 {"InRedirects", N_("redirects: %u"), i_inp_icmp | I_TITLE},
95 {"InEchos", N_("echo requests: %u"), i_inp_icmp | I_TITLE},
96 {"InEchoReps", N_("echo replies: %u"), i_inp_icmp | I_TITLE},
97 {"InTimestamps", N_("timestamp request: %u"), i_inp_icmp | I_TITLE},
98 {"InTimestampReps", N_("timestamp reply: %u"), i_inp_icmp | I_TITLE},
99 {"InAddrMasks", N_("address mask request: %u"), i_inp_icmp | I_TITLE}, /*? */
100 {"InAddrMaskReps", N_("address mask replies: %u"), i_inp_icmp | I_TITLE}, /*? */
101 {"OutMsgs", N_("%u ICMP messages sent"), number},
102 {"OutErrors", N_("%u ICMP messages failed"), number},
103 {"OutDestUnreachs", N_("destination unreachable: %u"), i_outp_icmp | I_TITLE},
104 {"OutTimeExcds", N_("time exceeded: %u"), i_outp_icmp | I_TITLE},
105 {"OutParmProbs", N_("wrong parameters: %u"), i_outp_icmp | I_TITLE}, /*? */
106 {"OutSrcQuenchs", N_("source quench: %u"), i_outp_icmp | I_TITLE},
107 {"OutRedirects", N_("redirect: %u"), i_outp_icmp | I_TITLE},
108 {"OutEchos", N_("echo request: %u"), i_outp_icmp | I_TITLE},
109 {"OutEchoReps", N_("echo replies: %u"), i_outp_icmp | I_TITLE},
110 {"OutTimestamps", N_("timestamp requests: %u"), i_outp_icmp | I_TITLE},
111 {"OutTimestampReps", N_("timestamp replies: %u"), i_outp_icmp | I_TITLE},
112 {"OutAddrMasks", N_("address mask requests: %u"), i_outp_icmp | I_TITLE},
113 {"OutAddrMaskReps", N_("address mask replies: %u"), i_outp_icmp | I_TITLE},
116 struct entry Tcptab[] =
118 {"RtoAlgorithm", N_("RTO algorithm is %s"), i_rto_alg | I_STATIC},
119 {"RtoMin", "", number},
120 {"RtoMax", "", number},
121 {"MaxConn", "", number},
122 {"ActiveOpens", N_("%u active connections openings"), number},
123 {"PassiveOpens", N_("%u passive connection openings"), number},
124 {"AttemptFails", N_("%u failed connection attempts"), number},
125 {"EstabResets", N_("%u connection resets received"), number},
126 {"CurrEstab", N_("%u connections established"), number},
127 {"InSegs", N_("%u segments received"), number},
128 {"OutSegs", N_("%u segments send out"), number},
129 {"RetransSegs", N_("%u segments retransmited"), number},
130 {"InErrs", N_("%u bad segments received."), number},
131 {"OutRsts", N_("%u resets sent"), number},
134 struct entry Udptab[] =
136 {"InDatagrams", N_("%u packets received"), number},
137 {"NoPorts", N_("%u packets to unknown port received."), number},
138 {"InErrors", N_("%u packet receive errors"), number},
139 {"OutDatagrams", N_("%u packets sent"), number},
142 struct entry Tcpexttab[] =
144 {"SyncookiesSent", N_("%u SYN cookies sent"), opt_number},
145 {"SyncookiesRecv", N_("%u SYN cookies received"), opt_number},
146 {"SyncookiesFailed", N_("%u invalid SYN cookies received"), opt_number},
148 { "EmbryonicRsts", N_("%u resets received for embryonic SYN_RECV sockets"),
149 opt_number },
150 { "PruneCalled", N_("%u packets pruned from receive queue because of socket"
151 " buffer overrun"), opt_number },
152 /* obsolete: 2.2.0 doesn't do that anymore */
153 { "RcvPruned", N_("%u packets pruned from receive queue"), opt_number },
154 { "OfoPruned", N_("%u packets dropped from out-of-order queue because of"
155 " socket buffer overrun"), opt_number },
156 { "OutOfWindowIcmps", N_("%u ICMP packets dropped because they were "
157 "out-of-window"), opt_number },
158 { "LockDroppedIcmps", N_("%u ICMP packets dropped because"
159 " socket was locked"), opt_number },
160 { "TW", N_("%u TCP sockets finished time wait in fast timer"), opt_number },
161 { "TWRecycled", N_("%u time wait sockets recycled by time stamp"), opt_number },
162 { "TWKilled", N_("%u TCP sockets finished time wait in slow timer"), opt_number },
163 { "PAWSPassive", N_("%u passive connections rejected because of"
164 " time stamp"), opt_number },
165 { "PAWSActive", N_("%u active connections rejected because of "
166 "time stamp"), opt_number },
167 { "PAWSEstab", N_("%u packets rejects in established connections because of"
168 " timestamp"), opt_number },
169 { "DelayedACKs", N_("%u delayed acks sent"), opt_number },
170 { "DelayedACKLocked", N_("%u delayed acks further delayed because of"
171 " locked socket"), opt_number },
172 { "DelayedACKLost", N_("Quick ack mode was activated %u times"), opt_number },
173 { "ListenOverflows", N_("%u times the listen queue of a socket overflowed"),
174 opt_number },
175 { "ListenDrops", N_("%u SYNs to LISTEN sockets dropped"), opt_number },
176 { "TCPPrequeued", N_("%u packets directly queued to recvmsg prequeue."),
177 opt_number },
178 { "TCPDirectCopyFromBacklog", N_("%u bytes directly in process context from backlog"), opt_number },
179 { "TCPDirectCopyFromPrequeue", N_("%u bytes directly received in process context from prequeue"),
180 opt_number },
181 { "TCPPrequeueDropped", N_("%u packets dropped from prequeue"), opt_number },
182 { "TCPHPHits", N_("%u packet headers predicted"), number },
183 { "TCPHPHitsToUser", N_("%u packets header predicted and "
184 "directly queued to user"), opt_number },
185 { "SockMallocOOM", N_("Ran %u times out of system memory during "
186 "packet sending"), opt_number },
187 { "TCPPureAcks", N_("%u acknowledgments not containing data payload received"), opt_number },
188 { "TCPHPAcks", N_("%u predicted acknowledgments"), opt_number },
189 { "TCPRenoRecovery", N_("%u times recovered from packet loss due to fast retransmit"), opt_number },
190 { "TCPSackRecovery", N_("%u times recovered from packet loss by selective acknowledgements"), opt_number },
191 { "TCPSACKReneging", N_("%u bad SACK blocks received"), opt_number },
192 { "TCPFACKReorder", N_("Detected reordering %u times using FACK"), opt_number },
193 { "TCPSACKReorder", N_("Detected reordering %u times using SACK"), opt_number },
194 { "TCPTSReorder", N_("Detected reordering %u times using time stamp"), opt_number },
195 { "TCPRenoReorder", N_("Detected reordering %u times using reno fast retransmit"), opt_number },
196 { "TCPFullUndo", N_("%u congestion windows fully recovered without slow start"), opt_number },
197 { "TCPPartialUndo", N_("%u congestion windows partially recovered using Hoe heuristic"), opt_number },
198 { "TCPDSackUndo", N_("%u congestion window recovered without slow start using DSACK"), opt_number },
199 { "TCPLossUndo", N_("%u congestion windows recovered without slow start after partial ack"), opt_number },
200 { "TCPLostRetransmits", N_("%u retransmits lost"), opt_number },
201 { "TCPRenoFailures", N_("%u timeouts after reno fast retransmit"), opt_number },
202 { "TCPSackFailures", N_("%u timeouts after SACK recovery"), opt_number },
203 { "TCPLossFailures", N_("%u timeouts in loss state"), opt_number },
204 { "TCPFastRetrans", N_("%u fast retransmits"), opt_number },
205 { "TCPForwardRetrans", N_("%u forward retransmits"), opt_number },
206 { "TCPSlowStartRetrans", N_("%u retransmits in slow start"), opt_number },
207 { "TCPTimeouts", N_("%u other TCP timeouts"), opt_number },
208 { "TCPRenoRecoveryFailed", N_("%u reno fast retransmits failed"), opt_number },
209 { "TCPSackRecoveryFail", N_("%u SACK retransmits failed"), opt_number },
210 { "TCPSchedulerFailed", N_("%u times receiver scheduled too late for direct processing"), opt_number },
211 { "TCPRcvCollapsed", N_("%u packets collapsed in receive queue due to low socket buffer"), opt_number },
212 { "TCPDSACKOldSent", N_("%u DSACKs sent for old packets"), opt_number },
213 { "TCPDSACKOfoSent", N_("%u DSACKs sent for out of order packets"), opt_number },
214 { "TCPDSACKRecv", N_("%u DSACKs received"), opt_number },
215 { "TCPDSACKOfoRecv", N_("%u DSACKs for out of order packets received"), opt_number },
216 { "TCPAbortOnSyn", N_("%u connections reset due to unexpected SYN"), opt_number },
217 { "TCPAbortOnData", N_("%u connections reset due to unexpected data"), opt_number },
218 { "TCPAbortOnClose", N_("%u connections reset due to early user close"), opt_number },
219 { "TCPAbortOnMemory", N_("%u connections aborted due to memory pressure"), opt_number },
220 { "TCPAbortOnTimeout", N_("%u connections aborted due to timeout"), opt_number },
221 { "TCPAbortOnLinger", N_("%u connections aborted after user close in linger timeout"), opt_number },
222 { "TCPAbortFailed", N_("%u times unabled to send RST due to no memory"), opt_number },
223 { "TCPMemoryPressures", N_("TCP ran low on memory %u times"), opt_number },
224 { "TCPLoss", N_("%u TCP data loss events"), opt_number },
225 { "TCPDSACKUndo", N_("%u congestion windows recovered without slow start by DSACK"),
226 opt_number },
227 { "TCPRenoRecoveryFail", N_("%u classic Reno fast retransmits failed"), opt_number },
230 struct tabtab {
231 char *title;
232 struct entry *tab;
233 size_t size;
234 int *flag;
237 struct tabtab snmptabs[] =
239 {"Ip", Iptab, sizeof(Iptab), &f_raw},
240 {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
241 {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
242 {"Udp", Udptab, sizeof(Udptab), &f_udp},
243 {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
244 {NULL}
247 /* XXX IGMP */
249 int cmpentries(const void *a, const void *b)
251 return strcmp(((struct entry *) a)->title, ((struct entry *) b)->title);
254 void printval(struct tabtab *tab, char *title, int val)
256 struct entry *ent = NULL, key;
257 int type;
258 char buf[512];
260 key.title = title;
261 if (tab->tab)
262 ent = bsearch(&key, tab->tab, tab->size / sizeof(struct entry),
263 sizeof(struct entry), cmpentries);
264 if (!ent) { /* try our best */
265 if (val)
266 printf("%*s%s: %d\n", states[state].indent, "", title, val);
267 return;
269 type = ent->type;
270 if (type & I_STATIC) {
271 type &= ~I_STATIC;
272 if (!print_static)
273 return;
275 if (*ent->out == '\0')
276 return;
278 if (type & I_TITLE) {
279 type &= ~I_TITLE;
280 if (state != type)
281 printf("%*s%s\n", states[state].indent, "", _(states[type].title));
283 buf[0] = '\0';
284 switch (type) {
285 case opt_number:
286 if (val == 0)
287 break;
288 /*FALL THOUGH*/
289 case number:
290 snprintf(buf, sizeof(buf), _(ent->out), val);
291 break;
292 case i_forward:
293 type = normal;
294 snprintf(buf, sizeof(buf), _(ent->out), val == 2 ? _("enabled") : _("disabled"));
295 break;
296 case i_outp_icmp:
297 case i_inp_icmp:
298 if (val > 0)
299 snprintf(buf, sizeof(buf), _(ent->out), val);
300 break;
301 case i_rto_alg: /* XXXX */
302 break;
303 default:
304 abort();
306 if (buf[0])
307 printf("%*s%s\n", states[type].indent, "", buf);
309 state = type;
312 struct tabtab *newtable(struct tabtab *tabs, char *title)
314 struct tabtab *t;
315 static struct tabtab dummytab;
317 for (t = tabs; t->title; t++) {
318 if (!strcmp(title, t->title)) {
319 if (*(t->flag))
320 printf("%s:\n", _(title));
321 state = normal;
322 return t;
325 if (!f_unknown)
326 return NULL;
327 printf("%s:\n", _(title));
328 dummytab.title = title;
329 dummytab.flag = &f_unknown;
330 return &dummytab;
333 void process_fd(FILE *f)
335 char buf1[1024], buf2[1024];
336 char *sp, *np, *p;
337 while (fgets(buf1, sizeof buf1, f)) {
338 int endflag;
339 struct tabtab *tab;
341 if (!fgets(buf2, sizeof buf2, f))
342 break;
343 sp = strchr(buf1, ':');
344 np = strchr(buf2, ':');
345 if (!np || !sp)
346 goto formaterr;
347 *sp = '\0';
349 tab = newtable(snmptabs, buf1);
350 if (tab == NULL) {
351 printf("unknown %s\n", buf1);
352 continue;
354 np++;
355 sp++;
357 endflag = 0;
358 while (!endflag) {
359 sp += strspn(sp, " \t\n");
360 np += strspn(np, " \t\n");
361 /*if (*np == '\0') goto formaterr; */
363 p = sp+strcspn(sp, " \t\n");
364 if (*p == '\0')
365 endflag = 1;
366 *p = '\0';
368 if (*sp != '\0' && *(tab->flag))
369 printval(tab, sp, strtoul(np, &np, 10));
371 sp = p + 1;
374 return;
376 formaterr:
377 perror(_("error parsing /proc/net/snmp"));
378 return;
382 void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
384 FILE *f;
386 f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
388 f = fopen("/proc/net/snmp", "r");
389 if (!f) {
390 perror(_("cannot open /proc/net/snmp"));
391 return;
393 process_fd(f);
395 if (ferror(f))
396 perror("/proc/net/snmp");
398 fclose(f);
400 f = fopen("/proc/net/netstat", "r");
402 if (f) {
403 process_fd(f);
405 if (ferror(f))
406 perror("/proc/net/netstat");
408 fclose(f);
410 return;
414 void inittab(void)
416 struct tabtab *t;
418 /* we sort at runtime because I'm lazy ;) */
419 for (t = snmptabs; t->title; t++)
420 qsort(t->tab, t->size / sizeof(struct entry),
421 sizeof(struct entry), cmpentries);