summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2006-09-26 17:47:06 +0000
committerDimitri Sokolyuk <demon@dim13.org>2006-09-26 17:47:06 +0000
commit7b744ac520f43417cae31cfa3f2a39d3b1aeb0ab (patch)
tree7feed8e2b1b6904a23e73e8f2c49292bcdd495c8
netmet2
-rw-r--r--Makefile8
-rw-r--r--netmet2.c325
2 files changed, 333 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6882117
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+# $Id$
+
+PROG= netmet2
+LDADD+= -lcurses
+DEBUG+= -Wall
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/netmet2.c b/netmet2.c
new file mode 100644
index 0000000..0b87253
--- /dev/null
+++ b/netmet2.c
@@ -0,0 +1,325 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2006 Dimitri Sokolyuk <demon@vhost.dyndns.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <ifaddrs.h>
+#include <curses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct data {
+ SIMPLEQ_ENTRY(data) link;
+ char name[IFNAMSIZ];
+ u_int flags;
+ struct if_data data;
+ struct if_data odata;
+ WINDOW *win;
+ WINDOW *info, *infobox;
+ WINDOW *plot, *plotbox;
+
+ int plotwidth;
+ int plotheight;
+ u_int (*cur)[2];
+ u_int max[2];
+ u_int maxboth;
+} *datap;
+
+SIMPLEQ_HEAD(, data) head;
+
+int hascolors;
+extern int LINES, COLS;
+
+void initscreen(int);
+void display(void);
+void display2(void);
+void updatedata(int, int);
+int findif(int, int, char **);
+int readdata(int, char *, void *);
+int dumpflags(u_int);
+void unit(WINDOW *, int);
+
+int
+main(int argc, char **argv)
+{
+ int sock;
+ int num;
+ int ch;
+ int del = 2;
+
+ while ((ch = getopt(argc, argv, "s:")) != -1) {
+ switch (ch) {
+ case 's':
+ del = atoi(optarg);
+ break;
+ default:
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ num = findif(sock, argc, argv);
+ printf("%d\n", num);
+ if (num == 0)
+ return -1;
+
+ initscreen(num);
+ curs_set(0);
+
+ for (;;) {
+ updatedata(sock, del);
+ display2();
+ doupdate();
+ sleep(del);
+ }
+
+ close(sock);
+ curs_set(1);
+ endwin();
+ return 0;
+}
+
+void
+initscreen(int n)
+{
+ int winh;
+ int i = 0;
+#define INFOW 16
+#define PLOTW (COLS - INFOW)
+
+ initscr();
+
+ if ((hascolors = has_colors()))
+ start_color();
+ init_pair(1, COLOR_GREEN, COLOR_BLACK);
+ init_pair(2, COLOR_RED, COLOR_BLACK);
+ init_pair(3, COLOR_BLACK, COLOR_GREEN);
+ init_pair(4, COLOR_BLACK, COLOR_RED);
+ init_pair(5, COLOR_BLACK, COLOR_YELLOW);
+
+ winh = LINES / n;
+
+ SIMPLEQ_FOREACH(datap, &head, link) {
+ datap->win = newwin(winh, COLS, (i++) * LINES / n, 0);
+
+ datap->infobox = derwin(datap->win, winh, INFOW, 0, 0);
+
+ box(datap->infobox, 0, 0);
+ mvwprintw(datap->infobox, 0, 1, "[%s]", datap->name);
+ datap->info = derwin(datap->win, winh - 2, INFOW - 2, 1, 1);
+
+ datap->plotbox = derwin(datap->win, winh, PLOTW, 0, INFOW);
+ box(datap->plotbox, 0, 0);
+
+ wmove(datap->plotbox, 0, 1);
+ waddch(datap->plotbox, '[');
+ wattron(datap->plotbox, COLOR_PAIR(1));
+ waddstr(datap->plotbox, "in");
+ wattroff(datap->plotbox, COLOR_PAIR(1));
+ waddch(datap->plotbox, '/');
+ wattron(datap->plotbox, COLOR_PAIR(2));
+ waddstr(datap->plotbox, "out");
+ wattroff(datap->plotbox, COLOR_PAIR(2));
+ waddch(datap->plotbox, ']');
+
+ datap->plot = derwin(datap->win, winh - 2, PLOTW - 2, 1, INFOW + 1);
+
+ datap->plotwidth = PLOTW - 2;
+ datap->plotheight = LINES / n - 2;
+ datap->cur = calloc(datap->plotheight, sizeof(*datap->cur));
+ wnoutrefresh(datap->win);
+ }
+}
+
+void
+display2(void)
+{
+ int i, lenin, lenout, pos;
+ int symin, symout;
+
+ SIMPLEQ_FOREACH(datap, &head, link) {
+ /*
+ mvwprintw(datap->info, 0, 0, "in: %8d", (*datap->cur)[0]);
+ mvwprintw(datap->info, 1, 0, "imax: %8d", datap->max[0]);
+ mvwprintw(datap->info, 2, 0, "out: %8d", (*datap->cur)[1]);
+ mvwprintw(datap->info, 3, 0, "omax: %8d", datap->max[1]);
+ */
+ mvwprintw(datap->info, 0, 0, "in: ");
+ unit(datap->info, (*datap->cur)[0]);
+ mvwprintw(datap->info, 1, 0, "imax:");
+ unit(datap->info, datap->max[0]);
+ mvwprintw(datap->info, 2, 0, "out: ");
+ unit(datap->info, (*datap->cur)[1]);
+ mvwprintw(datap->info, 3, 0, "omax:");
+ unit(datap->info, datap->max[1]);
+ wnoutrefresh(datap->info);
+
+ symin = hascolors ? ' ' : '+';
+ symout = hascolors ? ' ' : '-';
+
+ werase(datap->plot);
+ for (i = 0; i < datap->plotheight; i++) {
+ lenin = datap->maxboth == 0 ? 0 :
+ datap->cur[i][0] * datap->plotwidth / datap->maxboth;
+ lenout = datap->maxboth == 0 ? 0 :
+ datap->cur[i][1] * datap->plotwidth / datap->maxboth;
+
+ pos = datap->plotheight - i - 1;
+ if (lenin > lenout) {
+ wattron(datap->plot, COLOR_PAIR(3));
+ mvwhline(datap->plot, pos, 0, symin, lenin);
+ wattroff(datap->plot, COLOR_PAIR(3));
+
+ wattron(datap->plot, COLOR_PAIR(4));
+ mvwhline(datap->plot, pos, 0, symout, lenout);
+ wattroff(datap->plot, COLOR_PAIR(4));
+ } else if (lenin < lenout) { /* ACS_BLOCK */
+ wattron(datap->plot, COLOR_PAIR(4));
+ mvwhline(datap->plot, pos, 0, symout, lenout);
+ wattroff(datap->plot, COLOR_PAIR(4));
+
+ wattron(datap->plot, COLOR_PAIR(3));
+ mvwhline(datap->plot, pos, 0, symin, lenin);
+ wattroff(datap->plot, COLOR_PAIR(3));
+ } else {
+ wattron(datap->plot, COLOR_PAIR(5));
+ mvwhline(datap->plot, pos, 0, symin, lenin);
+ wattroff(datap->plot, COLOR_PAIR(5));
+ }
+ }
+ wnoutrefresh(datap->plot);
+ }
+}
+
+void
+updatedata(int sock, int del)
+{
+ int i;
+
+ SIMPLEQ_FOREACH(datap, &head, link) {
+ memmove(&datap->odata, &datap->data, sizeof(datap->odata));
+ readdata(sock, datap->name, &datap->data);
+
+ memmove(datap->cur[1], datap->cur[0], sizeof(*datap->cur) * (datap->plotheight - 1));
+ (*datap->cur)[0] = (datap->data.ifi_ibytes - datap->odata.ifi_ibytes) / del;
+ (*datap->cur)[1] = (datap->data.ifi_obytes - datap->odata.ifi_obytes) / del;
+
+ memset(datap->max, 0, sizeof(datap->max));
+ datap->maxboth = 0;
+ for (i = 0; i < datap->plotheight; i++) {
+ if (datap->cur[i][0] > datap->max[0])
+ datap->max[0] = datap->cur[i][0];
+ if (datap->cur[i][1] > datap->max[1])
+ datap->max[1] = datap->cur[i][1];
+
+ if (datap->cur[i][0] > datap->maxboth)
+ datap->maxboth = datap->cur[i][0];
+ if (datap->cur[i][1] > datap->maxboth)
+ datap->maxboth = datap->cur[i][1];
+ }
+ }
+}
+
+int
+findif(int sock, int argc, char **argv)
+{
+ struct ifaddrs *ifap, *ifa;
+ char *oname = NULL;
+ int ret = 0;
+ int i, flag = 0;
+
+ SIMPLEQ_INIT(&head);
+
+ getifaddrs(&ifap);
+
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ struct if_data ifd;
+
+ if ((oname != NULL && strcmp(oname, ifa->ifa_name) == 0)
+ || !(ifa->ifa_flags & IFF_UP)
+ || ifa->ifa_flags & IFF_LOOPBACK)
+ continue;
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], ifa->ifa_name) == 0)
+ flag = 1;
+ }
+ if (argc > 0 && flag == 0)
+ continue;
+ flag = 0;
+
+ oname = ifa->ifa_name;
+
+ if (readdata(sock, ifa->ifa_name, &ifd) == -1
+ || ifd.ifi_type == IFT_PFLOG)
+ continue;
+
+ datap = malloc(sizeof(struct data));
+ datap->flags = ifa->ifa_flags;
+ strlcpy(datap->name, ifa->ifa_name, sizeof(datap->name));
+ memcpy(&datap->data, &ifd, sizeof(datap->data));
+ SIMPLEQ_INSERT_TAIL(&head, datap, link);
+ ++ret;
+ }
+
+ freeifaddrs(ifap);
+ return ret;
+}
+
+int
+readdata(int sock, char *name, void *data)
+{
+ struct ifreq ifr;
+
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = data;
+
+ return ioctl(sock, SIOCGIFDATA, (caddr_t)&ifr);
+}
+
+int
+dumpflags(unsigned int b)
+{
+ char x[] = "M210SOAPNRNPLDBU";
+ int i = 16;
+ char buf[17];
+
+ buf[i] = '\0';
+ for (; i--; b >>= 1)
+ buf[i] = b & 1 ? x[i] : '-';
+ printf("%s\n", buf);
+
+ return 0;
+}
+
+void
+unit(WINDOW *w, int n)
+{
+ int i;
+
+ for (i = 0; n > 1<<10; ++i, n >>= 10)
+ ;
+ wprintw(w, "%4d %cBps", n, " KMG"[i]);
+}