diff --git a/Changelog b/Changelog index 5ea28a3..c3b7507 100644 --- a/Changelog +++ b/Changelog @@ -1,8 +1,16 @@ Changelog -2/07/04 (Arnout) +06/07/04 (Arnout) +-added support for monitoring multiple interfaces + at once + +------------------------------------------------- + +02/07/04 (Arnout) -enabled 'q' for quitting +------------------------------------------------- + 29/06/04 (Fabian) <-> 0.5.1 -Adding forceExit when device is ifdown (handle was null => segfault) diff --git a/Makefile b/Makefile index 5d174ca..55a90ed 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ VERSION := 0 SUBVERSION := 6 MINORVERSION := pre -bin := /usr/local/bin -man8 := /usr/local/man/man8/ +bin := $(DESTDIR)/usr/bin +man8 := $(DESTDIR)/usr/share/man/man8/ all: nethogs diff --git a/nethogs.cpp b/nethogs.cpp index 268c33b..43af04e 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -1,6 +1,4 @@ -/* nethogs.cpp - * - */ +/* nethogs.cpp */ #include "nethogs.h" @@ -27,12 +25,20 @@ extern "C" { bool needrefresh = true; unsigned refreshdelay = 1; +char * currentdevice = NULL; + const char version[] = " version " VERSION "." SUBVERSION "." MINORVERSION; timeval curtime; std::string * caption; - +bool local_addr::contains (const in_addr_t & n_addr) { + if (n_addr == addr) + return true; + if (next == NULL) + return false; + return next->contains(n_addr); +} void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m_packet) { @@ -49,8 +55,7 @@ void process (u_char * args, const struct pcap_pkthdr * header, const u_char * m return; } connection = new Connection (packet); - Process * process = getProcess(connection); - //process->addConnection (connection); + Process * process = getProcess(connection, currentdevice); if (needrefresh) { @@ -91,9 +96,29 @@ static void help(void) std::cerr << " device : device to monitor. default is eth0\n"; } +class device { +public: + device (char * m_name, device * m_next = NULL) + { + name = m_name; next = m_next; + } + char * name; + device * next; +}; + +class handle { +public: + handle (pcap_t * m_handle, char * m_devicename = NULL, handle * m_next = NULL) { + content = m_handle; next = m_next; devicename = m_devicename; + } + pcap_t * content; + char * devicename; + handle * next; +}; + int main (int argc, char** argv) { - char* dev = strdup("eth0"); + device * devices = NULL; for (argv++; *argv; argv++) { @@ -118,9 +143,12 @@ int main (int argc, char** argv) } else { - dev = strdup(*argv); + devices = new device (strdup(*argv), devices); } } + + if (devices == NULL) + devices = new device (strdup("eth0")); #if DEBUG #else WINDOW * screen = initscr(); @@ -129,34 +157,57 @@ int main (int argc, char** argv) cbreak(); nodelay(screen, TRUE); #endif - getLocal(dev); - caption = new std::string ("NetHogs"); caption->append(version); caption->append(", running at "); - caption->append(dev); if (NEEDROOT && (getuid() != 0)) forceExit("You need to be root to run NetHogs !"); char errbuf[PCAP_ERRBUF_SIZE]; - pcap_t * handle; - handle = pcap_open_live(dev, BUFSIZ, 0, 1000, errbuf); + handle * handles = NULL; + device * current_dev = devices; + while (current_dev != NULL) { + getLocal(current_dev->name); + caption->append(current_dev->name); + caption->append(" "); - if (!handle) - forceExit("Device is not active"); + pcap_t * newhandle = pcap_open_live(current_dev->name, BUFSIZ, 0, 100, errbuf); + if (newhandle != NULL) + { + handles = new handle (newhandle, current_dev->name, handles); + } + + current_dev = current_dev->next; + } signal (SIGALRM, &alarm_cb); signal (SIGINT, &quit_cb); alarm (refreshdelay); + while (1) { - pcap_dispatch (handle, -1, process, NULL); + handle * current_handle = handles; + while (current_handle != NULL) + { + currentdevice = current_handle->devicename; + pcap_dispatch (current_handle->content, -1, process, NULL); + current_handle = current_handle->next; + } + if (!DEBUG) { switch (getch()) { case 'q': + /* quit */ quit_cb(0); break; + case 's': + /* sort on 'sent' */ + break; + case 'r': + /* sort on 'received' */ + break; + } } if (needrefresh) { diff --git a/nethogs.h b/nethogs.h index c955891..2b38d5e 100644 --- a/nethogs.h +++ b/nethogs.h @@ -1,6 +1,7 @@ #ifndef __NETHOGS_H #define __NETHOGS_H +#include #define _BSD_SOURCE 1 @@ -21,8 +22,20 @@ #define DEBUG 0 -#define PROGNAME_WIDTH 30 +#define PROGNAME_WIDTH 27 void forceExit(const char *msg); +class local_addr { +public: + local_addr (in_addr_t m_addr, local_addr * m_next = NULL) + { + addr = m_addr; + next = m_next; + } + bool contains (const in_addr_t & n_addr); + in_addr_t addr; + local_addr * next; +}; + #endif diff --git a/packet.cpp b/packet.cpp index 98e86f6..2501f07 100644 --- a/packet.cpp +++ b/packet.cpp @@ -9,13 +9,14 @@ #include "nethogs.h" // #include "inet6.c" -struct in_addr * local_addr = NULL; +local_addr * local_addrs = NULL; /* * getLocal * device: This should be device explicit (e.g. eth0:1) * - * ioctl device for address + * uses ioctl to get address of this device, and adds it to the + * local_addrs-list. */ void getLocal (const char *device) { @@ -23,14 +24,6 @@ void getLocal (const char *device) struct ifreq iFreq; struct sockaddr_in *saddr; - if (local_addr != NULL) - { - std::cerr << "getLocal only needs to be called once in connection.cpp" << std::endl; - free (local_addr); - } - - local_addr = (struct in_addr *) malloc (sizeof(struct in_addr)); - if((sock=socket(AF_INET, SOCK_PACKET, htons(0x0806)))<0){ forceExit("creating socket failed while establishing local IP - are you root?"); } @@ -39,7 +32,9 @@ void getLocal (const char *device) forceExit("ioctl failed while establishing local IP"); } saddr=(struct sockaddr_in*)&iFreq.ifr_addr; - (*local_addr)=saddr->sin_addr; + local_addrs = new local_addr (saddr->sin_addr.s_addr, local_addrs); + //malloc + //(*local_addr)=saddr->sin_addr; } typedef u_int32_t tcp_seq; @@ -155,9 +150,9 @@ bool Packet::isOlderThan (timeval t) { bool Packet::Outgoing () { /* must be initialised with getLocal("eth0:1");) */ if (DEBUG) - assert (local_addr != NULL); + assert (local_addrs != NULL); - return (sip.s_addr == local_addr->s_addr); + return (local_addrs->contains(sip.s_addr)); } char * Packet::gethashstring () diff --git a/process.cpp b/process.cpp index c987f3f..48d88aa 100644 --- a/process.cpp +++ b/process.cpp @@ -224,7 +224,7 @@ private: Process * val; }; -Process * unknownproc = new Process (0, "unknown"); +Process * unknownproc = new Process (0, "", "unknown"); ProcList * processes = new ProcList (unknownproc, NULL); float tokbps (bpf_u_int32 bytes) @@ -250,11 +250,12 @@ char * uid2username (int uid) class Line { public: - Line (const char * name, double n_sent_kbps, double n_recv_kbps, int pid, int uid) + Line (const char * name, double n_sent_kbps, double n_recv_kbps, int pid, int uid, const char * n_devicename) { m_name = name; sent_kbps = n_sent_kbps; recv_kbps = n_recv_kbps; + devicename = n_devicename; m_pid = pid; m_uid = uid; } @@ -262,16 +263,17 @@ public: void show (int row) { #if DEBUG - std::cout << m_name << "\t" << m_sent_kbps << "\t" << recv_kbps << std::endl; + std::cout << m_name << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; #else 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, "%10.3f", sent_kbps); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 9 + 3, "%10.3f", recv_kbps); - mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 9 + 3 + 11, "KB/sec", recv_kbps); + 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); // TODO fix //if(m_kbps-upload_kbps>upload_kbps) // mvprintw (3+row, 6 + 20 + PROGNAME_WIDTH + 2, "<<<<"); @@ -284,6 +286,7 @@ public: double recv_kbps; private: const char * m_name; + const char * devicename; int m_pid; int m_uid; }; @@ -322,7 +325,7 @@ void do_refresh() clear(); mvprintw (0, 0, "%s", caption->c_str()); attron(A_REVERSE); - mvprintw (2, 0, " PID USER PROGRAM SENT RECEIVED "); + mvprintw (2, 0, " PID USER PROGRAM DEV SENT RECEIVED "); attroff(A_REVERSE); } else @@ -372,7 +375,7 @@ void do_refresh() 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); + 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++; @@ -390,7 +393,7 @@ void do_refresh() /* returns the process from proclist with matching pid * if none, creates it */ -Process * getProcess (unsigned long inode) +Process * getProcess (unsigned long inode, char * devicename) { struct prg_node * node = prg_cache_get(inode); @@ -411,7 +414,7 @@ Process * getProcess (unsigned long inode) current = current->next; } - Process * newproc = new Process (inode); + Process * newproc = new Process (inode, strdup(devicename)); newproc->name = strdup(node->name); newproc->pid = node->pid; @@ -425,13 +428,17 @@ Process * getProcess (unsigned long inode) return newproc; } -Process * getProcess (Connection * connection) +Process * getProcess (Connection * connection, char * devicename) { ProcList * curproc = processes; // see if we already know the inode for this connection if (DEBUG) - std::cout << "Connection reference packet found at " << connection->refpacket << std::endl; + { + std::cout << "Connection reference packet found at "; + std::cout << connection->refpacket << std::endl; + } + unsigned long * inode = (unsigned long *) conninode->get(connection->refpacket->gethashstring()); if (inode == NULL) @@ -451,7 +458,7 @@ Process * getProcess (Connection * connection) } } - Process * proc = getProcess(*inode); + Process * proc = getProcess(*inode, devicename); proc->incoming = new ConnList (connection, proc->incoming); return proc; } diff --git a/process.h b/process.h index 1922110..bcd87f5 100644 --- a/process.h +++ b/process.h @@ -30,10 +30,11 @@ private: class Process { public: - Process (unsigned long m_inode, char* m_name = NULL) + Process (unsigned long m_inode, char * m_devicename, char * m_name = NULL) { inode = m_inode; name = m_name; + devicename = m_devicename; incoming = NULL; outgoing = NULL; } @@ -56,6 +57,7 @@ public: } const char * name; + const char * devicename; int pid; int uid; @@ -64,7 +66,7 @@ public: ConnList * outgoing; }; -Process * getProcess (Connection * connection); +Process * getProcess (Connection * connection, char * devicename = NULL); void do_refresh (); void procclean ();