diff options
author | Phil Blundell <philb@gnu.org> | 1998-01-08 09:54:43 +0000 |
---|---|---|
committer | Phil Blundell <philb@gnu.org> | 1998-01-08 09:54:43 +0000 |
commit | 1ef3bd3bd1a104a99567cfa90485c89f7edcb812 (patch) | |
tree | f28676e85584644332eb204068cada3fd05a0ac3 /statistics.c | |
download | net-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.tar.gz net-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.tar.bz2 net-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.zip |
Initial revision
Diffstat (limited to 'statistics.c')
-rw-r--r-- | statistics.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/statistics.c b/statistics.c new file mode 100644 index 0000000..dcd9d9a --- /dev/null +++ b/statistics.c @@ -0,0 +1,258 @@ +/* Copyright '97 by Andi Kleen. Subject to the GPL. */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int print_static; + +enum State { number = 0, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg }; +#define normal number + +struct entry { + char *title; + char *out; + enum State type; +}; + +static enum State state; +static int indent[] = { 4, 4, 8, 8, 4 }; /* for each state */ + +#define I_STATIC (1<<16) /* static configuration option. */ +#define I_TITLE (1<<17) + +char *titles[] = { /* for each state */ + NULL, NULL, + "ICMP input histogram:", + "ICMP output histogram:", + NULL +}; + +/* XXX check against the snmp mib rfc. + */ +struct entry Iptab[] = { + { "Forwarding", "Forwarding is %s", i_forward|I_STATIC }, + { "DefaultTTL", "Default TTL is %d", number|I_STATIC }, + { "InReceives", "%d total packets received", number }, + { "InHdrErrors", "%d with invalid headers", number }, + { "InAddrErrors", "%d with invalid addresses", number }, + { "ForwDatagrams", "%d forwarded", number }, + { "InUnknownProtos", "%d with unknown protocol", number }, + { "InDiscards", "%d incoming packets discarded", number }, + { "InDelivers", "%d incoming packets delivered", number }, + { "OutRequests", "%d requests sent out", number }, /*?*/ + { "OutDiscards", "%d outgoing packets dropped", number }, + { "OutNoRoutes", "%d dropped because of missing route", number }, + { "ReasmTimeout", "%d fragments dropped after timeout", number }, + { "ReasmReqds", "%d reassemblies required", number }, /* ? */ + { "ReasmOKs", "%d packets reassembled ok", number }, + { "ReasmFails", "%d packet reassembles failed", number }, + { "FragOKs", "%d fragments received ok", number }, + { "FragFails", "%d fragments failed", number }, + { "FragCreates", "%d fragments created", number } +}; + +struct entry Icmptab[] = { + { "InMsgs", "%d ICMP messages received", number }, + { "InErrors", "%d input ICMP message failed.", number }, + { "InDestUnreachs", "destination unreachable: %d", i_inp_icmp|I_TITLE }, + { "InTimeExcds", "timeout in transit: %d", i_inp_icmp|I_TITLE }, + { "InParmProbs", "wrong parameters: %d", i_inp_icmp|I_TITLE }, /*?*/ + { "InSrcQuenchs", "source quenchs: %d", i_inp_icmp|I_TITLE }, + { "InRedirects", "redirects: %d", i_inp_icmp|I_TITLE }, + { "InEchos", "echo requests: %d", i_inp_icmp|I_TITLE }, + { "InEchoReps", "echo replies: %d", i_inp_icmp|I_TITLE }, + { "InTimestamps", "timestamp request: %d", i_inp_icmp|I_TITLE }, + { "InTimestampReps", "timestamp reply: %d", i_inp_icmp|I_TITLE }, + { "InAddrMasks", "address mask request: %d", i_inp_icmp|I_TITLE }, /*?*/ + { "InAddrMaskReps", "address mask replies", i_inp_icmp|I_TITLE }, /*?*/ + { "OutMsgs", "%d ICMP messages sent", number }, + { "OutErrors", "%d ICMP messages failed", number }, + { "OutDestUnreachs", "destination unreachable: %d", i_outp_icmp|I_TITLE }, + { "OutTimeExcds", "time exceeded: %d", i_outp_icmp|I_TITLE }, + { "OutParmProbs", "wrong parameters: %d", i_outp_icmp|I_TITLE }, /*?*/ + { "OutSrcQuenchs", "source quench: %d", i_outp_icmp|I_TITLE }, + { "OutRedirects", "redirect: %d", i_outp_icmp|I_TITLE }, + { "OutEchos", "echo request: %d", i_outp_icmp|I_TITLE }, + { "OutEchoReps", "echo replies: %d", i_outp_icmp|I_TITLE }, + { "OutTimestamps", "timestamp requests: %d", i_outp_icmp|I_TITLE }, + { "OutTimestampReps", "timestamp replies: %d", i_outp_icmp|I_TITLE }, + { "OutAddrMasks", "address mask requests: %d", i_outp_icmp|I_TITLE }, + { "OutAddrMaskReps", "address mask replies: %d", i_outp_icmp|I_TITLE }, +}; + +struct entry Tcptab[] = { + { "RtoAlgorithm", "RTO algorithm is %s", i_rto_alg|I_STATIC }, + { "RtoMin", "", number }, + { "RtoMax", "", number }, + { "MaxConn", "", number }, + { "ActiveOpens", "%d active opens", number }, + { "PassiveOpens", "%d passive opens", number }, + { "AttemptFails", "%d failed connection attempts", number }, + { "EstabResets", "%d connection resets received", number }, + { "CurrEstab", "%d connections established", number }, + { "InSegs", "%d segments received", number }, + { "OutSegs", "%d segments send out", number }, + { "RetransSegs", "%d segments retransmited", number }, +}; + +struct entry Udptab[] = { + { "InDatagrams", "%d packets received", number }, + { "NoPorts", "%d packets to unknown port received.", number }, + { "InErrors", "%d packet receive errors", number }, + { "OutDatagrams", "%d packets send", number }, +}; + +struct tabtab { + char *title; + struct entry *tab; + size_t size; +}; + +struct tabtab snmptabs[] = { + { "Ip", Iptab, sizeof(Iptab) }, + { "Icmp", Icmptab, sizeof(Icmptab) }, + { "Tcp", Tcptab, sizeof(Tcptab) }, + { "Udp", Udptab, sizeof(Udptab) }, + { NULL } +}; + +static char *skiptok(char *s) +{ + while (!isspace(*s) && *s != '\0') + s++; + return s; +} + + +/* XXX IGMP */ + +int cmpentries(const void *a, const void *b) +{ + return strcmp( ((struct entry*)a)->title, ((struct entry*)b)->title); +} + +void printval(struct tabtab *tab, char *title, int val) +{ + struct entry *ent, key; + int type; + char buf[512]; + + key.title = title; + ent = bsearch(&key, tab->tab, tab->size/sizeof(struct entry), + sizeof(struct entry), cmpentries); + if (!ent) /* XXX warning */ + return; + type = ent->type; + if (type & I_STATIC) { + type &= ~I_STATIC; + if (!print_static) + return; + } + if (*ent->out == '\0') + return; + + if (type & I_TITLE) { + type &= ~I_TITLE; + if (state != type) + printf("%*s%s\n", indent[state], "", titles[type]); + } + + buf[0] = '\0'; + switch (type) { + case number: + sprintf(buf, ent->out, val); + break; + case i_forward: + type = normal; + sprintf(buf, ent->out, val == 2 ? "enabled" : "disabled"); + break; + case i_outp_icmp: + case i_inp_icmp: + if (val > 0) { + sprintf(buf,ent->out, val); + } + break; + case i_rto_alg: /* XXXX */ + break; + default: + abort(); + } + if (buf[0]) + printf("%*s%s\n",indent[type],"", buf); + + state = type; +} + +struct tabtab *newtable(struct tabtab *tabs, char *title) +{ + struct tabtab *t; + + for (t = tabs; t->title; t++) + if (!strcmp(title, t->title)) { + printf("%s:\n", title); + state = normal; + return t; + } + return NULL; +} + +void parsesnmp() +{ + FILE *f; + char buf1[512], buf2[512]; + char *sp, *np, *p; + + f = fopen("/proc/net/snmp", "r"); + if (!f) { + perror("cannot open /proc/net/snmp"); + return; + } + while (fgets(buf1,sizeof buf1,f)) { + int endflag; + struct tabtab *tab; + + if (!fgets(buf2,sizeof buf2,f)) break; + sp = strchr(buf1, ':'); + np = strchr(buf2, ':'); + if (!np || !sp) + goto formaterr; + *sp = '\0'; + tab = newtable(snmptabs, buf1); + if (tab == NULL) /* XXX print warning */ + continue; + np++; sp++; + + endflag = 0; + while (!endflag) { + while(isspace(*sp)) sp++; + while(isspace(*np)) np++; + /*if (*np == '\0') goto formaterr;*/ + + p = skiptok(sp); + if (*p == '\0') endflag=1; + *p = '\0'; + printval(tab, sp, strtoul(np,&np,10)); + sp = p+1; + } + } + if (ferror(f)) + perror("/proc/net/snmp"); + fclose(f); + return; + +formaterr: + perror("error parsing /proc/net/snmp"); + return; +} + +void inittab() +{ + struct tabtab *t; + + /* we sort at runtime because I'm lazy ;) */ + for (t = snmptabs; t->title; t++) + qsort(t->tab, t->size/sizeof(struct entry), + sizeof(struct entry), cmpentries); +} |