From 4a3a21a5df8252083cd0bea7a48b0fde93160b5f Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Sat, 15 Jan 2005 12:28:35 +0000 Subject: [PATCH] * Use std::map instead of hand-written hashtable * Use handwritten inode-to-process-mapping instead of the one taken from netstat * Use a #define for using assertions --- Makefile | 10 +++--- connection.cpp | 2 +- connection.h | 2 +- cui.cpp | 24 ++++++++++---- hashtbl.cpp | 89 -------------------------------------------------- hashtest.cpp | 11 ------- inodeproc.cpp | 20 ++++++++++-- nethogs.cpp | 2 ++ nethogs.h | 6 ++-- packet.cpp | 6 ++-- process.cpp | 84 ++++++++++++++--------------------------------- process.h | 13 +++++--- 12 files changed, 83 insertions(+), 186 deletions(-) delete mode 100644 hashtbl.cpp delete mode 100644 hashtest.cpp diff --git a/Makefile b/Makefile index abedbf5..47dd91f 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,9 @@ man8 := $(DESTDIR)/usr/share/man/man8/ all: nethogs -#CFLAGS=-g -Wall -pg -CFLAGS=-O2 -OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o +CFLAGS=-g -Wall -pg +#CFLAGS=-O2 +OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o GCC=g++ .PHONY: tgz @@ -39,10 +39,10 @@ packet.o: packet.cpp packet.h nethogs.h $(GCC) $(CFLAGS) -c packet.cpp connection.o: connection.cpp connection.h nethogs.h $(GCC) $(CFLAGS) -c connection.cpp -hashtbl.o: hashtbl.cpp hashtbl.h nethogs.h - $(GCC) $(CFLAGS) -c hashtbl.cpp decpcap.o: decpcap.c decpcap.h gcc $(CFLAGS) -c decpcap.c +inode2prog.o: inode2prog.cpp inode2prog.h nethogs.h + $(GCC) $(CFLAGS) -c inode2prog.cpp cui.o: cui.cpp cui.h nethogs.h $(GCC) $(CFLAGS) -c cui.cpp -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" diff --git a/connection.cpp b/connection.cpp index f95f02a..22b0906 100644 --- a/connection.cpp +++ b/connection.cpp @@ -62,7 +62,7 @@ u_int32_t PackList::sumanddel (timeval t) Connection::Connection (Packet * packet) { - if (DEBUG) + if (ROBUST) assert (packet != NULL); connections = new ConnList (this, connections); sent_packets = new PackList (); diff --git a/connection.h b/connection.h index c7a3583..d913eef 100644 --- a/connection.h +++ b/connection.h @@ -31,7 +31,7 @@ public: } PackList (Packet * m_val) { - if (DEBUG) + if (ROBUST) assert (m_val != NULL); content = new PackListNode(m_val); } diff --git a/cui.cpp b/cui.cpp index 7ab5d8f..a482259 100644 --- a/cui.cpp +++ b/cui.cpp @@ -25,8 +25,11 @@ public: devicename = n_devicename; m_pid = pid; m_uid = uid; - assert (m_uid >= 0); - assert (m_pid >= 0); + if (ROBUST) + { + assert (m_uid >= 0); + assert (m_pid >= 0); + } } void show (int row); @@ -42,13 +45,16 @@ private: char * uid2username (int uid) { - struct passwd * pwd; + struct passwd * pwd = NULL; /* getpwuid() allocates space for this itself, * which we shouldn't free */ pwd = getpwuid(uid); + + if (ROBUST) + assert (pwd != NULL); + if (pwd == NULL) { - assert(false); return strdup ("unlisted"); } else { return strdup(pwd->pw_name); @@ -58,11 +64,14 @@ char * uid2username (int uid) void Line::show (int row) { - if (DEBUG || tracemode) + if (ROBUST) { assert (m_uid >= 0); assert (m_pid >= 0); + } + if (DEBUG || tracemode) + { std::cout << m_name << '/' << m_pid << '/' << m_uid << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; return; } @@ -172,7 +181,7 @@ void do_refresh() // walk though its connections, summing up their data, and // throwing away connections that haven't received a package // in the last PROCESSTIMEOUT seconds. - if (DEBUG) + if (ROBUST) { assert (curproc != NULL); assert (curproc->getVal() != NULL); @@ -233,7 +242,8 @@ void do_refresh() } } uid_t uid = curproc->getVal()->getUid(); - assert (uid >= 0); + if (ROBUST) + assert (uid >= 0); lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv), curproc->getVal()->pid, uid, curproc->getVal()->devicename); previousproc = curproc; diff --git a/hashtbl.cpp b/hashtbl.cpp deleted file mode 100644 index ac0aced..0000000 --- a/hashtbl.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include "hashtbl.h" - -HashNode::~HashNode () -{ - free (key); - //delete (content); - if (next) - delete (next); -} - -HashTable::HashTable(int n_size) -{ - size = n_size; - table = (HashNode **) malloc (size * sizeof(HashNode *)); - for (unsigned int i=0; i> krightmove; - retval = retval << kleftmove; - retval ^= carry; - retval ^= str[i]; - } - return retval % size; -} - -HashNode * HashTable::newHashNode(char * key, void * content, HashNode * next) -{ - HashNode * retval = new HashNode (); - retval->key = key; - retval->content = content; - retval->next = next; - return retval; -} - - -void HashTable::add(char * key, void * content) -{ - char * localkey = strdup(key); - unsigned int hkey = HashString (localkey); - //std::cout << "LOC: Adding node: " << localkey << " key " << hkey << endl; - table[hkey] = newHashNode(localkey, content, table[hkey]); -} - -void * HashTable::get(char * key) -{ - HashNode * current_node = table[HashString (key)]; - //cout << "looking for node " << HashString (key) << endl; - while (current_node != NULL) - { - //cout << "found node, key = " << current_node->key << endl; - if (strcmp(current_node->key, key) == 0) - { - return current_node->content; - } - current_node = current_node->next; - } - return NULL; -} diff --git a/hashtest.cpp b/hashtest.cpp deleted file mode 100644 index 7084a3b..0000000 --- a/hashtest.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include "hashtbl.h" - -void main () -{ - HashTable * table = new HashTable (10); - table->add("Foo", (void*)"Bar"); - table->add("Baz", (void*)"Qux"); - cout << "Foo is " << (char*)(table->get("Foo")) << endl; -} - diff --git a/inodeproc.cpp b/inodeproc.cpp index 5ff87fb..b1f5438 100644 --- a/inodeproc.cpp +++ b/inodeproc.cpp @@ -1,4 +1,6 @@ /* this comes from netstat.c, but is very useful :)) */ + +/* now unused, replaced by my own implementation */ #include #include #include @@ -10,6 +12,11 @@ #include #include #include +#include +#include + + +#include "nethogs.h" struct proginfo { @@ -153,25 +160,29 @@ static void prg_cache_load(void) continue; errno=0; dirfd=opendir(line); + // dirfd = fd for /proc/4322341/fd if (! dirfd) { if (errno==EACCES) eacces=1; continue; } line[procfdlen] = '/'; + // line =~ /proc/4322341/fd/ cmdlp = NULL; while ((direfd = readdir(dirfd))) { -#ifdef DIRENT_HAVE_D_TYPE_WORKS if (direfd->d_type!=DT_LNK) continue; -#endif if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line)) continue; + // line =~ /proc/4322341/fd/ + // fd/ memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/", PATH_FD_SUFFl+1); strcpy(line + procfdlen + 1, direfd->d_name); lnamelen=readlink(line,lname,sizeof(lname)-1); + fprintf (stdout, "Checking out link: %s\n", line); lname[lnamelen] = '\0'; /*make it a null-terminated string*/ + fprintf (stdout, "Name: %s\n", lname); extract_type_1_socket_inode(lname, &inode); @@ -184,6 +195,7 @@ static void prg_cache_load(void) sizeof(line) - 5) continue; strcpy(line + procfdlen-PATH_FD_SUFFl, PATH_CMDLINE); + fprintf(stdout, "Looking into %s\n", line); fd = open(line, O_RDONLY); if (fd < 0) continue; @@ -204,6 +216,7 @@ static void prg_cache_load(void) snprintf(finbuf, sizeof(finbuf), "%s", cmdlp); int pid; sscanf(direproc->d_name, "%d", &pid); + fprintf(stdout, "Adding: inode %d, buf %s, pid %d\n", inode, finbuf, pid); prg_cache_add(inode, finbuf, pid); } closedir(dirfd); @@ -225,3 +238,6 @@ static void prg_cache_load(void) " will not be shown, you would have to be root to see it all.)\n"); } +void main () { + prg_cache_load(); +} diff --git a/nethogs.cpp b/nethogs.cpp index 9700770..eae5b74 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -203,6 +203,8 @@ public: int main (int argc, char** argv) { + process_init(); + device * devices = NULL; //dp_link_type linktype = dp_link_ethernet; int promisc = 0; diff --git a/nethogs.h b/nethogs.h index cd27223..08f7fd7 100644 --- a/nethogs.h +++ b/nethogs.h @@ -32,10 +32,10 @@ #define DEBUG 0 -// if '0', do extra checks and +// if '1', do extra checks and // assertions. good for finding bugs // at an early stage of development. -// for production, should be 1. +// for production, should be 0. #define ROBUST 1 // 2 times: 32 characters, 7 ':''s, a ':12345'. @@ -93,7 +93,7 @@ public: int result = inet_pton (AF_INET6, address, &addr6); - if (DEBUG) + if (ROBUST) assert (result > 0); sa_family = AF_INET6; } diff --git a/packet.cpp b/packet.cpp index 3c4a96d..601af10 100644 --- a/packet.cpp +++ b/packet.cpp @@ -60,8 +60,8 @@ void getLocal (const char *device) char address [33]; char ifname [9]; int n_results = sscanf (buffer, "%32[0-9a-f] %*d %*d %*d %*d %8[0-9a-zA-Z]", address, ifname); - if (DEBUG) - assert (n_results = 2); + if (ROBUST) + assert (n_results = 2); if (strcmp (stripspaces(ifname), device) == 0) { @@ -178,7 +178,7 @@ bool Packet::isOlderThan (timeval t) { bool Packet::Outgoing () { /* must be initialised with getLocal("eth0:1");) */ - if (DEBUG) + if (ROBUST) assert (local_addrs != NULL); switch (dir) { diff --git a/process.cpp b/process.cpp index 39d1b7b..503b2a9 100644 --- a/process.cpp +++ b/process.cpp @@ -4,30 +4,44 @@ #include #include #include +#include +#include #include #include #include -#include #include #include "process.h" #include "nethogs.h" -#include "inodeproc.cpp" +/* #include "inodeproc.cpp" */ +#include "inode2prog.h" extern local_addr * local_addrs; -; +/* this file includes: + * - code to convert from connection to inode + * - calls to inodeproc to get the pid that belongs to that inode + */ /* * connection-inode table. takes information from /proc/net/tcp. * key contains source ip, source port, destination ip, destination * port in format: '1.2.3.4:5-1.2.3.4:5' */ -//HashTable * conninode = new HashTable (256); std::map conninode; -Process * unknownproc = new Process (0, "", "unknown"); -ProcList * processes = new ProcList (unknownproc, NULL); +/* + * Initialise the global process-list with `the' unknown process + * We must take care this one never gets removed from the list. + */ +Process * unknownproc; +ProcList * processes; + +void process_init () +{ + unknownproc = new Process (0, "", "unknown"); + processes = new ProcList (unknownproc, NULL); +} int Process::getLastPacket() { @@ -35,7 +49,7 @@ int Process::getLastPacket() ConnList * curconn=connections; while (curconn != NULL) { - if (DEBUG) + if (ROBUST) { assert (curconn != NULL); assert (curconn->getVal() != NULL); @@ -156,6 +170,7 @@ void addtoconninode (char * buffer) free (remote_string); } +/* opens /proc/net/tcp[6] and adds its contents line by line */ int addprocinfo (const char * filename) { FILE * procinfo = fopen (filename, "r"); @@ -177,65 +192,14 @@ int addprocinfo (const char * filename) { return 1; } -std::map inodeproc; - -/* this should be done quickly after the packet - * arrived, since the inode disappears from the table - * quickly, too :) */ -struct prg_node * findPID (unsigned long inode) -{ - /* we first look in inodeproc */ - struct prg_node * node = inodeproc[inode]; - - if (node != NULL) - return node; - - node = prg_cache_get(inode); - if (node != NULL && node->pid == 1) - { - if (DEBUG) - std::cout << "ITP: clearing and reloading cache\n"; - prg_cache_clear(); - prg_cache_load(); - node = prg_cache_get(inode); - // this still happens sometimes... - //assert (node->pid != 1); - } - - if (node == NULL) - { - if (DEBUG) - std::cout << "ITP: inode " << inode << " not in inode-to-pid-mapping - reloading." << std::endl; - prg_cache_clear(); - prg_cache_load(); - node = prg_cache_get(inode); - if (node == NULL) - { - if (DEBUG) - std::cout << "ITP: inode " << inode << " STILL not in inode-to-pid-mapping." << std::endl; - return NULL; - } - } - - /* make copy of returned node, add it to map, and return it */ - if (node != NULL) - { - struct prg_node * tempnode = (struct prg_node *) malloc (sizeof (struct prg_node)); - memcpy (tempnode, node, sizeof (struct prg_node)); - inodeproc[inode] = tempnode; - return tempnode; - } - else - return NULL; -} - Process * findProcess (struct prg_node * node) { ProcList * current = processes; while (current != NULL) { Process * currentproc = current->getVal(); - assert (currentproc != NULL); + if (ROBUST) + assert (currentproc != NULL); if (node->pid == currentproc->pid) return current->getVal(); diff --git a/process.h b/process.h index 948fe1b..331c1d2 100644 --- a/process.h +++ b/process.h @@ -14,7 +14,7 @@ class ConnList public: ConnList (Connection * m_val, ConnList * m_next) { - if (DEBUG) + if (ROBUST) assert (m_val != NULL); val = m_val; next = m_next; } @@ -61,8 +61,10 @@ public: uid = 0; } void check () { - assert (pid >= 0); - assert (uid >= 0); + if (ROBUST) { + assert (pid >= 0); + assert (uid >= 0); + } } /* TODO free m_name and m_devicename again in constructor */ ~Process () @@ -97,7 +99,7 @@ class ProcList public: ProcList (Process * m_val, ProcList * m_next) { - if (DEBUG) + if (ROBUST) assert (m_val != NULL); val = m_val; next = m_next; } @@ -110,6 +112,9 @@ private: }; Process * getProcess (Connection * connection, char * devicename = NULL); + +void process_init (); + void refreshconninode (); void procclean ();