diff --git a/DESIGN b/DESIGN new file mode 100644 index 0000000..ad05912 --- /dev/null +++ b/DESIGN @@ -0,0 +1,23 @@ +Rough design notitions: + +decpcap handles pcap. nethogs.cpp asks to be notified of all IPv4 or IPv6 +TCP packets. + +the IP callbacks store the source and destination addresses into the user +data. The TCP callback makes a Packet out of it, finds the Connection +corresponding to that packet, and adds the packet to the connection. + +If no connection is found, a new one is constructed, and the process +related to that connection is found though getProcess. + +If needed, the screen is refreshed. + +If, in getProcess, no corresponding process is found, the connection is +added to the 'unknown' process. + +To prevent connections from accidentally ending up in the 'unknown' process, +and then staying there indefinitely, we should maybe walk though +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. diff --git a/decpcap.c b/decpcap.c index 5335920..a757a3b 100644 --- a/decpcap.c +++ b/decpcap.c @@ -10,7 +10,7 @@ /* functions to set up a handle (which is basically just a pcap handle) */ -struct dp_handle * dp_open_live(char * device, enum dp_link_type link, int snaplen, int promisc, int to_ms, char * ebuf) +struct dp_handle * dp_open_live(char * device, int snaplen, int promisc, int to_ms, char * ebuf) { struct dp_handle * retval = (struct dp_handle *) malloc (sizeof (struct dp_handle)); pcap_t * temp = pcap_open_live(device, snaplen, promisc, to_ms, ebuf); @@ -27,7 +27,8 @@ struct dp_handle * dp_open_live(char * device, enum dp_link_type link, int snapl { retval->callback[i] = NULL; } - retval->linktype = link; + + retval->linktype = pcap_datalink(retval->pcap_handle); return retval; } @@ -186,11 +187,11 @@ void dp_pcap_callback (u_char * u_handle, const struct pcap_pkthdr * header, con memcpy (userdata_copy, handle->userdata, handle->userdata_size); switch (handle->linktype) { - case (dp_link_ethernet): + case (DLT_EN10MB): dp_parse_ethernet (handle, header, packet); break; - case (dp_link_ppp): - // TODO + case (DLT_PPP): + dp_parse_ppp (handle, header, packet); break; default: // TODO maybe error? or 'other' callback? diff --git a/decpcap.h b/decpcap.h index 2b74baf..6a6b553 100644 --- a/decpcap.h +++ b/decpcap.h @@ -14,11 +14,11 @@ enum dp_packet_type { dp_n_packet_types }; -enum dp_link_type { +/*enum dp_link_type { dp_link_ethernet, dp_link_ppp, dp_n_link_types -}; +};*/ /*struct dp_header { };*/ @@ -29,14 +29,14 @@ typedef int (*dp_callback)(u_char *, const dp_header *, const u_char *); struct dp_handle { pcap_t * pcap_handle; dp_callback callback [dp_n_packet_types]; - enum dp_link_type linktype; + int linktype; u_char * userdata; int userdata_size; }; /* functions to set up a handle (which is basically just a pcap handle) */ -struct dp_handle * dp_open_live(char * device, enum dp_link_type link, int snaplen, int promisc, int to_ms, char * ebuf); +struct dp_handle * dp_open_live(char * device, int snaplen, int promisc, int to_ms, char * ebuf); /* functions to add callbacks */ @@ -49,3 +49,7 @@ void dp_parse (enum dp_packet_type type, void * packet); /* functions to start monitoring */ int dp_dispatch (struct dp_handle * handler, int count, u_char *user, int size); + +/* functions that simply call libpcap */ + +int dp_datalink(struct dp_handle * handle); diff --git a/hashtbl.cpp b/hashtbl.cpp index 75821b8..46ce8f2 100644 --- a/hashtbl.cpp +++ b/hashtbl.cpp @@ -67,7 +67,7 @@ HashNode * HashTable::newHashNode(char * key, void * content, HashNode * next) void HashTable::add(char * key, void * content) { unsigned int hkey = HashString (key); - //cout << "Adding node: " << key << " key " << hkey << endl; + //std::cout << "(STILL)Adding node: " << key << " key " << hkey << endl; table[hkey] = newHashNode(key, content, table[hkey]); } diff --git a/inet6.c b/inet6.c deleted file mode 100644 index 306f65d..0000000 --- a/inet6.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * lib/inet6.c This file contains an implementation of the "INET6" - * support functions for the net-tools. - * (most of it copied from lib/inet.c 1.26). - * - * Version: $Id$ - * - * Author: Fred N. van Kempen, - * Copyright 1993 MicroWalt Corporation - * - * Modified: - *960808 {0.01} Frank Strauss : adapted for IPv6 support - *980701 {0.02} Arnaldo C. Melo: GNU gettext instead of catgets - *990824 Bernd Eckenfels: clear members for selecting v6 address - * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General - * Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at - * your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* -#include "version.h" -#include "net-support.h" -#include "pathnames.h" -#include "intl.h" -#include "util.h" -*/ - -extern int h_errno; /* some netdb.h versions don't export this */ - -static int INET6_resolve(char *name, struct sockaddr_in6 *sin6) -{ - struct addrinfo req, *ai; - int s; - - memset (&req, '\0', sizeof req); - req.ai_family = AF_INET6; - if ((s = getaddrinfo(name, NULL, &req, &ai))) { - fprintf(stderr, "getaddrinfo: %s: %d\n", name, s); - return -1; - } - memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); - - freeaddrinfo(ai); - - return (0); -} - -#ifndef IN6_IS_ADDR_UNSPECIFIED -#define IN6_IS_ADDR_UNSPECIFIED(a) \ - (((__u32 *) (a))[0] == 0 && ((__u32 *) (a))[1] == 0 && \ - ((__u32 *) (a))[2] == 0 && ((__u32 *) (a))[3] == 0) -#endif - - -static int INET6_rresolve(char *name, struct sockaddr_in6 *sin6, int numeric) -{ - int s; - - /* Grmpf. -FvK */ - if (sin6->sin6_family != AF_INET6) { -#ifdef DEBUG - fprintf(stderr, "rresolve: unsupport address family %d !\n", - sin6->sin6_family); -#endif - errno = EAFNOSUPPORT; - return (-1); - } - if (numeric & 0x7FFF) { - inet_ntop(AF_INET6, &sin6->sin6_addr, name, 80); - return (0); - } - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - if (numeric & 0x8000) - strcpy(name, "default"); - else - strcpy(name, "*"); - return (0); - } - - if ((s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), - name, 255 /* !! */ , NULL, 0, 0))) { - fputs("getnameinfo failed\n", stderr); - return -1; - } - return (0); -} - - -static void INET6_reserror(char *text) -{ - herror(text); -} - - -/* Display an Internet socket address. */ -static char *INET6_print(unsigned char *ptr) -{ - static char name[80]; - - inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80); - return name; -} - - -/* Display an Internet socket address. */ -/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */ -static char *INET6_sprint(struct sockaddr *sap, int numeric) -{ - static char buff[128]; - - if (sap->sa_family == 0xFFFF || sap->sa_family == 0) - return safe_strncpy(buff, "[NONE SET]", sizeof(buff)); - if (INET6_rresolve(buff, (struct sockaddr_in6 *) sap, numeric) != 0) - return safe_strncpy(buff, "[UNKNOWN]", sizeof(buff)); - return (buff); -} - - -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; /* ?;) */ -} - -static int INET6_input(int type, char *bufp, struct sockaddr *sap) -{ - switch (type) { - case 1: - return (INET6_getsock(bufp, sap)); - default: - return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap)); - } -} - - -struct aftype inet6_aftype = -{ - "inet6", NULL, /*"IPv6", */ AF_INET6, sizeof(struct in6_addr), - INET6_print, INET6_sprint, INET6_input, INET6_reserror, - INET6_rprint, INET6_rinput, NULL, - - -1, - "/proc/net/if_inet6" -}; diff --git a/nethogs.cpp b/nethogs.cpp index 5c83b5d..d2be013 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -30,7 +30,7 @@ unsigned refreshdelay = 1; bool tracemode = false; bool needrefresh = true; //packet_type packettype = packet_ethernet; -dp_link_type linktype = dp_link_ethernet; +//dp_link_type linktype = dp_link_ethernet; char * currentdevice = NULL; @@ -74,34 +74,6 @@ bool local_addr::contains(const struct in6_addr & n_addr) { return next->contains(n_addr); } -/* deprecated by process_tcp - * void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m_packet) -{ - curtime = header->ts; - - Packet * packet = getPacket (header, m_packet, packettype); - if (packet == NULL) - return; - - Connection * connection = findConnection(packet); - - if (connection != NULL) - { - connection->add(packet); - } else { - connection = new Connection (packet); - if (DEBUG) - std::cerr << "Getting process by connection\n"; - Process * process = getProcess(connection, currentdevice); - } - - if (needrefresh) - { - do_refresh(); - needrefresh = false; - } -}*/ - struct dpargs { int sa_family; in_addr ip_src; @@ -138,8 +110,8 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p } else { /* else: unknown connection, create new */ connection = new Connection (packet); - if (DEBUG) - std::cerr << "Getting process by connection\n"; + //if (DEBUG) + // std::cerr << "Getting process by connection\n"; Process * process = getProcess(connection, currentdevice); } @@ -201,11 +173,12 @@ static void versiondisplay(void) static void help(void) { - std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n"; + //std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n"; + std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [device [device [device ...]]]\n"; std::cerr << " -V : prints version.\n"; std::cerr << " -d : delay for update refresh rate in seconds. default is 1.\n"; std::cerr << " -t : tracemode.\n"; - std::cerr << " -f : format of packets on interface, default is eth.\n"; + //std::cerr << " -f : format of packets on interface, default is eth.\n"; std::cerr << " -p : sniff in promiscious mode (not recommended).\n"; std::cerr << " device : device(s) to monitor. default is eth0\n"; } @@ -222,7 +195,8 @@ public: class handle { public: - handle (dp_handle * m_handle, char * m_devicename = NULL, handle * m_next = NULL) { + handle (dp_handle * m_handle, char * m_devicename = NULL, + handle * m_next = NULL) { content = m_handle; next = m_next; devicename = m_devicename; } dp_handle * content; @@ -257,7 +231,7 @@ int main (int argc, char** argv) refreshdelay=atoi(*argv); } break; - case 'f': if (argv[1]) + /*case 'f': if (argv[1]) { argv++; if (strcmp (*argv, "ppp") == 0) @@ -266,6 +240,7 @@ int main (int argc, char** argv) linktype = dp_link_ethernet; } break; + */ default : help(); exit(0); } @@ -304,7 +279,7 @@ int main (int argc, char** argv) caption->append(" "); } - dp_handle * newhandle = dp_open_live(current_dev->name, linktype, BUFSIZ, promisc, 100, errbuf); + dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf); dp_addcb (newhandle, dp_packet_ip, process_ip); dp_addcb (newhandle, dp_packet_ip6, process_ip6); dp_addcb (newhandle, dp_packet_tcp, process_tcp); diff --git a/process.cpp b/process.cpp index 5221e02..435028e 100644 --- a/process.cpp +++ b/process.cpp @@ -19,7 +19,8 @@ extern timeval curtime; extern std::string * caption; extern local_addr * local_addrs; -static int INET6_getsock(char *bufp, struct sockaddr *sap) +/* 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; @@ -30,13 +31,26 @@ static int INET6_getsock(char *bufp, struct sockaddr *sap) if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) return (-1); - return 16; /* ?;) */ + return 16; } +*/ -static int INET6_input(int type, char *bufp, struct sockaddr *sap) +class ProcList { - return (INET6_getsock(bufp, sap)); -} +public: + ProcList (Process * m_val, ProcList * m_next) + { + if (DEBUG) + assert (m_val != NULL); + val = m_val; next = m_next; + } + Process * getVal () { return val; } + ProcList * getNext () { return next; } + ProcList * next; +private: + Process * val; +}; + struct aftype { char *name; @@ -63,6 +77,9 @@ struct aftype { */ HashTable * conninode = new HashTable (256); +Process * unknownproc = new Process (0, "", "unknown"); +ProcList * processes = new ProcList (unknownproc, NULL); + /* * parses a /proc/net/tcp-line of the form: * sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode @@ -98,12 +115,12 @@ void addtoconninode (char * buffer) fprintf(stderr,"Unexpected buffer: '%s'\n",buffer); exit(0); } - /*if (*inode == 0) { - // This sometimes happens due to what I think is a bug in the - // kernel. See http://lkml.org/lkml/2004/9/10/193. - fprintf(stderr,"Inode zero: '%s'\n",buffer); - exit(0); - }*/ + + if (*inode == 0) { + /* connection is in TIME_WAIT state. We rely on + * the old data still in the table. */ + return; + } if (strlen(local_addr) > 8) { @@ -126,12 +143,12 @@ void addtoconninode (char * buffer) sa_family = AF_INET; } else { /* real IPv6 address */ - inet_ntop(AF_INET6, &in6_local, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &localaddr); - inet_ntop(AF_INET6, &in6_remote, addr6, sizeof(addr6)); - INET6_getsock(addr6, (struct sockaddr *) &remaddr); - localaddr.sin6_family = AF_INET6; - remaddr.sin6_family = AF_INET6; + //inet_ntop(AF_INET6, &in6_local, addr6, sizeof(addr6)); + //INET6_getsock(addr6, (struct sockaddr *) &localaddr); + //inet_ntop(AF_INET6, &in6_remote, addr6, sizeof(addr6)); + //INET6_getsock(addr6, (struct sockaddr *) &remaddr); + //localaddr.sin6_family = AF_INET6; + //remaddr.sin6_family = AF_INET6; result_addr_local = in6_local; result_addr_remote = in6_remote; sa_family = AF_INET6; @@ -157,7 +174,7 @@ void addtoconninode (char * buffer) //if (DEBUG) // fprintf (stderr, "Hashkey: %s\n", hashkey); - conninode->add(hashkey, (void *)inode); + //std::cout << "Adding to conninode\n" << std::endl; /* workaround: sometimes, when a connection is actually from 172.16.3.1 to * 172.16.3.3, packages arrive from 195.169.216.157 to 172.16.3.3, where @@ -165,6 +182,7 @@ void addtoconninode (char * buffer) * interfaces */ struct local_addr * current_local_addr = local_addrs; while (current_local_addr != NULL) { + /* TODO maybe only add the ones with the same sa_family */ hashkey = (char *) malloc (HASHKEYSIZE * sizeof(char)); snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", current_local_addr->string, local_port, remote_string, rem_port); conninode->add(hashkey, (void *)inode); @@ -173,62 +191,125 @@ void addtoconninode (char * buffer) free (remote_string); } -void refreshconninode () -{ - delete conninode; - conninode = new HashTable (256); +int addprocinfo (const char * filename) { + FILE * procinfo = fopen (filename, "r"); char buffer[8192]; - FILE * procinfo = fopen ("/proc/net/tcp", "r"); + if (procinfo == NULL) + return 0; + + fgets(buffer, sizeof(buffer), procinfo); - // TODO use helper function - if (procinfo) + do { - fgets(buffer, sizeof(buffer), procinfo); - do + if (fgets(buffer, sizeof(buffer), procinfo)) + addtoconninode(buffer); + } while (!feof(procinfo)); + + fclose(procinfo); + + return 1; +} + +struct prg_node * findPID (unsigned long inode) +{ + /* find PID */ + struct prg_node * node = prg_cache_get(inode); + + if (node == NULL) + { + prg_cache_clear(); + prg_cache_load(); + node = prg_cache_get(inode); + if (node == NULL) { - if (fgets(buffer, sizeof(buffer), procinfo)) - addtoconninode(buffer); - } while (!feof(procinfo)); - fclose(procinfo); + if (DEBUG) + std::cout << "inode " << inode << " STILL not in inode-to-pid-mapping." << endl; + return NULL; + } + } + return node; +} + +Process * findProcess (struct prg_node * node) +{ + ProcList * current = processes; + while (current != NULL) + { + if (node->pid == current->getVal()->pid) + return current->getVal(); + current = current->next; } - else + return NULL; +} + +/* finds process based on inode, if any */ +Process * findProcess (unsigned long inode) +{ + struct prg_node * node = findPID(inode); + + if (node == NULL) + return NULL; + + return findProcess (node); +} + +/* check if we have identified any previously unknown + * connections are now known */ +void reviewUnknown () +{ + ConnList * curr_conn = unknownproc->connections; + ConnList * previous_conn = NULL; + + while (curr_conn != NULL) { + unsigned long * inode = (unsigned long *) + conninode->get(curr_conn->getVal()->refpacket->gethashstring()); + if (inode != NULL) + { + Process * proc = findProcess (*inode); + if (proc != unknownproc && proc != NULL) + { + /* Yay! - but how could this happen? */ + if (previous_conn != NULL) + { + previous_conn->setNext (curr_conn->getNext()); + proc->connections = new ConnList (curr_conn->getVal(), proc->connections); + delete curr_conn; + curr_conn = previous_conn; + } + else + { + unknownproc->connections = curr_conn->getNext(); + proc->connections = new ConnList (curr_conn->getVal(), proc->connections); + delete curr_conn; + curr_conn = unknownproc->connections; + } + } + } + previous_conn = curr_conn; + if (curr_conn != NULL) + curr_conn = curr_conn->getNext(); + } +} + +void refreshconninode () +{ + /* we don't forget old mappings, just overwrite */ + //delete conninode; + //conninode = new HashTable (256); + + if (! addprocinfo ("/proc/net/tcp")) { std::cout << "Error: couldn't open /proc/net/tcp\n"; exit(0); } + addprocinfo ("/proc/net/tcp6"); + + reviewUnknown(); - procinfo = fopen ("/proc/net/tcp6", "r"); - if (procinfo != NULL) { - fgets(buffer, sizeof(buffer), procinfo); - do { - if (fgets(buffer, sizeof(buffer), procinfo)) - addtoconninode(buffer); - } while (!feof(procinfo)); - fclose (procinfo); - } } -class ProcList -{ -public: - ProcList (Process * m_val, ProcList * m_next) - { - if (DEBUG) - assert (m_val != NULL); - val = m_val; next = m_next; - } - Process * getVal () { return val; } - ProcList * getNext () { return next; } - ProcList * next; -private: - Process * val; -}; - -Process * unknownproc = new Process (0, "", "unknown"); -ProcList * processes = new ProcList (unknownproc, NULL); - float tokbps (bpf_u_int32 bytes) { return (((double)bytes) / PERIOD) / 1024; @@ -262,25 +343,8 @@ public: m_uid = uid; } - void show (int row) - { - if (DEBUG || tracemode) - { - std::cout << m_name << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; - return; - } - - mvprintw (3+row, 0, "%d", m_pid); - char * username = uid2username(m_uid); - mvprintw (3+row, 6, "%s", username); - free (username); - mvprintw (3+row, 6 + 9, "%s", m_name); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2, "%s", devicename); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6, "%10.3f", sent_kbps); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3, "%10.3f", recv_kbps); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB/sec", recv_kbps); - } - + void show (int row); + double sent_kbps; double recv_kbps; private: @@ -290,6 +354,25 @@ private: int m_uid; }; +void Line::show (int row) +{ + if (DEBUG || tracemode) + { + std::cout << m_name << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; + return; + } + + mvprintw (3+row, 0, "%d", m_pid); + char * username = uid2username(m_uid); + mvprintw (3+row, 6, "%s", username); + free (username); + mvprintw (3+row, 6 + 9, "%s", m_name); + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2, "%s", devicename); + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6, "%10.3f", sent_kbps); + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3, "%10.3f", recv_kbps); + mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB/sec", recv_kbps); +} + int GreatestFirst (const void * ma, const void * mb) { Line ** pa = (Line **)ma; @@ -322,9 +405,10 @@ int count_processes() // Display all processes and relevant network traffic using show function void do_refresh() { + refreshconninode(); if (DEBUG || tracemode) { - std::cout << "Refreshing:\n"; + std::cout << "\n\nRefreshing:\n"; } else { @@ -335,7 +419,7 @@ void do_refresh() attroff(A_REVERSE); } ProcList * curproc = processes; - ProcList * lastproc = NULL; + ProcList * previousproc = NULL; int nproc = count_processes(); Line * lines [nproc]; int n = 0, i = 0; @@ -344,9 +428,9 @@ void do_refresh() while (curproc != NULL) { - // walk though its connections, summing up - // their data, and throwing away old stuff. - // if the last packet is older than PROCESSTIMEOUT seconds, discard. + // 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) { assert (curproc != NULL); @@ -354,9 +438,10 @@ void do_refresh() } if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc)) { - if (lastproc) + /* remove connection */ + if (previousproc) { - lastproc->next = curproc->next; + previousproc->next = curproc->next; ProcList * newcur = curproc->next; delete curproc; curproc = newcur; @@ -367,28 +452,34 @@ void do_refresh() curproc = processes; nproc--; } + continue; } - else + + bpf_u_int32 sum = 0, + sum_local = 0, + sum_conn = 0, + sum_connLocal = 0; + + /* walk though all this process's connections, and sum them + * up */ + ConnList * curconn = curproc->getVal()->connections; + while (curconn != NULL) { - bpf_u_int32 sum = 0, - sum_local = 0, - sum_conn = 0, - sum_connLocal = 0; - ConnList * curconn = curproc->getVal()->connections; - while (curconn != NULL) - { - curconn->getVal()->sumanddel(curtime, &sum, &sum_local); - sum_connLocal+=sum_local; - sum_conn+=sum; - 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); - lastproc = curproc; - curproc = curproc->next; - n++; + curconn->getVal()->sumanddel(curtime, &sum, &sum_local); + sum_connLocal += sum_local; + sum_conn += sum; + 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); + previousproc = curproc; + curproc = curproc->next; + n++; } + + /* sort the accumulated lines */ qsort (lines, nproc, sizeof(Line *), GreatestFirst); + + /* print them */ for (i=0; ishow(i); @@ -396,6 +487,16 @@ void do_refresh() sent_global += lines[i]->sent_kbps; delete lines[i]; } + if (tracemode || DEBUG) { + /* print the 'unknown' connections, for debugging */ + ConnList * curr_unknownconn = unknownproc->connections; + while (curr_unknownconn != NULL) { + std::cout << "Unknown connection: " << + curr_unknownconn->getVal()->refpacket->gethashstring() << std::endl; + + curr_unknownconn = curr_unknownconn->getNext(); + } + } if ((!tracemode) && (!DEBUG)){ attron(A_REVERSE); @@ -406,34 +507,22 @@ void do_refresh() } } -/* returns the process from proclist with matching pid +/* + * returns the process from proclist with matching pid * if the inode is not associated with any PID, return the unknown process * if the process is not yet in the proclist, add it */ Process * getProcess (unsigned long inode, char * devicename) { - struct prg_node * node = prg_cache_get(inode); - + struct prg_node * node = findPID(inode); + if (node == NULL) - { - prg_cache_clear(); - prg_cache_load(); - node = prg_cache_get(inode); - if (node == NULL) - { - if (DEBUG) - std::cerr << "inode " << inode << " STILL not in inode-to-program-mapping." << endl; - return unknownproc; - } - } + return unknownproc; - ProcList * current = processes; - while (current != NULL) - { - if (node->pid == current->getVal()->pid) - return current->getVal(); - current = current->next; - } + Process * proc = findProcess (node); + + if (proc != NULL) + return proc; Process * newproc = new Process (inode, strdup(devicename)); newproc->name = strdup(node->name); @@ -459,38 +548,36 @@ Process * getProcess (Connection * connection, char * devicename) { ProcList * curproc = processes; - // see if we already know the inode for this connection - if (DEBUG) - { - std::cout << "New connection reference packet.. "; - std::cout << connection->refpacket << std::endl; - } - - unsigned long * inode = (unsigned long *) conninode->get(connection->refpacket->gethashstring()); + unsigned long * inode = (unsigned long *) + conninode->get(connection->refpacket->gethashstring()); if (inode == NULL) { // no? refresh and check conn/inode table #if DEBUG - std::cerr << "Not in table, refreshing table from /proc/net/tcp.\n"; + std::cerr << "new connection not in connection-to-inode table.\n"; #endif refreshconninode(); - inode = (unsigned long *) conninode->get(connection->refpacket->gethashstring()); + inode = (unsigned long *) + conninode->get(connection->refpacket->gethashstring()); if (inode == NULL) { - /* HACK: the following is a hack for cases where the 'local' addresses - * aren't properly recognised, as is currently the case for IPv6 */ + /* HACK: the following is a hack for cases where the + * 'local' addresses aren't properly recognised, as is + * currently the case for IPv6 */ - /* we reverse the direction of the stream if successful. */ + /* we reverse the direction of the stream if + * successful. */ Packet * reversepacket = connection->refpacket->newInverted(); - //inode = (unsigned long *) conninode->get(reversepacket->gethashstring()); + inode = (unsigned long *) + conninode->get(reversepacket->gethashstring()); if (inode == NULL) { delete reversepacket; if (DEBUG) - std::cerr << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n"; + std::cout << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n"; unknownproc->connections = new ConnList (connection, unknownproc->connections); return unknownproc; } diff --git a/process.h b/process.h index 51e6b91..7b32aac 100644 --- a/process.h +++ b/process.h @@ -20,6 +20,10 @@ public: { return val; } + ConnList * setNext (ConnList * m_next) + { + next = m_next; + } ConnList * getNext () { return next;