diff --git a/Makefile b/Makefile index f5cfe65..9a47e9f 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ GCC=g++ .PHONY: tgz tgz: clean - cd .. ; tar czvf nethogs-$(VERSION).$(SUBVERSION).$(MINORVERSION).tar.gz nethogs-$(VERSION).$(SUBVERSION)/* + cd .. ; tar czvf nethogs-$(VERSION).$(SUBVERSION).$(MINORVERSION).tar.gz nethogs/* .PHONY: check check: @@ -24,7 +24,7 @@ install: nethogs nethogs.8 cp nethogs.8 $(man8) nethogs: nethogs.cpp $(OBJS) - $(GCC) $(CFLAGS) nethogs.cpp $(OBJS) -o nethogs -lpcap -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" + $(GCC) $(CFLAGS) nethogs.cpp $(OBJS) -o nethogs -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" #-lefence diff --git a/connection.cpp b/connection.cpp index 066d635..f95f02a 100644 --- a/connection.cpp +++ b/connection.cpp @@ -21,7 +21,7 @@ void PackList::add (Packet * p) { if (content == NULL) { - content = new PackListNode (p); + content = new PackListNode (new Packet (*p)); return; } @@ -31,13 +31,13 @@ void PackList::add (Packet * p) return; } - content = new PackListNode(p, content); + content = new PackListNode(new Packet (*p), content); } /* sums up the total bytes used and removes 'old' packets */ -bpf_u_int32 PackList::sumanddel (timeval t) +u_int32_t PackList::sumanddel (timeval t) { - bpf_u_int32 retval = 0; + u_int32_t retval = 0; PackListNode * current = content; PackListNode * previous = NULL; @@ -84,9 +84,9 @@ Connection::~Connection () { if (DEBUG) std::cout << "Deleting connection" << std::endl; - /* refpacket is a pointer to one of the packets in the lists, - * so not deleted */ - //delete refpacket; + /* refpacket is not a pointer to one of the packets in the lists + * so deleted */ + delete (refpacket); if (sent_packets != NULL) delete sent_packets; if (recv_packets != NULL) @@ -116,6 +116,7 @@ Connection::~Connection () } } +/* the packet will be freed by the calling code */ void Connection::add (Packet * packet) { lastpacket = packet->time.tv_sec; @@ -139,10 +140,14 @@ Connection * findConnection (Packet * packet) /* the reference packet is always *outgoing* */ if ((packet->match(current->val->refpacket)) || (invertedPacket->match(current->val->refpacket))) + { + delete invertedPacket; return current->val; + } current = current->next; } + delete invertedPacket; return NULL; } @@ -155,7 +160,7 @@ Connection * findConnection (Packet * packet) * Returns sum of sent packages (by address) * sum of recieved packages (by address) */ -void Connection::sumanddel (timeval t, bpf_u_int32 * sent, bpf_u_int32 * recv) +void Connection::sumanddel (timeval t, u_int32_t * sent, u_int32_t * recv) { (*sent)=(*recv)=0; diff --git a/connection.h b/connection.h index 693316a..c7a3583 100644 --- a/connection.h +++ b/connection.h @@ -42,7 +42,7 @@ public: } /* sums up the total bytes used and removes 'old' packets */ - bpf_u_int32 sumanddel (timeval t); + u_int32_t sumanddel (timeval t); void add (Packet * p); private: @@ -71,7 +71,7 @@ public: /* sums up the total bytes used * and removes 'old' packets. */ - void sumanddel(timeval curtime, bpf_u_int32 * sent, bpf_u_int32 * recv); + void sumanddel(timeval curtime, u_int32_t * sent, u_int32_t * recv); /* for checking if a packet is part of this connection */ /* the reference packet is always *outgoing*. */ diff --git a/hashtbl.cpp b/hashtbl.cpp index 46ce8f2..9a699d9 100644 --- a/hashtbl.cpp +++ b/hashtbl.cpp @@ -66,9 +66,10 @@ HashNode * HashTable::newHashNode(char * key, void * content, HashNode * next) void HashTable::add(char * key, void * content) { - unsigned int hkey = HashString (key); - //std::cout << "(STILL)Adding node: " << key << " key " << hkey << endl; - table[hkey] = newHashNode(key, content, table[hkey]); + char * localkey = strdup(key); + unsigned int hkey = HashString (localkey); + //std::cout << "(STILL)Adding node: " << localkey << " key " << hkey << endl; + table[hkey] = newHashNode(localkey, content, table[hkey]); } void * HashTable::get(char * key) diff --git a/hashtbl.h b/hashtbl.h index a0ab12b..835462d 100644 --- a/hashtbl.h +++ b/hashtbl.h @@ -16,6 +16,9 @@ class HashTable public: HashTable(int n_size); ~HashTable(); + + /* after calling 'add', the calling application + * must free the string */ void add(char * key, void * content); void * get(char * key); diff --git a/nethogs.cpp b/nethogs.cpp index d2be013..41c38c8 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -93,13 +93,14 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p switch (args->sa_family) { case (AF_INET): - //packet = new Packet (args->ip_src, ntohs(tcp->th_sport), args->ip_dst, ntohs(tcp->th_dport), header->len, header->ts); packet = new Packet (args->ip_src, ntohs(tcp->source), args->ip_dst, ntohs(tcp->dest), header->len, header->ts); break; case (AF_INET6): packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts); break; } + //if (DEBUG) + // std::cout << "Got packet from " << packet->gethashstring() << std::endl; Connection * connection = findConnection(packet); @@ -107,11 +108,10 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p { /* add packet to the connection */ connection->add(packet); + delete packet; } else { /* else: unknown connection, create new */ connection = new Connection (packet); - //if (DEBUG) - // std::cerr << "Getting process by connection\n"; Process * process = getProcess(connection, currentdevice); } @@ -152,6 +152,7 @@ void quit_cb (int i) procclean(); clear(); endwin(); + delete caption; exit(0); } @@ -310,9 +311,8 @@ int main (int argc, char** argv) struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); userdata->sa_family = AF_UNSPEC; currentdevice = current_handle->devicename; - /* TODO maybe userdata needs be reset every now and then? */ dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); - /* dp_dispatch handles deletion of the userdata */ + free (userdata); current_handle = current_handle->next; } diff --git a/packet.cpp b/packet.cpp index 7847ef2..fcb6494 100644 --- a/packet.cpp +++ b/packet.cpp @@ -10,6 +10,7 @@ #include #include #include +#include // #include "inet6.c" local_addr * local_addrs = NULL; @@ -124,77 +125,22 @@ struct tcp_hdr { u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; -/* Packet 'Constructor' - but returns NULL on failure */ -/* deprecated by decpcap -Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type headertype) -{ - int packettype; - int headersize; - - switch (headertype) - { - case (packet_ethernet): - { - const struct ether_header * ethernet = (struct ether_header *)packet; - packettype = ethernet->ether_type; - headersize = sizeof (struct ether_header); - }; break; - case (packet_ppp): - { - const struct ppp_header * ppp = (struct ppp_header *)packet; - packettype = ppp->packettype; - headersize = sizeof (struct ppp_header); - }; break; - } - if (packettype == 0x0008) - { - const struct ip * ip = (struct ip *)(packet + headersize); - if (ip->ip_p != 6) - { -#if DEBUG - std::cerr << "Dropped non-tcp IPv4 packet of type " << (int)(ip->ip_p) << std::endl; -#endif - return NULL; - } - const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + headersize + sizeof(struct ip)); - return new Packet (ip->ip_src, ntohs(tcp->th_sport), ip->ip_dst, ntohs(tcp->th_dport), header->len, header->ts); - } else if (packettype == 0xDD86) { - const struct ip6_hdr * ip6 = (struct ip6_hdr *)(packet + headersize); - if ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt != 0x06) - { - // TODO maybe we need to skip over some headers? -#if DEBUG - std::cerr << "Dropped non-tcp IPv6 header of type " << (int)((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt) << std::endl; -#endif - return NULL; - } - const struct tcp_hdr * tcp = (struct tcp_hdr *)(packet + headersize + sizeof(ip6_hdr)); - - return new Packet (ip6->ip6_src, ntohs(tcp->th_sport), - ip6->ip6_dst, ntohs(tcp->th_dport), header->len, header->ts); - } - -#if DEBUG - std::cerr << "Dropped non-ip packet of type " << packettype << std::endl; -#endif - return NULL; -} -*/ - -Packet::Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, bpf_u_int32 m_len, timeval m_time, direction m_dir) +Packet::Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction m_dir) { sip = m_sip; sport = m_sport; dip = m_dip; dport = m_dport; len = m_len; time = m_time; dir = m_dir; sa_family = AF_INET; + hashstring = NULL; } -Packet::Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, bpf_u_int32 m_len, timeval m_time, direction m_dir) +Packet::Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction m_dir) { sip6 = m_sip; sport = m_sport; dip6 = m_dip; dport = m_dport; len = m_len; time = m_time; dir = m_dir; sa_family = AF_INET6; + hashstring = NULL; } Packet * Packet::newInverted () { @@ -206,11 +152,19 @@ Packet * Packet::newInverted () { } /* constructs returns a new Packet() structure with the same contents as this one */ -/*Packet::Packet (const Packet &old_packet) { - sip = old_packet.sip; sport = old_packet.sport; - dip = old_packet.dip; dport = old_packet.dport; - len = old_packet.len; time = old_packet.time; -}*/ +Packet::Packet (const Packet &old_packet) { + sip = old_packet.sip; sport = old_packet.sport; + sip6 = old_packet.sip6; + dip6 = old_packet.dip6; + dip = old_packet.dip; dport = old_packet.dport; + len = old_packet.len; time = old_packet.time; + sa_family = old_packet.sa_family; + if (old_packet.hashstring == NULL) + hashstring = NULL; + else + hashstring = strdup(old_packet.hashstring); + +} bool sameinaddr(in_addr one, in_addr other) { @@ -266,11 +220,20 @@ bool Packet::Outgoing () { /* returns the packet in '1.2.3.4:5-1.2.3.4:5'-form, for use in the 'conninode' table */ /* '1.2.3.4' should be the local address. */ +/* the calling code should take care of deletion of the hash string */ char * Packet::gethashstring () { - char * retval = (char *) malloc (HASHKEYSIZE * sizeof(char)); - char * local_string = (char*) malloc (50); - char * remote_string = (char*) malloc (50); + if (hashstring != NULL) + { + if (DEBUG) + std::cout << "Returning cached hash string: " << hashstring << std::endl; + return hashstring; + } + + hashstring = (char *) malloc (HASHKEYSIZE * sizeof(char)); + + char * local_string = (char *) malloc (50); + char * remote_string = (char *) malloc (50); if (sa_family == AF_INET) { inet_ntop(sa_family, &sip, local_string, 49); inet_ntop(sa_family, &dip, remote_string, 49); @@ -279,13 +242,15 @@ char * Packet::gethashstring () inet_ntop(sa_family, &dip6, remote_string, 49); } if (Outgoing()) { - snprintf(retval, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, sport, remote_string, dport); + snprintf(hashstring, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, sport, remote_string, dport); } else { - snprintf(retval, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", remote_string, dport, local_string, sport); + snprintf(hashstring, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", remote_string, dport, local_string, sport); } free (local_string); free (remote_string); - return retval; + if (DEBUG) + std::cout << "Returning newly created hash string: " << hashstring << std::endl; + return hashstring; } /* 2 packets match if they have the same diff --git a/packet.h b/packet.h index 58f15bb..85b9570 100644 --- a/packet.h +++ b/packet.h @@ -9,11 +9,6 @@ #include #include "nethogs.h" -extern "C" -{ - #include -} - enum direction { dir_unknown, dir_incoming, @@ -33,12 +28,21 @@ public: in_addr dip; unsigned short sport; unsigned short dport; - bpf_u_int32 len; + u_int32_t len; timeval time; - Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, bpf_u_int32 m_len, timeval m_time, direction dir = dir_unknown); - Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, bpf_u_int32 m_len, timeval m_time, direction dir = dir_unknown); - /* using default copy constructor */ + Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction dir = dir_unknown); + Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction dir = dir_unknown); + /* copy constructor */ + Packet (const Packet &old); + ~Packet () + { + if (hashstring != NULL) + { + free (hashstring); + hashstring = NULL; + } + } /* Packet (const Packet &old_packet); */ /* copy constructor that turns the packet around */ Packet * newInverted (); @@ -53,8 +57,7 @@ public: private: direction dir; short int sa_family; + char * hashstring; }; -//Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type packettype); - #endif diff --git a/process.cpp b/process.cpp index 17da47d..7e24d58 100644 --- a/process.cpp +++ b/process.cpp @@ -68,7 +68,8 @@ void addtoconninode (char * buffer) char addr6[INET6_ADDRSTRLEN]; struct in6_addr in6_local; struct in6_addr in6_remote; - // the following line might leak memory. + + // the following leaks some memory. unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); 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", @@ -139,6 +140,8 @@ void addtoconninode (char * buffer) //std::cout << "Adding to conninode\n" << std::endl; + conninode->add(hashkey, (void *)inode); + /* 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 * 172.16.3.1 and 195.169.216.157 are the local addresses of different @@ -146,11 +149,11 @@ void addtoconninode (char * buffer) 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); current_local_addr = current_local_addr->next; } + free (hashkey); free (remote_string); } @@ -184,7 +187,8 @@ struct prg_node * findPID (unsigned long inode) prg_cache_clear(); prg_cache_load(); node = prg_cache_get(inode); - assert (node->pid != 1); + // this still happens sometimes... + //assert (node->pid != 1); } if (node == NULL) @@ -280,7 +284,7 @@ void refreshconninode () } -float tokbps (bpf_u_int32 bytes) +float tokbps (u_int32_t bytes) { return (((double)bytes) / PERIOD) / 1024; } @@ -327,7 +331,7 @@ void Line::show (int row) { if (DEBUG || tracemode) { - std::cout << m_name << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; + std::cout << m_name << '/' << m_pid << '/' << m_uid << "\t" << sent_kbps << "\t" << recv_kbps << std::endl; return; } @@ -425,8 +429,8 @@ void do_refresh() continue; } - bpf_u_int32 sum_sent = 0, - sum_recv = 0; + u_int32_t sum_sent = 0, + sum_recv = 0; /* walk though all this process's connections, and sum them * up */ @@ -449,7 +453,7 @@ void do_refresh() } else { - bpf_u_int32 sent = 0, recv = 0; + u_int32_t sent = 0, recv = 0; curconn->getVal()->sumanddel(curtime, &sent, &recv); sum_sent += sent; sum_recv += recv; diff --git a/process.h b/process.h index 0f50598..e0c3ad0 100644 --- a/process.h +++ b/process.h @@ -47,6 +47,8 @@ public: name = m_name; devicename = m_devicename; connections = NULL; + pid = 0; + uid = 0; } int getLastPacket () {