cleanups. mainly memory leak fixes

This commit is contained in:
Arnout Engelen
2004-09-14 19:24:01 +00:00
parent cf2f473cd1
commit fc333df257
10 changed files with 92 additions and 109 deletions

View File

@@ -13,7 +13,7 @@ GCC=g++
.PHONY: tgz .PHONY: tgz
tgz: clean 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 .PHONY: check
check: check:
@@ -24,7 +24,7 @@ install: nethogs nethogs.8
cp nethogs.8 $(man8) cp nethogs.8 $(man8)
nethogs: nethogs.cpp $(OBJS) 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 #-lefence

View File

@@ -21,7 +21,7 @@ void PackList::add (Packet * p)
{ {
if (content == NULL) if (content == NULL)
{ {
content = new PackListNode (p); content = new PackListNode (new Packet (*p));
return; return;
} }
@@ -31,13 +31,13 @@ void PackList::add (Packet * p)
return; return;
} }
content = new PackListNode(p, content); content = new PackListNode(new Packet (*p), content);
} }
/* sums up the total bytes used and removes 'old' packets */ /* 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 * current = content;
PackListNode * previous = NULL; PackListNode * previous = NULL;
@@ -84,9 +84,9 @@ Connection::~Connection ()
{ {
if (DEBUG) if (DEBUG)
std::cout << "Deleting connection" << std::endl; std::cout << "Deleting connection" << std::endl;
/* refpacket is a pointer to one of the packets in the lists, /* refpacket is not a pointer to one of the packets in the lists
* so not deleted */ * so deleted */
//delete refpacket; delete (refpacket);
if (sent_packets != NULL) if (sent_packets != NULL)
delete sent_packets; delete sent_packets;
if (recv_packets != NULL) if (recv_packets != NULL)
@@ -116,6 +116,7 @@ Connection::~Connection ()
} }
} }
/* the packet will be freed by the calling code */
void Connection::add (Packet * packet) void Connection::add (Packet * packet)
{ {
lastpacket = packet->time.tv_sec; lastpacket = packet->time.tv_sec;
@@ -139,10 +140,14 @@ Connection * findConnection (Packet * packet)
/* the reference packet is always *outgoing* */ /* the reference packet is always *outgoing* */
if ((packet->match(current->val->refpacket)) if ((packet->match(current->val->refpacket))
|| (invertedPacket->match(current->val->refpacket))) || (invertedPacket->match(current->val->refpacket)))
{
delete invertedPacket;
return current->val; return current->val;
}
current = current->next; current = current->next;
} }
delete invertedPacket;
return NULL; return NULL;
} }
@@ -155,7 +160,7 @@ Connection * findConnection (Packet * packet)
* Returns sum of sent packages (by address) * Returns sum of sent packages (by address)
* sum of recieved 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; (*sent)=(*recv)=0;

View File

@@ -42,7 +42,7 @@ public:
} }
/* sums up the total bytes used and removes 'old' packets */ /* 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); void add (Packet * p);
private: private:
@@ -71,7 +71,7 @@ public:
/* sums up the total bytes used /* sums up the total bytes used
* and removes 'old' packets. */ * 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 */ /* for checking if a packet is part of this connection */
/* the reference packet is always *outgoing*. */ /* the reference packet is always *outgoing*. */

View File

@@ -66,9 +66,10 @@ HashNode * HashTable::newHashNode(char * key, void * content, HashNode * next)
void HashTable::add(char * key, void * content) void HashTable::add(char * key, void * content)
{ {
unsigned int hkey = HashString (key); char * localkey = strdup(key);
//std::cout << "(STILL)Adding node: " << key << " key " << hkey << endl; unsigned int hkey = HashString (localkey);
table[hkey] = newHashNode(key, content, table[hkey]); //std::cout << "(STILL)Adding node: " << localkey << " key " << hkey << endl;
table[hkey] = newHashNode(localkey, content, table[hkey]);
} }
void * HashTable::get(char * key) void * HashTable::get(char * key)

View File

@@ -16,6 +16,9 @@ class HashTable
public: public:
HashTable(int n_size); HashTable(int n_size);
~HashTable(); ~HashTable();
/* after calling 'add', the calling application
* must free the string */
void add(char * key, void * content); void add(char * key, void * content);
void * get(char * key); void * get(char * key);

View File

@@ -93,13 +93,14 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p
switch (args->sa_family) switch (args->sa_family)
{ {
case (AF_INET): 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); packet = new Packet (args->ip_src, ntohs(tcp->source), args->ip_dst, ntohs(tcp->dest), header->len, header->ts);
break; break;
case (AF_INET6): case (AF_INET6):
packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts); packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts);
break; break;
} }
//if (DEBUG)
// std::cout << "Got packet from " << packet->gethashstring() << std::endl;
Connection * connection = findConnection(packet); 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 */ /* add packet to the connection */
connection->add(packet); connection->add(packet);
delete packet;
} else { } else {
/* else: unknown connection, create new */ /* else: unknown connection, create new */
connection = new Connection (packet); connection = new Connection (packet);
//if (DEBUG)
// std::cerr << "Getting process by connection\n";
Process * process = getProcess(connection, currentdevice); Process * process = getProcess(connection, currentdevice);
} }
@@ -152,6 +152,7 @@ void quit_cb (int i)
procclean(); procclean();
clear(); clear();
endwin(); endwin();
delete caption;
exit(0); exit(0);
} }
@@ -310,9 +311,8 @@ int main (int argc, char** argv)
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
userdata->sa_family = AF_UNSPEC; userdata->sa_family = AF_UNSPEC;
currentdevice = current_handle->devicename; 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 (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
/* dp_dispatch handles deletion of the userdata */ free (userdata);
current_handle = current_handle->next; current_handle = current_handle->next;
} }

View File

@@ -10,6 +10,7 @@
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip6.h> #include <netinet/ip6.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <stdio.h>
// #include "inet6.c" // #include "inet6.c"
local_addr * local_addrs = NULL; local_addr * local_addrs = NULL;
@@ -124,77 +125,22 @@ struct tcp_hdr {
u_short th_sum; /* checksum */ u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */ u_short th_urp; /* urgent pointer */
}; };
/* Packet 'Constructor' - but returns NULL on failure */ 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)
/* 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)
{ {
sip = m_sip; sport = m_sport; sip = m_sip; sport = m_sport;
dip = m_dip; dport = m_dport; dip = m_dip; dport = m_dport;
len = m_len; time = m_time; len = m_len; time = m_time;
dir = m_dir; sa_family = AF_INET; 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; sip6 = m_sip; sport = m_sport;
dip6 = m_dip; dport = m_dport; dip6 = m_dip; dport = m_dport;
len = m_len; time = m_time; len = m_len; time = m_time;
dir = m_dir; sa_family = AF_INET6; dir = m_dir; sa_family = AF_INET6;
hashstring = NULL;
} }
Packet * Packet::newInverted () { Packet * Packet::newInverted () {
@@ -206,11 +152,19 @@ Packet * Packet::newInverted () {
} }
/* constructs returns a new Packet() structure with the same contents as this one */ /* constructs returns a new Packet() structure with the same contents as this one */
/*Packet::Packet (const Packet &old_packet) { Packet::Packet (const Packet &old_packet) {
sip = old_packet.sip; sport = old_packet.sport; sip = old_packet.sip; sport = old_packet.sport;
dip = old_packet.dip; dport = old_packet.dport; sip6 = old_packet.sip6;
len = old_packet.len; time = old_packet.time; 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) 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 */ /* 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. */ /* '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 * Packet::gethashstring ()
{ {
char * retval = (char *) malloc (HASHKEYSIZE * sizeof(char)); if (hashstring != NULL)
char * local_string = (char*) malloc (50); {
char * remote_string = (char*) malloc (50); 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) { if (sa_family == AF_INET) {
inet_ntop(sa_family, &sip, local_string, 49); inet_ntop(sa_family, &sip, local_string, 49);
inet_ntop(sa_family, &dip, remote_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); inet_ntop(sa_family, &dip6, remote_string, 49);
} }
if (Outgoing()) { 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 { } 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 (local_string);
free (remote_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 /* 2 packets match if they have the same

View File

@@ -9,11 +9,6 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include "nethogs.h" #include "nethogs.h"
extern "C"
{
#include <pcap.h>
}
enum direction { enum direction {
dir_unknown, dir_unknown,
dir_incoming, dir_incoming,
@@ -33,12 +28,21 @@ public:
in_addr dip; in_addr dip;
unsigned short sport; unsigned short sport;
unsigned short dport; unsigned short dport;
bpf_u_int32 len; u_int32_t len;
timeval time; 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 (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, 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, u_int32_t m_len, timeval m_time, direction dir = dir_unknown);
/* using default copy constructor */ /* copy constructor */
Packet (const Packet &old);
~Packet ()
{
if (hashstring != NULL)
{
free (hashstring);
hashstring = NULL;
}
}
/* Packet (const Packet &old_packet); */ /* Packet (const Packet &old_packet); */
/* copy constructor that turns the packet around */ /* copy constructor that turns the packet around */
Packet * newInverted (); Packet * newInverted ();
@@ -53,8 +57,7 @@ public:
private: private:
direction dir; direction dir;
short int sa_family; short int sa_family;
char * hashstring;
}; };
//Packet * getPacket (const struct pcap_pkthdr * header, const u_char * packet, packet_type packettype);
#endif #endif

View File

@@ -68,7 +68,8 @@ void addtoconninode (char * buffer)
char addr6[INET6_ADDRSTRLEN]; char addr6[INET6_ADDRSTRLEN];
struct in6_addr in6_local; struct in6_addr in6_local;
struct in6_addr in6_remote; 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)); 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", 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; //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 /* 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.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 * 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; struct local_addr * current_local_addr = local_addrs;
while (current_local_addr != NULL) { while (current_local_addr != NULL) {
/* TODO maybe only add the ones with the same sa_family */ /* 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); snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", current_local_addr->string, local_port, remote_string, rem_port);
conninode->add(hashkey, (void *)inode); conninode->add(hashkey, (void *)inode);
current_local_addr = current_local_addr->next; current_local_addr = current_local_addr->next;
} }
free (hashkey);
free (remote_string); free (remote_string);
} }
@@ -184,7 +187,8 @@ struct prg_node * findPID (unsigned long inode)
prg_cache_clear(); prg_cache_clear();
prg_cache_load(); prg_cache_load();
node = prg_cache_get(inode); node = prg_cache_get(inode);
assert (node->pid != 1); // this still happens sometimes...
//assert (node->pid != 1);
} }
if (node == NULL) 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; return (((double)bytes) / PERIOD) / 1024;
} }
@@ -327,7 +331,7 @@ void Line::show (int row)
{ {
if (DEBUG || tracemode) 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; return;
} }
@@ -425,8 +429,8 @@ void do_refresh()
continue; continue;
} }
bpf_u_int32 sum_sent = 0, u_int32_t sum_sent = 0,
sum_recv = 0; sum_recv = 0;
/* walk though all this process's connections, and sum them /* walk though all this process's connections, and sum them
* up */ * up */
@@ -449,7 +453,7 @@ void do_refresh()
} }
else else
{ {
bpf_u_int32 sent = 0, recv = 0; u_int32_t sent = 0, recv = 0;
curconn->getVal()->sumanddel(curtime, &sent, &recv); curconn->getVal()->sumanddel(curtime, &sent, &recv);
sum_sent += sent; sum_sent += sent;
sum_recv += recv; sum_recv += recv;

View File

@@ -47,6 +47,8 @@ public:
name = m_name; name = m_name;
devicename = m_devicename; devicename = m_devicename;
connections = NULL; connections = NULL;
pid = 0;
uid = 0;
} }
int getLastPacket () int getLastPacket ()
{ {