From cf2f473cd1d233a5d4b5e9b5add3947f162d56da Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 14 Sep 2004 16:14:23 +0000 Subject: [PATCH] several bugfixes, including some memory management --- DESIGN | 7 +++++ connection.cpp | 30 ++++++++++++++++-- inodeproc.cpp | 1 + nethogs.h | 4 +++ packet.cpp | 3 +- process.cpp | 83 +++++++++++++++++++++----------------------------- process.h | 5 +++ 7 files changed, 82 insertions(+), 51 deletions(-) diff --git a/DESIGN b/DESIGN index ad05912..d6d21d7 100644 --- a/DESIGN +++ b/DESIGN @@ -21,3 +21,10 @@ the unknownproc's connections whenever the connection-to-inode table is refreshed. And maybe, while there are still unknown connections, the connection-to-inode table should be updated regularly. + + +There are some global data structures: +connection.cpp: + connections. 'ConnList' list containting all currently known connections. + A connection removes itself from the global 'connections' list in its + destructor. diff --git a/connection.cpp b/connection.cpp index 97f2072..066d635 100644 --- a/connection.cpp +++ b/connection.cpp @@ -43,7 +43,8 @@ bpf_u_int32 PackList::sumanddel (timeval t) while (current != NULL) { - if (current->val->isOlderThan(t)) + //std::cout << "Comparing " << current->val->time.tv_sec << " <= " << t.tv_sec - PERIOD << endl; + if (current->val->time.tv_sec <= t.tv_sec - PERIOD) { if (current == content) content = NULL; @@ -83,11 +84,36 @@ Connection::~Connection () { if (DEBUG) std::cout << "Deleting connection" << std::endl; - delete refpacket; + /* refpacket is a pointer to one of the packets in the lists, + * so not deleted */ + //delete refpacket; if (sent_packets != NULL) delete sent_packets; if (recv_packets != NULL) delete recv_packets; + + ConnList * curr_conn = connections; + ConnList * prev_conn = NULL; + while (curr_conn != NULL) + { + if (curr_conn->val == this) + { + ConnList * todelete = curr_conn; + curr_conn = curr_conn->next; + if (prev_conn == NULL) + { + connections = curr_conn; + } else { + prev_conn->next = curr_conn; + } + delete (todelete); + } + else + { + prev_conn = curr_conn; + curr_conn = curr_conn->next; + } + } } void Connection::add (Packet * packet) diff --git a/inodeproc.cpp b/inodeproc.cpp index 898494d..5ff87fb 100644 --- a/inodeproc.cpp +++ b/inodeproc.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/nethogs.h b/nethogs.h index e5ffc3c..497f39c 100644 --- a/nethogs.h +++ b/nethogs.h @@ -19,6 +19,10 @@ * after which a process is removed */ #define PROCESSTIMEOUT 150 +/* the amount of time after the last packet was recieved + * after which a connection is removed */ +#define CONNTIMEOUT 50 + /* Set to '0' when compiling for a system that uses Linux Capabilities, * like www.adamantix.org: in that case nethogs shouldn't check if it's * running as root. Take care to give it sufficient privileges though. */ diff --git a/packet.cpp b/packet.cpp index ed7f9b3..7847ef2 100644 --- a/packet.cpp +++ b/packet.cpp @@ -218,7 +218,8 @@ bool sameinaddr(in_addr one, in_addr other) } bool Packet::isOlderThan (timeval t) { - return (time.tv_sec + PERIOD <= t.tv_sec); + std::cout << "Comparing " << time.tv_sec << " <= " << t.tv_sec << endl; + return (time.tv_sec <= t.tv_sec); } bool Packet::Outgoing () { diff --git a/process.cpp b/process.cpp index 435028e..17da47d 100644 --- a/process.cpp +++ b/process.cpp @@ -19,22 +19,6 @@ extern timeval curtime; extern std::string * caption; extern local_addr * local_addrs; -/* takes the text in bufp, and uses it to fill the sockaddr *sap. */ -/*static int INET6_getsock(char *bufp, struct sockaddr *sap) -{ - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *) sap; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = 0; - - if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) - return (-1); - - return 16; -} -*/ - class ProcList { public: @@ -51,25 +35,6 @@ private: Process * val; }; - -struct aftype { - char *name; - char *title; - int af; - int alen; - char *(*print) (unsigned char *); - char *(*sprint) (struct sockaddr *, int numeric); - int (*input) (int type, char *bufp, struct sockaddr *); - void (*herror) (char *text); - int (*rprint) (int options); - int (*rinput) (int typ, int ext, char **argv); - - /* may modify src */ - int (*getmask) (char *src, struct sockaddr * mask, char *name); - - int fd; - char *flag_file; -}; /* * connection-inode table. takes information from /proc/net/tcp. * key contains source ip, source port, destination ip, destination @@ -103,11 +68,9 @@ void addtoconninode (char * buffer) char addr6[INET6_ADDRSTRLEN]; struct in6_addr in6_local; struct in6_addr in6_remote; - extern struct aftype inet6_aftype; - // the following line leaks memory. + // the following line might leak memory. unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); - // TODO check it matched int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*lX:%*lX %*X:%*lX %*lX %*d %*d %ld %*512s\n", local_addr, &local_port, rem_addr, &rem_port, inode); @@ -216,6 +179,13 @@ struct prg_node * findPID (unsigned long inode) { /* find PID */ struct prg_node * node = prg_cache_get(inode); + if (node != NULL && node->pid == 1) + { + prg_cache_clear(); + prg_cache_load(); + node = prg_cache_get(inode); + assert (node->pid != 1); + } if (node == NULL) { @@ -329,7 +299,6 @@ char * uid2username (int uid) } } - class Line { public: @@ -436,6 +405,7 @@ void do_refresh() assert (curproc != NULL); assert (curproc->getVal() != NULL); } + /* do not remove the unknown process */ if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc)) { /* remove connection */ @@ -455,22 +425,39 @@ void do_refresh() continue; } - bpf_u_int32 sum = 0, - sum_local = 0, - sum_conn = 0, - sum_connLocal = 0; + bpf_u_int32 sum_sent = 0, + sum_recv = 0; /* walk though all this process's connections, and sum them * up */ ConnList * curconn = curproc->getVal()->connections; + ConnList * previous = NULL; while (curconn != NULL) { - curconn->getVal()->sumanddel(curtime, &sum, &sum_local); - sum_connLocal += sum_local; - sum_conn += sum; - curconn = curconn->getNext(); + if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) + { + /* stalled connection, remove. */ + ConnList * todelete = curconn; + Connection * conn_todelete = curconn->getVal(); + curconn = curconn->getNext(); + if (todelete == curproc->getVal()->connections) + curproc->getVal()->connections = curconn; + if (previous != NULL) + previous->setNext(curconn); + delete (todelete); + delete (conn_todelete); + } + else + { + bpf_u_int32 sent = 0, recv = 0; + curconn->getVal()->sumanddel(curtime, &sent, &recv); + sum_sent += sent; + sum_recv += recv; + previous = curconn; + curconn = curconn->getNext(); + } } - lines[n] = new Line (curproc->getVal()->name, tokbps(sum_conn), tokbps(sum_connLocal), curproc->getVal()->pid, curproc->getVal()->uid, curproc->getVal()->devicename); + lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv), curproc->getVal()->pid, curproc->getVal()->uid, curproc->getVal()->devicename); previousproc = curproc; curproc = curproc->next; n++; diff --git a/process.h b/process.h index 7b32aac..0f50598 100644 --- a/process.h +++ b/process.h @@ -16,6 +16,11 @@ public: assert (m_val != NULL); val = m_val; next = m_next; } + ~ConnList () + { + /* does not delete its value, to allow a connection to + * remove itself from the global connlist in its destructor */ + } Connection * getVal () { return val;