Add mii-tool from David Hinds.
[oss-qm-packages.git] / statistics.c
blobeda19e313d44f7da1cc77e248af058e56116705d
1 /* Copyright 1997,1999 by Andi Kleen. Subject to the GPL. */
2 /* $Id: statistics.c,v 1.11 1999/01/06 12:05:49 freitag Exp $ */
3 /* 19980630 - i18n - Arnaldo Carvalho de Melo <acme@conectiva.com.br> */
4 /* 19981113 - i18n fixes - Arnaldo Carvalho de Melo <acme@conectiva.com.br> */
5 /* 19990101 - added net/netstat, -t, -u, -w supprt - Bernd Eckenfels */
6 #include <ctype.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "config.h"
11 #include "intl.h"
13 /* #define WARN 1 */
15 #ifdef WARN
16 #define UFWARN(x) x
17 #else
18 #define UFWARN(x)
19 #endif
21 int print_static,f_raw,f_tcp,f_udp;
23 enum State {
24 number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
25 MaxState
28 #define normal number
30 struct entry {
31 char *title;
32 char *out;
33 enum State type;
36 struct statedesc {
37 int indent;
38 char *title;
39 };
41 struct statedesc states[] = {
42 [number] = { 4, NULL },
43 [opt_number] = { 4, NULL },
44 [i_forward] = { 4, NULL },
45 [i_inp_icmp] = { 8, N_("ICMP input histogram:") },
46 [i_outp_icmp] = { 8, N_("ICMP output histogram:") },
47 [MaxState] = {0},
48 };
50 static enum State state;
52 #define I_STATIC (1<<16) /* static configuration option. */
53 #define I_TITLE (1<<17)
55 /*
56 * XXX check against the snmp mib rfc.
58 * Don't mark the first field as translatable! It's a snmp MIB standard.
59 * - acme
61 struct entry Iptab[] =
63 {"Forwarding", N_("Forwarding is %s"), i_forward | I_STATIC},
64 {"DefaultTTL", N_("Default TTL is %d"), number | I_STATIC},
65 {"InReceives", N_("%d total packets received"), number},
66 {"InHdrErrors", N_("%d with invalid headers"), opt_number},
67 {"InAddrErrors", N_("%d with invalid addresses"), opt_number},
68 {"ForwDatagrams", N_("%d forwarded"), number},
69 {"InUnknownProtos", N_("%d with unknown protocol"), opt_number},
70 {"InDiscards", N_("%d incoming packets discarded"), number},
71 {"InDelivers", N_("%d incoming packets delivered"), number},
72 {"OutRequests", N_("%d requests sent out"), number}, /*? */
73 {"OutDiscards", N_("%d outgoing packets dropped"), opt_number},
74 {"OutNoRoutes", N_("%d dropped because of missing route"), opt_number},
75 {"ReasmTimeout", N_("%d fragments dropped after timeout"), opt_number},
76 {"ReasmReqds", N_("%d reassemblies required"), opt_number}, /* ? */
77 {"ReasmOKs", N_("%d packets reassembled ok"), opt_number},
78 {"ReasmFails", N_("%d packet reassembles failed"), opt_number},
79 {"FragOKs", N_("%d fragments received ok"), opt_number},
80 {"FragFails", N_("%d fragments failed"), opt_number},
81 {"FragCreates", N_("%d fragments created"), opt_number}
84 struct entry Icmptab[] =
86 {"InMsgs", N_("%d ICMP messages received"), number},
87 {"InErrors", N_("%d input ICMP message failed."), number},
88 {"InDestUnreachs", N_("destination unreachable: %d"), i_inp_icmp | I_TITLE},
89 {"InTimeExcds", N_("timeout in transit: %d"), i_inp_icmp | I_TITLE},
90 {"InParmProbs", N_("wrong parameters: %d"), i_inp_icmp | I_TITLE}, /*? */
91 {"InSrcQuenchs", N_("source quenchs: %d"), i_inp_icmp | I_TITLE},
92 {"InRedirects", N_("redirects: %d"), i_inp_icmp | I_TITLE},
93 {"InEchos", N_("echo requests: %d"), i_inp_icmp | I_TITLE},
94 {"InEchoReps", N_("echo replies: %d"), i_inp_icmp | I_TITLE},
95 {"InTimestamps", N_("timestamp request: %d"), i_inp_icmp | I_TITLE},
96 {"InTimestampReps", N_("timestamp reply: %d"), i_inp_icmp | I_TITLE},
97 {"InAddrMasks", N_("address mask request: %d"), i_inp_icmp | I_TITLE}, /*? */
98 {"InAddrMaskReps", N_("address mask replies"), i_inp_icmp | I_TITLE}, /*? */
99 {"OutMsgs", N_("%d ICMP messages sent"), number},
100 {"OutErrors", N_("%d ICMP messages failed"), number},
101 {"OutDestUnreachs", N_("destination unreachable: %d"), i_outp_icmp | I_TITLE},
102 {"OutTimeExcds", N_("time exceeded: %d"), i_outp_icmp | I_TITLE},
103 {"OutParmProbs", N_("wrong parameters: %d"), i_outp_icmp | I_TITLE}, /*? */
104 {"OutSrcQuenchs", N_("source quench: %d"), i_outp_icmp | I_TITLE},
105 {"OutRedirects", N_("redirect: %d"), i_outp_icmp | I_TITLE},
106 {"OutEchos", N_("echo request: %d"), i_outp_icmp | I_TITLE},
107 {"OutEchoReps", N_("echo replies: %d"), i_outp_icmp | I_TITLE},
108 {"OutTimestamps", N_("timestamp requests: %d"), i_outp_icmp | I_TITLE},
109 {"OutTimestampReps", N_("timestamp replies: %d"), i_outp_icmp | I_TITLE},
110 {"OutAddrMasks", N_("address mask requests: %d"), i_outp_icmp | I_TITLE},
111 {"OutAddrMaskReps", N_("address mask replies: %d"), i_outp_icmp | I_TITLE},
114 struct entry Tcptab[] =
116 {"RtoAlgorithm", N_("RTO algorithm is %s"), i_rto_alg | I_STATIC},
117 {"RtoMin", "", number},
118 {"RtoMax", "", number},
119 {"MaxConn", "", number},
120 {"ActiveOpens", N_("%d active connections openings"), number},
121 {"PassiveOpens", N_("%d passive connection openings"), number},
122 {"AttemptFails", N_("%d failed connection attempts"), number},
123 {"EstabResets", N_("%d connection resets received"), number},
124 {"CurrEstab", N_("%d connections established"), number},
125 {"InSegs", N_("%d segments received"), number},
126 {"OutSegs", N_("%d segments send out"), number},
127 {"RetransSegs", N_("%d segments retransmited"), number},
128 {"InErrs", N_("%d bad segments received."), number},
129 {"OutRsts", N_("%d resets sent"), number},
132 struct entry Udptab[] =
134 {"InDatagrams", N_("%d packets received"), number},
135 {"NoPorts", N_("%d packets to unknown port received."), number},
136 {"InErrors", N_("%d packet receive errors"), number},
137 {"OutDatagrams", N_("%d packets sent"), number},
140 struct entry Tcpexttab[] =
142 {"SyncookiesSent", N_("%d SYN cookies sent"), opt_number},
143 {"SyncookiesRecv", N_("%d SYN cookies received"), opt_number},
144 {"SyncookiesFailed", N_("%d invalid SYN cookies received"), opt_number},
146 { "EmbryonicRsts", N_("%d resets received for embryonic SYN_RECV sockets"),
147 opt_number },
148 { "PruneCalled", N_("%d packets pruned from receive queue because of socket"
149 " buffer overrun"), opt_number },
150 /* obsolete: 2.2.0 doesn't do that anymore */
151 { "RcvPruned", N_("%d packets pruned from out-of-order queue"), opt_number },
152 { "OfoPruned", N_("%d packets dropped from out-of-order queue because of"
153 " socket buffer overrun"), opt_number },
154 { "OutOfWindowIcmps", N_("%d ICMP packets dropped because they were "
155 "out-of-window"), opt_number },
156 { "LockDroppedIcmps", N_("%d ICMP packets dropped because socket was locked"),
157 opt_number },
160 struct tabtab {
161 char *title;
162 struct entry *tab;
163 size_t size;
164 int *flag;
167 struct tabtab snmptabs[] =
169 {"Ip", Iptab, sizeof(Iptab), &f_raw},
170 {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
171 {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
172 {"Udp", Udptab, sizeof(Udptab), &f_udp},
173 {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
174 {NULL}
177 /* XXX IGMP */
179 int cmpentries(const void *a, const void *b)
181 return strcmp(((struct entry *) a)->title, ((struct entry *) b)->title);
184 void printval(struct tabtab *tab, char *title, int val)
186 struct entry *ent, key;
187 int type;
188 char buf[512];
190 key.title = title;
191 ent = bsearch(&key, tab->tab, tab->size / sizeof(struct entry),
192 sizeof(struct entry), cmpentries);
193 if (!ent) { /* try our best */
194 printf("%*s%s: %d\n", states[state].indent, "", title, val);
195 return;
197 type = ent->type;
198 if (type & I_STATIC) {
199 type &= ~I_STATIC;
200 if (!print_static)
201 return;
203 if (*ent->out == '\0')
204 return;
206 if (type & I_TITLE) {
207 type &= ~I_TITLE;
208 if (state != type)
209 printf("%*s%s\n", states[state].indent, "", _(states[type].title));
211 buf[0] = '\0';
212 switch (type) {
213 case opt_number:
214 if (val == 0)
215 break;
216 /*FALL THOUGH*/
217 case number:
218 snprintf(buf, sizeof(buf), _(ent->out), val);
219 break;
220 case i_forward:
221 type = normal;
222 snprintf(buf, sizeof(buf), _(ent->out), val == 2 ? _("enabled") : _("disabled"));
223 break;
224 case i_outp_icmp:
225 case i_inp_icmp:
226 if (val > 0)
227 snprintf(buf, sizeof(buf), _(ent->out), val);
228 break;
229 case i_rto_alg: /* XXXX */
230 break;
231 default:
232 abort();
234 if (buf[0])
235 printf("%*s%s\n", states[type].indent, "", buf);
237 state = type;
240 struct tabtab *newtable(struct tabtab *tabs, char *title)
242 struct tabtab *t;
244 for (t = tabs; t->title; t++)
245 if (!strcmp(title, t->title)) {
246 if (*(t->flag))
247 printf("%s:\n", _(title));
248 state = normal;
249 return t;
251 return NULL;
255 void process_fd(FILE *f)
257 char buf1[512], buf2[512];
258 char *sp, *np, *p;
259 while (fgets(buf1, sizeof buf1, f)) {
260 int endflag;
261 struct tabtab *tab;
263 if (!fgets(buf2, sizeof buf2, f))
264 break;
265 sp = strchr(buf1, ':');
266 np = strchr(buf2, ':');
267 if (!np || !sp)
268 goto formaterr;
269 *sp = '\0';
270 tab = newtable(snmptabs, buf1);
271 if (tab == NULL) {
272 UFWARN((printf(_("unknown title %s\n"), buf1)));
273 continue;
275 np++;
276 sp++;
278 endflag = 0;
279 while (!endflag) {
280 sp += strspn(sp, " \t\n");
281 np += strspn(np, " \t\n");
282 /*if (*np == '\0') goto formaterr; */
284 p = sp+strcspn(sp, " \t\n");
285 if (*p == '\0')
286 endflag = 1;
287 *p = '\0';
289 if (*sp != '\0' && *(tab->flag))
290 printval(tab, sp, strtoul(np, &np, 10));
292 sp = p + 1;
295 return;
297 formaterr:
298 perror(_("error parsing /proc/net/snmp"));
299 return;
303 void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
305 FILE *f;
307 f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
309 f = fopen("/proc/net/snmp", "r");
310 if (!f) {
311 perror(_("cannot open /proc/net/snmp"));
312 return;
314 process_fd(f);
316 if (ferror(f))
317 perror("/proc/net/snmp");
319 fclose(f);
321 f = fopen("/proc/net/netstat", "r");
323 if (f) {
324 process_fd(f);
326 if (ferror(f))
327 perror("/proc/net/netstat");
329 fclose(f);
331 return;
335 void inittab(void)
337 struct tabtab *t;
339 /* we sort at runtime because I'm lazy ;) */
340 for (t = snmptabs; t->title; t++)
341 qsort(t->tab, t->size / sizeof(struct entry),
342 sizeof(struct entry), cmpentries);