diff --git a/Makefile b/Makefile index 85ce99b..696db41 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,10 @@ DESTDIR := /usr/local bin := $(DESTDIR)/bin man8 := $(DESTDIR)/share/man/man8/ -all: nethogs decpcap_test +all: nethogs decpcap_test nethogs_testsum -#CFLAGS=-g -Wall -CFLAGS=-O2 +CFLAGS=-g -Wall +#CFLAGS=-O2 OBJS=packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o .PHONY: tgz @@ -28,6 +28,8 @@ install: nethogs nethogs.8 nethogs: nethogs.cpp $(OBJS) $(CXX) $(CFLAGS) nethogs.cpp $(OBJS) -o nethogs -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" +nethogs_testsum: nethogs_testsum.cpp $(OBJS) + $(CXX) $(CFLAGS) -g nethogs_testsum.cpp $(OBJS) -o nethogs_testsum -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" decpcap_test: decpcap_test.cpp decpcap.o $(CXX) $(CFLAGS) decpcap_test.cpp decpcap.o -o decpcap_test -lpcap -lm diff --git a/connection.cpp b/connection.cpp index afcea4f..e9d9801 100644 --- a/connection.cpp +++ b/connection.cpp @@ -69,19 +69,25 @@ Connection::Connection (Packet * packet) connections = new ConnList (this, connections); sent_packets = new PackList (); recv_packets = new PackList (); + sumSent = 0; + sumRecv = 0; + if (DEBUG) + { + std::cout << "New connection, with package len " << packet->len << std::endl; + } if (packet->Outgoing()) { + sumSent += packet->len; sent_packets->add(packet); refpacket = new Packet (*packet); } else { + sumRecv += packet->len; recv_packets->add(packet); refpacket = packet->newInverted(); } lastpacket = packet->time.tv_sec; if (DEBUG) std::cout << "New reference packet created at " << refpacket << std::endl; - sumSent = 0; - sumRecv = 0; } Connection::~Connection () @@ -126,12 +132,21 @@ void Connection::add (Packet * packet) lastpacket = packet->time.tv_sec; if (packet->Outgoing()) { + if (DEBUG) + { + std::cout << "Outgoing: " << packet->len << std::endl; + } sumSent += packet->len; sent_packets->add (packet); } else { + if (DEBUG) + { + std::cout << "Incoming: " << packet->len << std::endl; + } sumRecv += packet->len; + std::cout << "sumRecv now: " << sumRecv << std::endl; recv_packets->add (packet); } } @@ -168,7 +183,7 @@ Connection * findConnection (Packet * packet) * Returns sum of sent packages (by address) * sum of recieved packages (by address) */ -void Connection::sumanddel (timeval t, u_int32_t * sent, u_int32_t * recv) +void Connection::sumanddel (timeval t, u_int32_t * recv, u_int32_t * sent) { (*sent)=(*recv)=0; diff --git a/connection.h b/connection.h index 486d5f2..6c5925a 100644 --- a/connection.h +++ b/connection.h @@ -73,7 +73,7 @@ public: /* sums up the total bytes used * and removes 'old' packets. */ - void sumanddel(timeval curtime, u_int32_t * sent, u_int32_t * recv); + void sumanddel(timeval curtime, u_int32_t * recv, u_int32_t * sent); /* for checking if a packet is part of this connection */ /* the reference packet is always *outgoing*. */ diff --git a/cui.cpp b/cui.cpp index 4fd7182..62c7b85 100644 --- a/cui.cpp +++ b/cui.cpp @@ -20,15 +20,17 @@ extern Process * unknownip; // sort on sent or received? bool sortRecv = true; // viewMode: kb/s or total -int viewMode = 0; int VIEWMODE_KBPS = 0; int VIEWMODE_TOTAL_KB = 1; -int nViewModes = 2; +int VIEWMODE_TOTAL_B = 2; +int VIEWMODE_TOTAL_MB = 3; +int viewMode = VIEWMODE_TOTAL_B; +int nViewModes = 4; class Line { public: - Line (const char * name, double n_sent_value, double n_recv_value, pid_t pid, uid_t uid, const char * n_devicename) + Line (const char * name, double n_recv_value, double n_sent_value, pid_t pid, uid_t uid, const char * n_devicename) { if (!ROBUST) { @@ -116,9 +118,17 @@ void Line::show (int row) { mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB/sec"); } + else if (viewMode == VIEWMODE_TOTAL_MB) + { + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "MB "); + } else if (viewMode == VIEWMODE_TOTAL_KB) { - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB"); + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB "); + } + else if (viewMode == VIEWMODE_TOTAL_B) + { + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "B "); } } @@ -200,6 +210,14 @@ void ui_tick () } } +float tomb (u_int32_t bytes) +{ + return ((double)bytes) / 1024 / 1024; +} +float tokb (u_int32_t bytes) +{ + return ((double)bytes) / 1024; +} float tokbps (u_int32_t bytes) { return (((double)bytes) / PERIOD) / 1024; @@ -233,7 +251,7 @@ void getkbps (Process * curproc, float * recvd, float * sent) else { u_int32_t sent = 0, recv = 0; - curconn->getVal()->sumanddel(curtime, &sent, &recv); + curconn->getVal()->sumanddel(curtime, &recv, &sent); sum_sent += sent; sum_recv += recv; previous = curconn; @@ -245,7 +263,7 @@ void getkbps (Process * curproc, float * recvd, float * sent) } /** get total values for this process */ -void gettotal(Process * curproc, float * recvd, float * sent) +void gettotal(Process * curproc, u_int32_t * recvd, u_int32_t * sent) { u_int32_t sum_sent = 0, sum_recv = 0; @@ -257,8 +275,39 @@ void gettotal(Process * curproc, float * recvd, float * sent) sum_recv += conn->sumRecv; curconn = curconn->getNext(); } - *recvd = tokbps(sum_recv); - *sent = tokbps(sum_sent); + //std::cout << "Sum sent: " << sum_sent << std::endl; + //std::cout << "Sum recv: " << sum_recv << std::endl; + *recvd = sum_recv; + *sent = sum_sent; +} + +void gettotalmb(Process * curproc, float * recvd, float * sent) +{ + u_int32_t sum_sent = 0, + sum_recv = 0; + gettotal(curproc, &sum_recv, &sum_sent); + *recvd = tomb(sum_recv); + *sent = tomb(sum_sent); +} + +/** get total values for this process */ +void gettotalkb(Process * curproc, float * recvd, float * sent) +{ + u_int32_t sum_sent = 0, + sum_recv = 0; + gettotal(curproc, &sum_recv, &sum_sent); + *recvd = tokb(sum_recv); + *sent = tokb(sum_sent); +} + +void gettotalb(Process * curproc, float * recvd, float * sent) +{ + u_int32_t sum_sent = 0, + sum_recv = 0; + gettotal(curproc, &sum_recv, &sum_sent); + //std::cout << "Total sent: " << sum_sent << std::endl; + *sent = sum_sent; + *recvd = sum_recv; } // Display all processes and relevant network traffic using show function @@ -335,11 +384,23 @@ void do_refresh() if (viewMode == VIEWMODE_KBPS) { + std::cout << "kbps viemode" << std::endl; getkbps (curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_KB) { - gettotal(curproc->getVal(), &value_recv, &value_sent); + //std::cout << "total viemode" << std::endl; + gettotalkb(curproc->getVal(), &value_recv, &value_sent); + } + else if (viewMode == VIEWMODE_TOTAL_MB) + { + //std::cout << "total viemode" << std::endl; + gettotalmb(curproc->getVal(), &value_recv, &value_sent); + } + else if (viewMode == VIEWMODE_TOTAL_B) + { + //std::cout << "total viemode" << std::endl; + gettotalb(curproc->getVal(), &value_recv, &value_sent); } else { @@ -354,7 +415,7 @@ void do_refresh() assert (curproc->getVal()->pid >= 0); assert (n < nproc); } - lines[n] = new Line (curproc->getVal()->name, value_sent, value_recv, + lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent, curproc->getVal()->pid, uid, curproc->getVal()->devicename); previousproc = curproc; curproc = curproc->next; @@ -399,8 +460,12 @@ void do_refresh() if (viewMode == VIEWMODE_KBPS) { mvprintw (3+1+i, 73, "KB/sec "); + } else if (viewMode == VIEWMODE_TOTAL_B) { + mvprintw (3+1+i, 73, "B "); } else if (viewMode == VIEWMODE_TOTAL_KB) { mvprintw (3+1+i, 73, "KB "); + } else if (viewMode == VIEWMODE_TOTAL_MB) { + mvprintw (3+1+i, 73, "MB "); } attroff(A_REVERSE); mvprintw (4+1+i, 0, ""); diff --git a/decpcap.c b/decpcap.c index 8edee55..4194875 100644 --- a/decpcap.c +++ b/decpcap.c @@ -7,6 +7,8 @@ #include #include "decpcap.h" +#define DP_DEBUG 0 + /* functions to set up a handle (which is basically just a pcap handle) */ struct dp_handle * dp_fillhandle(pcap_t * phandle) @@ -92,6 +94,10 @@ void dp_parse_tcp (struct dp_handle * handle, const dp_header * header, const u_ void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct ip * ip = (struct ip *) packet; + if (DP_DEBUG) + { + fprintf(stdout, "Looking at packet with length %ud\n", header->len); + } u_char * payload = (u_char *) packet + sizeof (struct ip); if (handle->callback[dp_packet_ip] != NULL) diff --git a/decpcap.h b/decpcap.h index e67fffc..70475f8 100644 --- a/decpcap.h +++ b/decpcap.h @@ -2,7 +2,7 @@ #include #include -#define DP_ERRBUFF_SIZE PCAP_ERRBUF_SIZE +#define DP_ERRBUF_SIZE PCAP_ERRBUF_SIZE /* definitions */ @@ -24,6 +24,7 @@ enum dp_packet_type { };*/ /*struct dp_header { + * pcap };*/ typedef struct pcap_pkthdr dp_header; diff --git a/decpcap_test.cpp b/decpcap_test.cpp index 9d4eb45..371021f 100644 --- a/decpcap_test.cpp +++ b/decpcap_test.cpp @@ -6,8 +6,8 @@ extern "C" { int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) { std::cout << "Callback for processing TCP packet called" << std::endl; + return 0; } - int main (int argc, char ** argv) { @@ -16,7 +16,7 @@ int main (int argc, char ** argv) std::cout << "Please, enter a filename" << std::endl; } - char* errbuf = new char[DP_ERRBUFF_SIZE]; + char* errbuf = new char[DP_ERRBUF_SIZE]; dp_handle * newhandle = dp_open_offline(argv[1], errbuf); dp_addcb (newhandle, dp_packet_tcp, process_tcp); @@ -25,5 +25,4 @@ int main (int argc, char ** argv) { std::cout << "Error dispatching: " << dp_geterr(newhandle); } - } diff --git a/inode2prog.cpp b/inode2prog.cpp index 8873781..3aa753b 100644 --- a/inode2prog.cpp +++ b/inode2prog.cpp @@ -111,7 +111,7 @@ void get_info_by_linkname (char * pid, char * linkname) { /* updates the `inodeproc' inode-to-prg_node * for all inodes belonging to this PID - * (/proc/pid/fd/*) + * (/proc/pid/fd/42) * */ void get_info_for_pid(char * pid) { size_t dirlen = 10 + strlen(pid); diff --git a/nethogs.cpp b/nethogs.cpp index 723a80c..5820d26 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -345,7 +345,8 @@ int main (int argc, char** argv) if (newhandle != NULL) { /* The following code solves sf.net bug 1019381, but is only available - * in newer versions (from 0.8 it seems) of libpcap */ + * in newer versions (from 0.8 it seems) of libpcap + */ if (dp_setnonblock (newhandle, 1, errbuf) == -1) { // ERROR @@ -359,29 +360,54 @@ int main (int argc, char** argv) signal (SIGALRM, &alarm_cb); signal (SIGINT, &quit_cb); alarm (refreshdelay); + fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n"); + + // Main loop: + // + // Walks though the 'handles' list, which contains handles opened in non-blocking mode. + // This causes the CPU utilisation to go up to 100%. This is tricky: while (1) { + bool packets_read = false; + handle * current_handle = handles; while (current_handle != NULL) { struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); userdata->sa_family = AF_UNSPEC; currentdevice = current_handle->devicename; - dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); + int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); + if (retval == -1 || retval == -2) + { + std::cerr << "Error dispatching" << std::endl; + } + else if (retval != 0) + { + packets_read = true; + } free (userdata); current_handle = current_handle->next; } - if ((!DEBUG)&&(!tracemode)) { + if ((!DEBUG)&&(!tracemode)) + { // handle user input ui_tick(); } + if (needrefresh) { do_refresh(); needrefresh = false; } + + // If no packets were read at all this iteration, pause to prevent 100% + // CPU utilisation; + if (!packets_read) + { + usleep(100); + } } } diff --git a/process.h b/process.h index 40ad202..db826ff 100644 --- a/process.h +++ b/process.h @@ -46,6 +46,7 @@ public: /* the process makes a copy of the device name and name. */ Process (unsigned long m_inode, char * m_devicename, char * m_name = NULL) { + //std::cout << "ARN: Process created with dev " << m_devicename << std::endl; if (DEBUG) std::cout << "PROC: Process created at " << this << std::endl; inode = m_inode;