aa3c3eefeb051c4bb2451b97e1449aad07bf96be
[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.22 2008/10/03 01:07:47 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 };
203
204 struct entry Udp6tab[] =
205 {
206     {"Udp6InDatagrams", N_("%u packets received"), number},
207     {"Udp6NoPorts", N_("%u packets to unknown port received."), number},
208     {"Udp6InErrors", N_("%u packet receive errors"), number},
209     {"Udp6OutDatagrams", N_("%u packets sent"), number},
210 };
211
212 struct entry Tcpexttab[] =
213 {
214     {"SyncookiesSent", N_("%u SYN cookies sent"), opt_number},
215     {"SyncookiesRecv", N_("%u SYN cookies received"), opt_number},
216     {"SyncookiesFailed", N_("%u invalid SYN cookies received"), opt_number},
217
218     { "EmbryonicRsts", N_("%u resets received for embryonic SYN_RECV sockets"),
219       opt_number },  
220     { "PruneCalled", N_("%u packets pruned from receive queue because of socket"
221                         " buffer overrun"), opt_number },  
222     /* obsolete: 2.2.0 doesn't do that anymore */
223     { "RcvPruned", N_("%u packets pruned from receive queue"), opt_number },
224     { "OfoPruned", N_("%u packets dropped from out-of-order queue because of"
225                       " socket buffer overrun"), opt_number }, 
226     { "OutOfWindowIcmps", N_("%u ICMP packets dropped because they were "
227                              "out-of-window"), opt_number }, 
228     { "LockDroppedIcmps", N_("%u ICMP packets dropped because"
229                              " socket was locked"), opt_number },
230     { "TW", N_("%u TCP sockets finished time wait in fast timer"), opt_number },
231     { "TWRecycled", N_("%u time wait sockets recycled by time stamp"), opt_number }, 
232     { "TWKilled", N_("%u TCP sockets finished time wait in slow timer"), opt_number },
233     { "PAWSPassive", N_("%u passive connections rejected because of"
234                         " time stamp"), opt_number },
235     { "PAWSActive", N_("%u active connections rejected because of "
236                        "time stamp"), opt_number },
237     { "PAWSEstab", N_("%u packets rejects in established connections because of"
238                       " timestamp"), opt_number },
239     { "DelayedACKs", N_("%u delayed acks sent"), opt_number },
240     { "DelayedACKLocked", N_("%u delayed acks further delayed because of"
241                              " locked socket"), opt_number },
242     { "DelayedACKLost", N_("Quick ack mode was activated %u times"), opt_number },
243     { "ListenOverflows", N_("%u times the listen queue of a socket overflowed"),
244       opt_number },
245     { "ListenDrops", N_("%u SYNs to LISTEN sockets dropped"), opt_number },
246     { "TCPPrequeued", N_("%u packets directly queued to recvmsg prequeue."), 
247       opt_number },
248     { "TCPDirectCopyFromBacklog", N_("%u bytes directly in process context from backlog"), opt_number },
249     { "TCPDirectCopyFromPrequeue", N_("%u bytes directly received in process context from prequeue"),
250                                       opt_number },
251     { "TCPPrequeueDropped", N_("%u packets dropped from prequeue"), opt_number },
252     { "TCPHPHits", N_("%u packet headers predicted"), number },
253     { "TCPHPHitsToUser", N_("%u packets header predicted and "
254                             "directly queued to user"), opt_number },
255     { "SockMallocOOM", N_("Ran %u times out of system memory during " 
256                           "packet sending"), opt_number }, 
257     { "TCPPureAcks", N_("%u acknowledgments not containing data payload received"), opt_number },
258     { "TCPHPAcks", N_("%u predicted acknowledgments"), opt_number },
259     { "TCPRenoRecovery", N_("%u times recovered from packet loss due to fast retransmit"), opt_number },
260     { "TCPSackRecovery", N_("%u times recovered from packet loss by selective acknowledgements"), opt_number },
261     { "TCPSACKReneging", N_("%u bad SACK blocks received"), opt_number },
262     { "TCPFACKReorder", N_("Detected reordering %u times using FACK"), opt_number },
263     { "TCPSACKReorder", N_("Detected reordering %u times using SACK"), opt_number },
264     { "TCPTSReorder", N_("Detected reordering %u times using time stamp"), opt_number },
265     { "TCPRenoReorder", N_("Detected reordering %u times using reno fast retransmit"), opt_number },
266     { "TCPFullUndo", N_("%u congestion windows fully recovered without slow start"), opt_number }, 
267     { "TCPPartialUndo", N_("%u congestion windows partially recovered using Hoe heuristic"), opt_number },
268     { "TCPDSackUndo", N_("%u congestion window recovered without slow start using DSACK"), opt_number },
269     { "TCPLossUndo", N_("%u congestion windows recovered without slow start after partial ack"), opt_number },
270     { "TCPLostRetransmits", N_("%u retransmits lost"), opt_number },
271     { "TCPRenoFailures",  N_("%u timeouts after reno fast retransmit"), opt_number },
272     { "TCPSackFailures",  N_("%u timeouts after SACK recovery"), opt_number },
273     { "TCPLossFailures",  N_("%u timeouts in loss state"), opt_number },
274     { "TCPFastRetrans", N_("%u fast retransmits"), opt_number },
275     { "TCPForwardRetrans", N_("%u forward retransmits"), opt_number }, 
276     { "TCPSlowStartRetrans", N_("%u retransmits in slow start"), opt_number },
277     { "TCPTimeouts", N_("%u other TCP timeouts"), opt_number },
278     { "TCPRenoRecoveryFailed", N_("%u reno fast retransmits failed"), opt_number },
279     { "TCPSackRecoveryFail", N_("%u SACK retransmits failed"), opt_number },
280     { "TCPSchedulerFailed", N_("%u times receiver scheduled too late for direct processing"), opt_number },
281     { "TCPRcvCollapsed", N_("%u packets collapsed in receive queue due to low socket buffer"), opt_number },
282     { "TCPDSACKOldSent", N_("%u DSACKs sent for old packets"), opt_number },
283     { "TCPDSACKOfoSent", N_("%u DSACKs sent for out of order packets"), opt_number },
284     { "TCPDSACKRecv", N_("%u DSACKs received"), opt_number },
285     { "TCPDSACKOfoRecv", N_("%u DSACKs for out of order packets received"), opt_number },
286     { "TCPAbortOnSyn", N_("%u connections reset due to unexpected SYN"), opt_number },
287     { "TCPAbortOnData", N_("%u connections reset due to unexpected data"), opt_number },
288     { "TCPAbortOnClose", N_("%u connections reset due to early user close"), opt_number },
289     { "TCPAbortOnMemory", N_("%u connections aborted due to memory pressure"), opt_number },
290     { "TCPAbortOnTimeout", N_("%u connections aborted due to timeout"), opt_number },
291     { "TCPAbortOnLinger", N_("%u connections aborted after user close in linger timeout"), opt_number },
292     { "TCPAbortFailed", N_("%u times unabled to send RST due to no memory"), opt_number }, 
293     { "TCPMemoryPressures", N_("TCP ran low on memory %u times"), opt_number }, 
294     { "TCPLoss", N_("%u TCP data loss events"), opt_number },
295     { "TCPDSACKUndo", N_("%u congestion windows recovered without slow start by DSACK"), 
296         opt_number },
297     { "TCPRenoRecoveryFail", N_("%u classic Reno fast retransmits failed"), opt_number },
298 };
299
300 struct tabtab {
301     char *title;
302     struct entry *tab;
303     size_t size;
304     int *flag; 
305 };
306
307 struct tabtab snmptabs[] =
308 {
309     {"Ip", Iptab, sizeof(Iptab), &f_raw},
310     {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
311     {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
312     {"Udp", Udptab, sizeof(Udptab), &f_udp},
313     {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
314     {NULL}
315 };
316
317 struct tabtab snmp6tabs[] =
318 {
319     {"Ip6", Ip6tab, sizeof(Ip6tab), &f_raw},
320     {"Icmp6", Icmp6tab, sizeof(Icmp6tab), &f_raw},
321     {"Udp6", Udp6tab, sizeof(Udp6tab), &f_udp},
322     {"Tcp6", Tcptab, sizeof(Tcptab), &f_tcp},
323     {NULL}
324 };
325
326 /* XXX IGMP */
327
328 int cmpentries(const void *a, const void *b)
329 {
330     return strcmp(((struct entry *) a)->title, ((struct entry *) b)->title);
331 }
332
333 void printval(struct tabtab *tab, char *title, int val)
334 {
335     struct entry *ent = NULL, key;
336     int type;
337     char buf[512];
338
339     key.title = title;
340         if (tab->tab) 
341             ent = bsearch(&key, tab->tab, tab->size / sizeof(struct entry),
342                           sizeof(struct entry), cmpentries);
343     if (!ent) {                 /* try our best */
344         if (val) 
345                 printf("%*s%s: %d\n", states[state].indent, "", title, val);
346         return;
347     }
348     type = ent->type;
349     if (type & I_STATIC) {
350         type &= ~I_STATIC;
351         if (!print_static)
352             return;
353     }
354     if (*ent->out == '\0')
355         return;
356
357     if (type & I_TITLE) {
358         type &= ~I_TITLE;
359         if (state != type)
360             printf("%*s%s\n", states[state].indent, "", _(states[type].title));
361     }
362     buf[0] = '\0';
363     switch (type) {
364     case opt_number:
365         if (val == 0) 
366             break;
367         /*FALL THOUGH*/
368     case number:
369         snprintf(buf, sizeof(buf), _(ent->out), val);
370         break;
371     case i_forward:
372         type = normal;
373         snprintf(buf, sizeof(buf), _(ent->out), val == 2 ? _("enabled") : _("disabled"));
374         break;
375     case i_outp_icmp:
376     case i_inp_icmp:
377         if (val > 0)
378             snprintf(buf, sizeof(buf), _(ent->out), val);
379         break;
380     case i_rto_alg:             /* XXXX */
381         break;
382     default:
383         abort();
384     }
385     if (buf[0])
386         printf("%*s%s\n", states[type].indent, "", buf);
387
388     state = type;
389 }
390
391 struct tabtab *newtable(struct tabtab *tabs, char *title)
392 {
393     struct tabtab *t;
394         static struct tabtab dummytab;
395         
396     for (t = tabs; t->title; t++) {
397                 if (!strcmp(title, t->title)) {
398                 if (*(t->flag))
399                                 printf("%s:\n", _(title));
400                     state = normal;
401                         return t;
402                 }
403         }
404         if (!f_unknown) 
405                 return NULL; 
406         printf("%s:\n", _(title));
407         dummytab.title = title;
408         dummytab.flag = &f_unknown; 
409         return &dummytab;
410 }
411
412 int process_fd(FILE *f, int all, char *filter)
413 {
414     char buf1[2048], buf2[2048];
415     char *sp, *np, *p;
416     while (fgets(buf1, sizeof buf1, f)) {
417         int endflag;
418         struct tabtab *tab;
419
420         if (buf1[0] == '\n') // skip empty first line in 2.6 kernels
421             continue;
422             
423         if (!fgets(buf2, sizeof buf2, f))
424             break;
425         sp = strchr(buf1, ':');
426         np = strchr(buf2, ':');
427         if (!np || !sp)
428             goto formaterr;
429         *sp = '\0';
430
431         if (!all)
432            if (strncmp(buf1, filter, strlen(filter)))
433                continue;
434
435         tab = newtable(snmptabs, buf1);
436         if (tab == NULL) {
437                 printf("unknown %s\n", buf1);
438                 continue;
439         }
440         np++;
441         sp++;
442
443         endflag = 0;
444         while (!endflag) {
445             sp += strspn(sp, " \t\n"); 
446             np += strspn(np, " \t\n"); 
447             /*if (*np == '\0') goto formaterr; */
448
449             p = sp+strcspn(sp, " \t\n");
450             if (*p == '\0')
451                 endflag = 1;
452             *p = '\0';
453
454             if (*sp != '\0' && *(tab->flag))    
455                 printval(tab, sp, strtoul(np, &np, 10));
456
457             sp = p + 1;
458         }
459     }
460   return 0;
461   
462 formaterr:
463   return -1;
464 }
465
466 void cpytitle(char *original, char *new)
467 {
468      char *ptr = original;
469      while(*ptr != '6' && *ptr != '\0') {
470            *new = *ptr;
471             new++;
472             ptr++;
473      }
474     *new = *ptr;
475     new++;
476     *new = '\0';
477 }
478
479 void process6_fd(FILE *f)
480 {
481    char buf1[1024],buf2[50],buf3[1024];
482    unsigned long val;
483    struct tabtab *tab = NULL;
484    int cpflg = 0;
485
486    while (fgets(buf1, sizeof buf1, f)) {
487           sscanf(buf1, "%s %lu", buf2, &val);
488           if(!cpflg) {
489              cpytitle(buf2, buf3);
490              tab = newtable(snmp6tabs, buf3);
491              cpflg = 1;
492           }
493           if(!strstr(buf2, buf3)) {
494              cpytitle(buf2, buf3);
495              tab = newtable(snmp6tabs, buf3);
496           }
497           if (*(tab->flag))
498              printval(tab, buf2, val);
499    }
500
501 }
502
503 void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
504 {
505     FILE *f;
506
507     f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
508     
509     f = proc_fopen("/proc/net/snmp");
510     if (!f) {
511         perror(_("cannot open /proc/net/snmp"));
512         return;
513     }
514
515     if (process_fd(f, 1, NULL) < 0)
516       fprintf(stderr, _("Problem while parsing /proc/net/snmp\n"));
517
518     if (ferror(f))
519         perror("/proc/net/snmp");
520
521     fclose(f);
522
523     f = proc_fopen("/proc/net/netstat");
524
525     if (f) {
526         if (process_fd(f, 1, NULL) <0)
527           fprintf(stderr, _("Problem while parsing /proc/net/netstat\n"));
528
529         if (ferror(f))
530             perror("/proc/net/netstat");
531     
532         fclose(f);
533     }
534     return;
535 }
536     
537 void parsesnmp6(int flag_raw, int flag_tcp, int flag_udp)
538 {
539     FILE *f;
540
541     f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
542
543     f = fopen("/proc/net/snmp6", "r");
544     if (!f) {
545         perror(_("cannot open /proc/net/snmp6"));
546         return;
547     }
548     process6_fd(f);
549     if (ferror(f))
550         perror("/proc/net/snmp6");
551
552     fclose(f);
553     f = fopen("/proc/net/snmp", "r");
554     if (!f) {
555         perror(_("cannot open /proc/net/snmp"));
556         return;
557     }
558     process_fd(f, 0, "Tcp");
559     if (ferror(f))
560         perror("/proc/net/snmp");
561
562     fclose(f);
563 }
564
565 void inittab(void)
566 {
567     struct tabtab *t;
568
569     /* we sort at runtime because I'm lazy ;) */
570     for (t = snmptabs; t->title; t++)
571         qsort(t->tab, t->size / sizeof(struct entry),
572               sizeof(struct entry), cmpentries);
573 }
574
575 void inittab6(void)
576 {
577     struct tabtab *t;
578
579     for (t = snmp6tabs; t->title; t++)
580         qsort(t->tab, t->size / sizeof(struct entry),
581               sizeof(struct entry), cmpentries);
582 }
583