Add Bluetooth socket support
[platform/upstream/net-tools.git] / statistics.c
1 /*
2  * Copyright 1997,1999,2000 Andi Kleen. Subject to the GPL. 
3  * $Id: statistics.c,v 1.23 2010-10-29 19:24:36 ecki 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"
14 #include "proc.h"
15
16 /* #define WARN 1 */
17
18 #ifdef WARN
19 #define UFWARN(x) x
20 #else
21 #define UFWARN(x)
22 #endif
23
24 int print_static,f_raw,f_tcp,f_udp,f_unknown = 1;
25
26 enum State {
27     number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
28     MaxState
29 };
30
31 #define normal number
32
33 struct entry {
34     char *title;
35     char *out;
36     enum State type;
37 };
38
39 struct statedesc { 
40     int indent;
41     char *title; 
42 }; 
43
44 struct statedesc states[] = { 
45     [number] = { 4, NULL },
46     [opt_number] = { 4, NULL }, 
47     [i_forward] = { 4, NULL },
48     [i_inp_icmp] = { 8, N_("ICMP input histogram:") },
49     [i_outp_icmp] = { 8, N_("ICMP output histogram:") },
50     [MaxState] = {0},
51 }; 
52
53 static enum State state;
54
55 #define I_STATIC (1<<16)        /* static configuration option. */
56 #define I_TITLE  (1<<17)
57
58 /* 
59  * XXX check against the snmp mib rfc.
60  *
61  * Don't mark the first field as translatable! It's a snmp MIB standard.
62  * - acme
63  */
64 struct entry Iptab[] =
65 {
66     {"Forwarding", N_("Forwarding is %s"), i_forward | I_STATIC},
67     {"DefaultTTL", N_("Default TTL is %u"), number | I_STATIC},
68     {"InReceives", N_("%u total packets received"), number},
69     {"InHdrErrors", N_("%u with invalid headers"), opt_number},
70     {"InAddrErrors", N_("%u with invalid addresses"), opt_number},
71     {"ForwDatagrams", N_("%u forwarded"), number},
72     {"InUnknownProtos", N_("%u with unknown protocol"), opt_number},
73     {"InDiscards", N_("%u incoming packets discarded"), number},
74     {"InDelivers", N_("%u incoming packets delivered"), number},
75     {"OutRequests", N_("%u requests sent out"), number},        /*? */
76     {"OutDiscards", N_("%u outgoing packets dropped"), opt_number},
77     {"OutNoRoutes", N_("%u dropped because of missing route"), opt_number},
78     {"ReasmTimeout", N_("%u fragments dropped after timeout"), opt_number},
79     {"ReasmReqds", N_("%u reassemblies required"), opt_number}, /* ? */
80     {"ReasmOKs", N_("%u packets reassembled ok"), opt_number},
81     {"ReasmFails", N_("%u packet reassembles failed"), opt_number},
82     {"FragOKs", N_("%u fragments received ok"), opt_number},
83     {"FragFails", N_("%u fragments failed"), opt_number},
84     {"FragCreates", N_("%u fragments created"), opt_number}
85 };
86
87 struct entry Ip6tab[] =
88 {
89     {"Ip6InReceives", N_("%u total packets received"), number},
90     {"Ip6InHdrErrors", N_("%u with invalid headers"), opt_number},
91     {"Ip6InTooBigErrors", N_("%u with packets too big"), opt_number},
92     {"Ip6InNoRoutes", N_("%u incoming packets with no route"), opt_number},
93     {"Ip6InAddrErrors", N_("%u with invalid addresses"), opt_number},
94     {"Ip6InUnknownProtos", N_("%u with unknown protocol"), opt_number},
95     {"Ip6InTruncatedPkts", N_("%u with truncated packets"), opt_number},
96     {"Ip6InDiscards", N_("%u incoming packets discarded"), number},
97     {"Ip6InDelivers", N_("%u incoming packets delivered"), number},
98     {"Ip6OutForwDatagrams", N_("%u forwarded"), number},
99     {"Ip6OutRequests", N_("%u requests sent out"), number},     /*? */
100     {"Ip6OutDiscards", N_("%u outgoing packets dropped"), opt_number},
101     {"Ip6OutNoRoutes", N_("%u dropped because of missing route"), opt_number},
102     {"Ip6ReasmTimeout", N_("%u fragments dropped after timeout"), opt_number},
103     {"Ip6ReasmReqds", N_("%u reassemblies required"), opt_number}, /* ? */
104     {"Ip6ReasmOKs", N_("%u packets reassembled ok"), opt_number},
105     {"Ip6ReasmFails", N_("%u packet reassembles failed"), opt_number},
106     {"Ip6FragOKs", N_("%u fragments received ok"), opt_number},
107     {"Ip6FragFails", N_("%u fragments failed"), opt_number},
108     {"Ip6FragCreates", N_("%u fragments created"), opt_number},
109     {"Ip6InMcastPkts", N_("%u incoming multicast packets"), opt_number},
110     {"Ip6OutMcastPkts", N_("%u outgoing multicast packets"), opt_number}
111 };
112
113 struct entry Icmptab[] =
114 {
115     {"InMsgs", N_("%u ICMP messages received"), number},
116     {"InErrors", N_("%u input ICMP message failed."), number},
117     {"InDestUnreachs", N_("destination unreachable: %u"), i_inp_icmp | I_TITLE},
118     {"InTimeExcds", N_("timeout in transit: %u"), i_inp_icmp | I_TITLE},
119     {"InParmProbs", N_("wrong parameters: %u"), i_inp_icmp | I_TITLE},  /*? */
120     {"InSrcQuenchs", N_("source quenches: %u"), i_inp_icmp | I_TITLE},
121     {"InRedirects", N_("redirects: %u"), i_inp_icmp | I_TITLE},
122     {"InEchos", N_("echo requests: %u"), i_inp_icmp | I_TITLE},
123     {"InEchoReps", N_("echo replies: %u"), i_inp_icmp | I_TITLE},
124     {"InTimestamps", N_("timestamp request: %u"), i_inp_icmp | I_TITLE},
125     {"InTimestampReps", N_("timestamp reply: %u"), i_inp_icmp | I_TITLE},
126     {"InAddrMasks", N_("address mask request: %u"), i_inp_icmp | I_TITLE},      /*? */
127     {"InAddrMaskReps", N_("address mask replies: %u"), i_inp_icmp | I_TITLE},   /*? */
128     {"OutMsgs", N_("%u ICMP messages sent"), number},
129     {"OutErrors", N_("%u ICMP messages failed"), number},
130     {"OutDestUnreachs", N_("destination unreachable: %u"), i_outp_icmp | I_TITLE},
131     {"OutTimeExcds", N_("time exceeded: %u"), i_outp_icmp | I_TITLE},
132     {"OutParmProbs", N_("wrong parameters: %u"), i_outp_icmp | I_TITLE},        /*? */
133     {"OutSrcQuenchs", N_("source quench: %u"), i_outp_icmp | I_TITLE},
134     {"OutRedirects", N_("redirect: %u"), i_outp_icmp | I_TITLE},
135     {"OutEchos", N_("echo request: %u"), i_outp_icmp | I_TITLE},
136     {"OutEchoReps", N_("echo replies: %u"), i_outp_icmp | I_TITLE},
137     {"OutTimestamps", N_("timestamp requests: %u"), i_outp_icmp | I_TITLE},
138     {"OutTimestampReps", N_("timestamp replies: %u"), i_outp_icmp | I_TITLE},
139     {"OutAddrMasks", N_("address mask requests: %u"), i_outp_icmp | I_TITLE},
140     {"OutAddrMaskReps", N_("address mask replies: %u"), i_outp_icmp | I_TITLE},
141 };
142
143 struct entry Icmp6tab[] =
144 {
145     {"Icmp6InMsgs", N_("%u ICMP messages received"), number},
146     {"Icmp6InErrors", N_("%u input ICMP message failed."), number},
147     {"Icmp6InDestUnreachs", N_("destination unreachable: %u"), i_inp_icmp | I_TITLE},
148     {"Icmp6InPktTooBigs", N_("packets too big: %u"), i_inp_icmp | I_TITLE},
149     {"Icmp6InTimeExcds", N_("received ICMPv6 time exceeded: %u"), i_inp_icmp | I_TITLE},
150     {"Icmp6InParmProblems", N_("parameter problem: %u"), i_inp_icmp | I_TITLE},
151     {"Icmp6InEchos", N_("echo requests: %u"), i_inp_icmp | I_TITLE},
152     {"Icmp6InEchoReplies", N_("echo replies: %u"), i_inp_icmp | I_TITLE},
153     {"Icmp6InGroupMembQueries", N_("group member queries: %u"), i_inp_icmp | I_TITLE},
154     {"Icmp6InGroupMembResponses", N_("group member responses: %u"), i_inp_icmp | I_TITLE},
155     {"Icmp6InGroupMembReductions", N_("group member reductions: %u"), i_inp_icmp | I_TITLE},
156     {"Icmp6InRouterSolicits", N_("router solicits: %u"), i_inp_icmp | I_TITLE},
157     {"Icmp6InRouterAdvertisements", N_("router advertisement: %u"), i_inp_icmp | I_TITLE},
158     {"Icmp6InNeighborSolicits", N_("neighbour solicits: %u"), i_inp_icmp | I_TITLE},
159     {"Icmp6InNeighborAdvertisements", N_("neighbour advertisement: %u"), i_inp_icmp | I_TITLE},
160     {"Icmp6InRedirects", N_("redirects: %u"), i_inp_icmp | I_TITLE},
161     {"Icmp6OutMsgs", N_("%u ICMP messages sent"), number},
162     {"Icmp6OutDestUnreachs", N_("destination unreachable: %u"), i_outp_icmp | I_TITLE},
163     {"Icmp6OutPktTooBigs", N_("packets too big: %u"), i_outp_icmp | I_TITLE},
164     {"Icmp6OutTimeExcds", N_("sent ICMPv6 time exceeded: %u"), i_outp_icmp | I_TITLE},
165     {"Icmp6OutParmProblems", N_("parameter problem: %u"), i_outp_icmp | I_TITLE},
166     {"Icmp6OutEchos", N_("echo requests: %u"), i_outp_icmp | I_TITLE},
167     {"Icmp6OutEchoReplies", N_("echo replies: %u"), i_outp_icmp | I_TITLE},
168     {"Icmp6OutGroupMembQueries", N_("group member queries: %u"), i_outp_icmp | I_TITLE},
169     {"Icmp6OutGroupMembResponses", N_("group member responses: %u"), i_outp_icmp | I_TITLE},
170     {"Icmp6OutGroupMembReductions", N_("group member reductions: %u"), i_outp_icmp | I_TITLE},
171     {"Icmp6OutRouterSolicits", N_("router solicits: %u"), i_outp_icmp | I_TITLE},
172     {"Icmp6OutRouterAdvertisements ", N_("router advertisement: %u"), i_outp_icmp | I_TITLE},
173     {"Icmp6OutNeighborSolicits", N_("neighbor solicits: %u"), i_outp_icmp | I_TITLE},
174     {"Icmp6OutNeighborAdvertisements", N_("neighbor advertisements: %u"), i_outp_icmp | I_TITLE},
175     {"Icmp6OutRedirects", N_("redirects: %u"), i_outp_icmp | I_TITLE},
176 };
177
178 struct entry Tcptab[] =
179 {
180     {"RtoAlgorithm", N_("RTO algorithm is %s"), i_rto_alg | I_STATIC},
181     {"RtoMin", "", number},
182     {"RtoMax", "", number},
183     {"MaxConn", "", number},
184     {"ActiveOpens", N_("%u active connections openings"), number},
185     {"PassiveOpens", N_("%u passive connection openings"), number},
186     {"AttemptFails", N_("%u failed connection attempts"), number},
187     {"EstabResets", N_("%u connection resets received"), number},
188     {"CurrEstab", N_("%u connections established"), number},
189     {"InSegs", N_("%u segments received"), number},
190     {"OutSegs", N_("%u segments send out"), number},
191     {"RetransSegs", N_("%u segments retransmited"), number},
192     {"InErrs", N_("%u bad segments received."), number},
193     {"OutRsts", N_("%u resets sent"), number},
194 };
195
196 struct entry Udptab[] =
197 {
198     {"InDatagrams", N_("%u packets received"), number},
199     {"NoPorts", N_("%u packets to unknown port received."), number},
200     {"InErrors", N_("%u packet receive errors"), number},
201     {"OutDatagrams", N_("%u packets sent"), number},
202     {"RcvbufErrors", N_("%u receive buffer errors"), number},
203     {"SndbufErrors", N_("%u send buffer errors"), number},
204  };
205
206 struct entry Udp6tab[] =
207 {
208     {"Udp6InDatagrams", N_("%u packets received"), number},
209     {"Udp6NoPorts", N_("%u packets to unknown port received."), number},
210     {"Udp6InErrors", N_("%u packet receive errors"), number},
211     {"Udp6OutDatagrams", N_("%u packets sent"), number},
212 };
213
214 struct entry Tcpexttab[] =
215 {
216     {"SyncookiesSent", N_("%u SYN cookies sent"), opt_number},
217     {"SyncookiesRecv", N_("%u SYN cookies received"), opt_number},
218     {"SyncookiesFailed", N_("%u invalid SYN cookies received"), opt_number},
219
220     { "EmbryonicRsts", N_("%u resets received for embryonic SYN_RECV sockets"),
221       opt_number },  
222     { "PruneCalled", N_("%u packets pruned from receive queue because of socket"
223                         " buffer overrun"), opt_number },  
224     /* obsolete: 2.2.0 doesn't do that anymore */
225     { "RcvPruned", N_("%u packets pruned from receive queue"), opt_number },
226     { "OfoPruned", N_("%u packets dropped from out-of-order queue because of"
227                       " socket buffer overrun"), opt_number }, 
228     { "OutOfWindowIcmps", N_("%u ICMP packets dropped because they were "
229                              "out-of-window"), opt_number }, 
230     { "LockDroppedIcmps", N_("%u ICMP packets dropped because"
231                              " socket was locked"), opt_number },
232     { "TW", N_("%u TCP sockets finished time wait in fast timer"), opt_number },
233     { "TWRecycled", N_("%u time wait sockets recycled by time stamp"), opt_number }, 
234     { "TWKilled", N_("%u TCP sockets finished time wait in slow timer"), opt_number },
235     { "PAWSPassive", N_("%u passive connections rejected because of"
236                         " time stamp"), opt_number },
237     { "PAWSActive", N_("%u active connections rejected because of "
238                        "time stamp"), opt_number },
239     { "PAWSEstab", N_("%u packets rejects in established connections because of"
240                       " timestamp"), opt_number },
241     { "DelayedACKs", N_("%u delayed acks sent"), opt_number },
242     { "DelayedACKLocked", N_("%u delayed acks further delayed because of"
243                              " locked socket"), opt_number },
244     { "DelayedACKLost", N_("Quick ack mode was activated %u times"), opt_number },
245     { "ListenOverflows", N_("%u times the listen queue of a socket overflowed"),
246       opt_number },
247     { "ListenDrops", N_("%u SYNs to LISTEN sockets dropped"), opt_number },
248     { "TCPPrequeued", N_("%u packets directly queued to recvmsg prequeue."), 
249       opt_number },
250     { "TCPDirectCopyFromBacklog", N_("%u bytes directly in process context from backlog"), opt_number },
251     { "TCPDirectCopyFromPrequeue", N_("%u bytes directly received in process context from prequeue"),
252                                       opt_number },
253     { "TCPPrequeueDropped", N_("%u packets dropped from prequeue"), opt_number },
254     { "TCPHPHits", N_("%u packet headers predicted"), number },
255     { "TCPHPHitsToUser", N_("%u packets header predicted and "
256                             "directly queued to user"), opt_number },
257     { "SockMallocOOM", N_("Ran %u times out of system memory during " 
258                           "packet sending"), opt_number }, 
259     { "TCPPureAcks", N_("%u acknowledgments not containing data payload received"), opt_number },
260     { "TCPHPAcks", N_("%u predicted acknowledgments"), opt_number },
261     { "TCPRenoRecovery", N_("%u times recovered from packet loss due to fast retransmit"), opt_number },
262     { "TCPSackRecovery", N_("%u times recovered from packet loss by selective acknowledgements"), opt_number },
263     { "TCPSACKReneging", N_("%u bad SACK blocks received"), opt_number },
264     { "TCPFACKReorder", N_("Detected reordering %u times using FACK"), opt_number },
265     { "TCPSACKReorder", N_("Detected reordering %u times using SACK"), opt_number },
266     { "TCPTSReorder", N_("Detected reordering %u times using time stamp"), opt_number },
267     { "TCPRenoReorder", N_("Detected reordering %u times using reno fast retransmit"), opt_number },
268     { "TCPFullUndo", N_("%u congestion windows fully recovered without slow start"), opt_number }, 
269     { "TCPPartialUndo", N_("%u congestion windows partially recovered using Hoe heuristic"), opt_number },
270     { "TCPDSackUndo", N_("%u congestion window recovered without slow start using DSACK"), opt_number },
271     { "TCPLossUndo", N_("%u congestion windows recovered without slow start after partial ack"), opt_number },
272     { "TCPLostRetransmits", N_("%u retransmits lost"), opt_number },
273     { "TCPRenoFailures",  N_("%u timeouts after reno fast retransmit"), opt_number },
274     { "TCPSackFailures",  N_("%u timeouts after SACK recovery"), opt_number },
275     { "TCPLossFailures",  N_("%u timeouts in loss state"), opt_number },
276     { "TCPFastRetrans", N_("%u fast retransmits"), opt_number },
277     { "TCPForwardRetrans", N_("%u forward retransmits"), opt_number }, 
278     { "TCPSlowStartRetrans", N_("%u retransmits in slow start"), opt_number },
279     { "TCPTimeouts", N_("%u other TCP timeouts"), opt_number },
280     { "TCPRenoRecoveryFailed", N_("%u reno fast retransmits failed"), opt_number },
281     { "TCPSackRecoveryFail", N_("%u SACK retransmits failed"), opt_number },
282     { "TCPSchedulerFailed", N_("%u times receiver scheduled too late for direct processing"), opt_number },
283     { "TCPRcvCollapsed", N_("%u packets collapsed in receive queue due to low socket buffer"), opt_number },
284     { "TCPDSACKOldSent", N_("%u DSACKs sent for old packets"), opt_number },
285     { "TCPDSACKOfoSent", N_("%u DSACKs sent for out of order packets"), opt_number },
286     { "TCPDSACKRecv", N_("%u DSACKs received"), opt_number },
287     { "TCPDSACKOfoRecv", N_("%u DSACKs for out of order packets received"), opt_number },
288     { "TCPAbortOnSyn", N_("%u connections reset due to unexpected SYN"), opt_number },
289     { "TCPAbortOnData", N_("%u connections reset due to unexpected data"), opt_number },
290     { "TCPAbortOnClose", N_("%u connections reset due to early user close"), opt_number },
291     { "TCPAbortOnMemory", N_("%u connections aborted due to memory pressure"), opt_number },
292     { "TCPAbortOnTimeout", N_("%u connections aborted due to timeout"), opt_number },
293     { "TCPAbortOnLinger", N_("%u connections aborted after user close in linger timeout"), opt_number },
294     { "TCPAbortFailed", N_("%u times unabled to send RST due to no memory"), opt_number }, 
295     { "TCPMemoryPressures", N_("TCP ran low on memory %u times"), opt_number }, 
296     { "TCPLoss", N_("%u TCP data loss events"), opt_number },
297     { "TCPDSACKUndo", N_("%u congestion windows recovered without slow start by DSACK"), 
298         opt_number },
299     { "TCPRenoRecoveryFail", N_("%u classic Reno fast retransmits failed"), opt_number },
300 };
301
302 struct tabtab {
303     char *title;
304     struct entry *tab;
305     size_t size;
306     int *flag; 
307 };
308
309 struct tabtab snmptabs[] =
310 {
311     {"Ip", Iptab, sizeof(Iptab), &f_raw},
312     {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
313     {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
314     {"Udp", Udptab, sizeof(Udptab), &f_udp},
315     {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
316     {NULL}
317 };
318
319 struct tabtab snmp6tabs[] =
320 {
321     {"Ip6", Ip6tab, sizeof(Ip6tab), &f_raw},
322     {"Icmp6", Icmp6tab, sizeof(Icmp6tab), &f_raw},
323     {"Udp6", Udp6tab, sizeof(Udp6tab), &f_udp},
324     {"Tcp6", Tcptab, sizeof(Tcptab), &f_tcp},
325     {NULL}
326 };
327
328 /* XXX IGMP */
329
330 int cmpentries(const void *a, const void *b)
331 {
332     return strcmp(((struct entry *) a)->title, ((struct entry *) b)->title);
333 }
334
335 void printval(struct tabtab *tab, char *title, int val)
336 {
337     struct entry *ent = NULL, key;
338     int type;
339     char buf[512];
340
341     key.title = title;
342         if (tab->tab) 
343             ent = bsearch(&key, tab->tab, tab->size / sizeof(struct entry),
344                           sizeof(struct entry), cmpentries);
345     if (!ent) {                 /* try our best */
346         if (val) 
347                 printf("%*s%s: %d\n", states[state].indent, "", title, val);
348         return;
349     }
350     type = ent->type;
351     if (type & I_STATIC) {
352         type &= ~I_STATIC;
353         if (!print_static)
354             return;
355     }
356     if (*ent->out == '\0')
357         return;
358
359     if (type & I_TITLE) {
360         type &= ~I_TITLE;
361         if (state != type)
362             printf("%*s%s\n", states[state].indent, "", _(states[type].title));
363     }
364     buf[0] = '\0';
365     switch (type) {
366     case opt_number:
367         if (val == 0) 
368             break;
369         /*FALL THOUGH*/
370     case number:
371         snprintf(buf, sizeof(buf), _(ent->out), val);
372         break;
373     case i_forward:
374         type = normal;
375         snprintf(buf, sizeof(buf), _(ent->out), val == 2 ? _("enabled") : _("disabled"));
376         break;
377     case i_outp_icmp:
378     case i_inp_icmp:
379         if (val > 0)
380             snprintf(buf, sizeof(buf), _(ent->out), val);
381         break;
382     case i_rto_alg:             /* XXXX */
383         break;
384     default:
385         abort();
386     }
387     if (buf[0])
388         printf("%*s%s\n", states[type].indent, "", buf);
389
390     state = type;
391 }
392
393 struct tabtab *newtable(struct tabtab *tabs, char *title)
394 {
395     struct tabtab *t;
396         static struct tabtab dummytab;
397         
398     for (t = tabs; t->title; t++) {
399                 if (!strcmp(title, t->title)) {
400                 if (*(t->flag))
401                                 printf("%s:\n", _(title));
402                     state = normal;
403                         return t;
404                 }
405         }
406         if (!f_unknown) 
407                 return NULL; 
408         printf("%s:\n", _(title));
409         dummytab.title = title;
410         dummytab.flag = &f_unknown; 
411         return &dummytab;
412 }
413
414 int process_fd(FILE *f, int all, char *filter)
415 {
416     char buf1[2048], buf2[2048];
417     char *sp, *np, *p;
418     while (fgets(buf1, sizeof buf1, f)) {
419         int endflag;
420         struct tabtab *tab;
421
422         if (buf1[0] == '\n') // skip empty first line in 2.6 kernels
423             continue;
424             
425         if (!fgets(buf2, sizeof buf2, f))
426             break;
427         sp = strchr(buf1, ':');
428         np = strchr(buf2, ':');
429         if (!np || !sp)
430             goto formaterr;
431         *sp = '\0';
432
433         if (!all)
434            if (strncmp(buf1, filter, strlen(filter)))
435                continue;
436
437         tab = newtable(snmptabs, buf1);
438         if (tab == NULL) {
439                 printf("unknown %s\n", buf1);
440                 continue;
441         }
442         np++;
443         sp++;
444
445         endflag = 0;
446         while (!endflag) {
447             sp += strspn(sp, " \t\n"); 
448             np += strspn(np, " \t\n"); 
449             /*if (*np == '\0') goto formaterr; */
450
451             p = sp+strcspn(sp, " \t\n");
452             if (*p == '\0')
453                 endflag = 1;
454             *p = '\0';
455
456             if (*sp != '\0' && *(tab->flag))    
457                 printval(tab, sp, strtoul(np, &np, 10));
458
459             sp = p + 1;
460         }
461     }
462   return 0;
463   
464 formaterr:
465   return -1;
466 }
467
468 void cpytitle(char *original, char *new)
469 {
470      char *ptr = original;
471      while(*ptr != '6' && *ptr != '\0') {
472            *new = *ptr;
473             new++;
474             ptr++;
475      }
476     *new = *ptr;
477     new++;
478     *new = '\0';
479 }
480
481 void process6_fd(FILE *f)
482 {
483    char buf1[1024],buf2[50],buf3[1024];
484    unsigned long val;
485    struct tabtab *tab = NULL;
486    int cpflg = 0;
487
488    while (fgets(buf1, sizeof buf1, f)) {
489           sscanf(buf1, "%s %lu", buf2, &val);
490           if(!cpflg) {
491              cpytitle(buf2, buf3);
492              tab = newtable(snmp6tabs, buf3);
493              cpflg = 1;
494           }
495           if(!strstr(buf2, buf3)) {
496              cpytitle(buf2, buf3);
497              tab = newtable(snmp6tabs, buf3);
498           }
499           if (*(tab->flag))
500              printval(tab, buf2, val);
501    }
502
503 }
504
505 void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
506 {
507     FILE *f;
508
509     f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
510     
511     f = proc_fopen("/proc/net/snmp");
512     if (!f) {
513         perror(_("cannot open /proc/net/snmp"));
514         return;
515     }
516
517     if (process_fd(f, 1, NULL) < 0)
518       fprintf(stderr, _("Problem while parsing /proc/net/snmp\n"));
519
520     if (ferror(f))
521         perror("/proc/net/snmp");
522
523     fclose(f);
524
525     f = proc_fopen("/proc/net/netstat");
526
527     if (f) {
528         if (process_fd(f, 1, NULL) <0)
529           fprintf(stderr, _("Problem while parsing /proc/net/netstat\n"));
530
531         if (ferror(f))
532             perror("/proc/net/netstat");
533     
534         fclose(f);
535     }
536     return;
537 }
538     
539 void parsesnmp6(int flag_raw, int flag_tcp, int flag_udp)
540 {
541     FILE *f;
542
543     f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
544
545     f = fopen("/proc/net/snmp6", "r");
546     if (!f) {
547         perror(_("cannot open /proc/net/snmp6"));
548         return;
549     }
550     process6_fd(f);
551     if (ferror(f))
552         perror("/proc/net/snmp6");
553
554     fclose(f);
555     f = fopen("/proc/net/snmp", "r");
556     if (!f) {
557         perror(_("cannot open /proc/net/snmp"));
558         return;
559     }
560     process_fd(f, 0, "Tcp");
561     if (ferror(f))
562         perror("/proc/net/snmp");
563
564     fclose(f);
565 }
566
567 void inittab(void)
568 {
569     struct tabtab *t;
570
571     /* we sort at runtime because I'm lazy ;) */
572     for (t = snmptabs; t->title; t++)
573         qsort(t->tab, t->size / sizeof(struct entry),
574               sizeof(struct entry), cmpentries);
575 }
576
577 void inittab6(void)
578 {
579     struct tabtab *t;
580
581     for (t = snmp6tabs; t->title; t++)
582         qsort(t->tab, t->size / sizeof(struct entry),
583               sizeof(struct entry), cmpentries);
584 }
585