aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Blundell <philb@gnu.org>1998-01-08 09:54:43 +0000
committerPhil Blundell <philb@gnu.org>1998-01-08 09:54:43 +0000
commit1ef3bd3bd1a104a99567cfa90485c89f7edcb812 (patch)
treef28676e85584644332eb204068cada3fd05a0ac3 /statistics.c
downloadnet-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.tar.gz
net-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.tar.bz2
net-tools-1ef3bd3bd1a104a99567cfa90485c89f7edcb812.zip
Initial revision
Diffstat (limited to 'statistics.c')
-rw-r--r--statistics.c258
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);
+}