Fixed memory leaks
This commit is contained in:
2
Makefile
2
Makefile
@@ -7,7 +7,7 @@ man8 := $(DESTDIR)/usr/share/man/man8/
|
|||||||
|
|
||||||
all: nethogs
|
all: nethogs
|
||||||
|
|
||||||
CFLAGS=-g -Wall -pg
|
CFLAGS=-g -Wall
|
||||||
#CFLAGS=-O2
|
#CFLAGS=-O2
|
||||||
OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o
|
OBJS=structs.o packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o
|
||||||
GCC=g++
|
GCC=g++
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ void PackList::add (Packet * p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* store copy of packet, so that original may be freed */
|
||||||
content = new PackListNode(new Packet (*p), content);
|
content = new PackListNode(new Packet (*p), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ u_int32_t PackList::sumanddel (timeval t)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* packet may be deleted by caller */
|
||||||
Connection::Connection (Packet * packet)
|
Connection::Connection (Packet * packet)
|
||||||
{
|
{
|
||||||
if (ROBUST)
|
if (ROBUST)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public:
|
|||||||
/* sums up the total bytes used and removes 'old' packets */
|
/* sums up the total bytes used and removes 'old' packets */
|
||||||
u_int32_t sumanddel (timeval t);
|
u_int32_t sumanddel (timeval t);
|
||||||
|
|
||||||
|
/* calling code may delete packet */
|
||||||
void add (Packet * p);
|
void add (Packet * p);
|
||||||
private:
|
private:
|
||||||
PackListNode * content;
|
PackListNode * content;
|
||||||
@@ -55,6 +56,7 @@ public:
|
|||||||
/* constructs a connection, makes a copy of
|
/* constructs a connection, makes a copy of
|
||||||
* the packet as 'refpacket', and adds the
|
* the packet as 'refpacket', and adds the
|
||||||
* packet to the packlist */
|
* packet to the packlist */
|
||||||
|
/* packet may be deleted by caller */
|
||||||
Connection (Packet * packet);
|
Connection (Packet * packet);
|
||||||
|
|
||||||
~Connection();
|
~Connection();
|
||||||
@@ -83,6 +85,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Find the connection this packet belongs to */
|
/* Find the connection this packet belongs to */
|
||||||
|
/* (the calling code may free the packet afterwards) */
|
||||||
Connection * findConnection (Packet * packet);
|
Connection * findConnection (Packet * packet);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
111
cui.cpp
111
cui.cpp
@@ -17,8 +17,13 @@ extern Process * unknownproc;
|
|||||||
class Line
|
class Line
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Line (const char * name, double n_sent_kbps, double n_recv_kbps, int pid, uid_t uid, const char * n_devicename)
|
Line (const char * name, double n_sent_kbps, double n_recv_kbps, pid_t pid, uid_t uid, const char * n_devicename)
|
||||||
{
|
{
|
||||||
|
if (ROBUST)
|
||||||
|
{
|
||||||
|
assert (uid >= 0);
|
||||||
|
assert (pid >= 0);
|
||||||
|
}
|
||||||
m_name = name;
|
m_name = name;
|
||||||
sent_kbps = n_sent_kbps;
|
sent_kbps = n_sent_kbps;
|
||||||
recv_kbps = n_recv_kbps;
|
recv_kbps = n_recv_kbps;
|
||||||
@@ -39,22 +44,23 @@ public:
|
|||||||
private:
|
private:
|
||||||
const char * m_name;
|
const char * m_name;
|
||||||
const char * devicename;
|
const char * devicename;
|
||||||
int m_pid;
|
pid_t m_pid;
|
||||||
int m_uid;
|
uid_t m_uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
char * uid2username (int uid)
|
char * uid2username (uid_t uid)
|
||||||
{
|
{
|
||||||
struct passwd * pwd = NULL;
|
struct passwd * pwd = NULL;
|
||||||
/* getpwuid() allocates space for this itself,
|
/* getpwuid() allocates space for this itself,
|
||||||
* which we shouldn't free */
|
* which we shouldn't free */
|
||||||
pwd = getpwuid(uid);
|
pwd = getpwuid(uid);
|
||||||
|
|
||||||
if (ROBUST)
|
|
||||||
assert (pwd != NULL);
|
|
||||||
|
|
||||||
if (pwd == NULL)
|
if (pwd == NULL)
|
||||||
{
|
{
|
||||||
|
if (ROBUST)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
return strdup ("unlisted");
|
return strdup ("unlisted");
|
||||||
} else {
|
} else {
|
||||||
return strdup(pwd->pw_name);
|
return strdup(pwd->pw_name);
|
||||||
@@ -169,7 +175,7 @@ void do_refresh()
|
|||||||
double sent_global = 0;
|
double sent_global = 0;
|
||||||
double recv_global = 0;
|
double recv_global = 0;
|
||||||
|
|
||||||
if (DEBUG)
|
if (ROBUST)
|
||||||
{
|
{
|
||||||
// initialise to null pointers
|
// initialise to null pointers
|
||||||
for (int i = 0; i < nproc; i++)
|
for (int i = 0; i < nproc; i++)
|
||||||
@@ -185,6 +191,7 @@ void do_refresh()
|
|||||||
{
|
{
|
||||||
assert (curproc != NULL);
|
assert (curproc != NULL);
|
||||||
assert (curproc->getVal() != NULL);
|
assert (curproc->getVal() != NULL);
|
||||||
|
assert (nproc == processes->size());
|
||||||
}
|
}
|
||||||
/* do not remove the unknown process */
|
/* do not remove the unknown process */
|
||||||
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc))
|
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknownproc))
|
||||||
@@ -207,48 +214,62 @@ void do_refresh()
|
|||||||
nproc--;
|
nproc--;
|
||||||
//continue;
|
//continue;
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
|
||||||
u_int32_t 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)
|
|
||||||
{
|
{
|
||||||
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT)
|
|
||||||
|
u_int32_t 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)
|
||||||
{
|
{
|
||||||
/* stalled connection, remove. */
|
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT)
|
||||||
ConnList * todelete = curconn;
|
{
|
||||||
Connection * conn_todelete = curconn->getVal();
|
/* stalled connection, remove. */
|
||||||
curconn = curconn->getNext();
|
ConnList * todelete = curconn;
|
||||||
if (todelete == curproc->getVal()->connections)
|
Connection * conn_todelete = curconn->getVal();
|
||||||
curproc->getVal()->connections = curconn;
|
curconn = curconn->getNext();
|
||||||
if (previous != NULL)
|
if (todelete == curproc->getVal()->connections)
|
||||||
previous->setNext(curconn);
|
curproc->getVal()->connections = curconn;
|
||||||
delete (todelete);
|
if (previous != NULL)
|
||||||
delete (conn_todelete);
|
previous->setNext(curconn);
|
||||||
|
delete (todelete);
|
||||||
|
delete (conn_todelete);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u_int32_t sent = 0, recv = 0;
|
||||||
|
curconn->getVal()->sumanddel(curtime, &sent, &recv);
|
||||||
|
sum_sent += sent;
|
||||||
|
sum_recv += recv;
|
||||||
|
previous = curconn;
|
||||||
|
curconn = curconn->getNext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
uid_t uid = curproc->getVal()->getUid();
|
||||||
|
if (ROBUST)
|
||||||
{
|
{
|
||||||
u_int32_t sent = 0, recv = 0;
|
assert (getpwuid(uid) != NULL);
|
||||||
curconn->getVal()->sumanddel(curtime, &sent, &recv);
|
assert (curproc->getVal()->pid >= 0);
|
||||||
sum_sent += sent;
|
assert (n < nproc);
|
||||||
sum_recv += recv;
|
}
|
||||||
previous = curconn;
|
lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv),
|
||||||
curconn = curconn->getNext();
|
curproc->getVal()->pid, uid, curproc->getVal()->devicename);
|
||||||
|
previousproc = curproc;
|
||||||
|
curproc = curproc->next;
|
||||||
|
n++;
|
||||||
|
if (ROBUST)
|
||||||
|
{
|
||||||
|
assert (nproc == processes->size());
|
||||||
|
if (curproc == NULL)
|
||||||
|
assert (n-1 < nproc);
|
||||||
|
else
|
||||||
|
assert (n < nproc);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
uid_t uid = curproc->getVal()->getUid();
|
|
||||||
if (ROBUST)
|
|
||||||
assert (uid >= 0);
|
|
||||||
lines[n] = new Line (curproc->getVal()->name, tokbps(sum_sent), tokbps(sum_recv),
|
|
||||||
curproc->getVal()->pid, uid, curproc->getVal()->devicename);
|
|
||||||
previousproc = curproc;
|
|
||||||
curproc = curproc->next;
|
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ char * getprogname (char * pid) {
|
|||||||
int fd = open(filename, O_RDONLY);
|
int fd = open(filename, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf (stderr, "Error opening %s: %s\n", filename, strerror(errno));
|
fprintf (stderr, "Error opening %s: %s\n", filename, strerror(errno));
|
||||||
|
free (filename);
|
||||||
exit(3);
|
exit(3);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -63,6 +64,7 @@ char * getprogname (char * pid) {
|
|||||||
cout << "Error closing file: " << strerror(errno) << endl;
|
cout << "Error closing file: " << strerror(errno) << endl;
|
||||||
exit(34);
|
exit(34);
|
||||||
}
|
}
|
||||||
|
free (filename);
|
||||||
if (length < bufsize - 1)
|
if (length < bufsize - 1)
|
||||||
buffer[length]='\0';
|
buffer[length]='\0';
|
||||||
|
|
||||||
@@ -76,6 +78,13 @@ char * getprogname (char * pid) {
|
|||||||
return strdup(retval);
|
return strdup(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setnode (unsigned long inode, prg_node * newnode)
|
||||||
|
{
|
||||||
|
if (inodeproc[inode] != NULL)
|
||||||
|
free (inodeproc[inode]);
|
||||||
|
inodeproc[inode] = newnode;
|
||||||
|
}
|
||||||
|
|
||||||
void get_info_by_linkname (char * pid, char * linkname) {
|
void get_info_by_linkname (char * pid, char * linkname) {
|
||||||
if (strncmp(linkname, "socket:[", 8) == 0) {
|
if (strncmp(linkname, "socket:[", 8) == 0) {
|
||||||
char * ptr = linkname + 8;
|
char * ptr = linkname + 8;
|
||||||
@@ -90,7 +99,7 @@ void get_info_by_linkname (char * pid, char * linkname) {
|
|||||||
// TODO progname could be more memory-efficient
|
// TODO progname could be more memory-efficient
|
||||||
strncpy (newnode->name, progname, PROGNAME_WIDTH);
|
strncpy (newnode->name, progname, PROGNAME_WIDTH);
|
||||||
free (progname);
|
free (progname);
|
||||||
inodeproc[inode] = newnode;
|
setnode (inode, newnode);
|
||||||
} else {
|
} else {
|
||||||
//std::cout << "Linkname looked like: " << linkname << endl;
|
//std::cout << "Linkname looked like: " << linkname << endl;
|
||||||
}
|
}
|
||||||
@@ -128,6 +137,11 @@ void get_info_for_pid(char * pid) {
|
|||||||
int linklen = 80;
|
int linklen = 80;
|
||||||
char linkname [linklen];
|
char linkname [linklen];
|
||||||
int usedlen = readlink(fromname, linkname, linklen-1);
|
int usedlen = readlink(fromname, linkname, linklen-1);
|
||||||
|
if (usedlen == -1)
|
||||||
|
{
|
||||||
|
free (fromname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (ROBUST)
|
if (ROBUST)
|
||||||
assert (usedlen < linklen);
|
assert (usedlen < linklen);
|
||||||
linkname[usedlen] = '\0';
|
linkname[usedlen] = '\0';
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ 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);
|
||||||
getProcess(connection, currentdevice);
|
getProcess(connection, currentdevice);
|
||||||
}
|
}
|
||||||
|
delete packet;
|
||||||
|
|
||||||
if (needrefresh)
|
if (needrefresh)
|
||||||
{
|
{
|
||||||
|
|||||||
32
process.cpp
32
process.cpp
@@ -28,7 +28,7 @@ extern local_addr * local_addrs;
|
|||||||
* key contains source ip, source port, destination ip, destination
|
* key contains source ip, source port, destination ip, destination
|
||||||
* port in format: '1.2.3.4:5-1.2.3.4:5'
|
* port in format: '1.2.3.4:5-1.2.3.4:5'
|
||||||
*/
|
*/
|
||||||
std::map <std::string, unsigned long *> conninode;
|
std::map <std::string, unsigned long> conninode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialise the global process-list with `the' unknown process
|
* Initialise the global process-list with `the' unknown process
|
||||||
@@ -82,18 +82,19 @@ void addtoconninode (char * buffer)
|
|||||||
struct in6_addr in6_local;
|
struct in6_addr in6_local;
|
||||||
struct in6_addr in6_remote;
|
struct in6_addr in6_remote;
|
||||||
|
|
||||||
// the following leaks some memory.
|
// this leaked memory
|
||||||
unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long));
|
//unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long));
|
||||||
|
unsigned long inode;
|
||||||
|
|
||||||
int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
|
int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
|
||||||
local_addr, &local_port, rem_addr, &rem_port, inode);
|
local_addr, &local_port, rem_addr, &rem_port, &inode);
|
||||||
|
|
||||||
if (matches != 5) {
|
if (matches != 5) {
|
||||||
fprintf(stderr,"Unexpected buffer: '%s'\n",buffer);
|
fprintf(stderr,"Unexpected buffer: '%s'\n",buffer);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*inode == 0) {
|
if (inode == 0) {
|
||||||
/* connection is in TIME_WAIT state. We rely on
|
/* connection is in TIME_WAIT state. We rely on
|
||||||
* the old data still in the table. */
|
* the old data still in the table. */
|
||||||
return;
|
return;
|
||||||
@@ -229,14 +230,14 @@ void reviewUnknown ()
|
|||||||
ConnList * previous_conn = NULL;
|
ConnList * previous_conn = NULL;
|
||||||
|
|
||||||
while (curr_conn != NULL) {
|
while (curr_conn != NULL) {
|
||||||
unsigned long * inode = conninode[curr_conn->getVal()->refpacket->gethashstring()];
|
unsigned long inode = conninode[curr_conn->getVal()->refpacket->gethashstring()];
|
||||||
if (inode != NULL)
|
if (inode != 0)
|
||||||
{
|
{
|
||||||
Process * proc = findProcess (*inode);
|
Process * proc = findProcess (inode);
|
||||||
if (proc != unknownproc && proc != NULL)
|
if (proc != unknownproc && proc != NULL)
|
||||||
{
|
{
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
std::cout << "ITP: WARNING: Previously unknown inode " << *inode << " now got process...??\n";
|
std::cout << "ITP: WARNING: Previously unknown inode " << inode << " now got process...??\n";
|
||||||
/* Yay! - but how could this happen? */
|
/* Yay! - but how could this happen? */
|
||||||
//assert(false);
|
//assert(false);
|
||||||
if (previous_conn != NULL)
|
if (previous_conn != NULL)
|
||||||
@@ -315,7 +316,7 @@ Process * getProcess (unsigned long inode, char * devicename)
|
|||||||
if (proc != NULL)
|
if (proc != NULL)
|
||||||
return proc;
|
return proc;
|
||||||
|
|
||||||
Process * newproc = new Process (inode, strdup(devicename));
|
Process * newproc = new Process (inode, devicename);
|
||||||
newproc->name = strdup(node->name);
|
newproc->name = strdup(node->name);
|
||||||
newproc->pid = node->pid;
|
newproc->pid = node->pid;
|
||||||
|
|
||||||
@@ -325,6 +326,7 @@ Process * getProcess (unsigned long inode, char * devicename)
|
|||||||
stat(procdir, &stats);
|
stat(procdir, &stats);
|
||||||
newproc->setUid(stats.st_uid);
|
newproc->setUid(stats.st_uid);
|
||||||
|
|
||||||
|
assert (getpwuid(stats.st_uid) != NULL);
|
||||||
processes = new ProcList (newproc, processes);
|
processes = new ProcList (newproc, processes);
|
||||||
return newproc;
|
return newproc;
|
||||||
}
|
}
|
||||||
@@ -338,9 +340,9 @@ Process * getProcess (unsigned long inode, char * devicename)
|
|||||||
*/
|
*/
|
||||||
Process * getProcess (Connection * connection, char * devicename)
|
Process * getProcess (Connection * connection, char * devicename)
|
||||||
{
|
{
|
||||||
unsigned long * inode = conninode[connection->refpacket->gethashstring()];
|
unsigned long inode = conninode[connection->refpacket->gethashstring()];
|
||||||
|
|
||||||
if (inode == NULL)
|
if (inode == 0)
|
||||||
{
|
{
|
||||||
// no? refresh and check conn/inode table
|
// no? refresh and check conn/inode table
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -348,7 +350,7 @@ Process * getProcess (Connection * connection, char * devicename)
|
|||||||
#endif
|
#endif
|
||||||
refreshconninode();
|
refreshconninode();
|
||||||
inode = conninode[connection->refpacket->gethashstring()];
|
inode = conninode[connection->refpacket->gethashstring()];
|
||||||
if (inode == NULL)
|
if (inode == 0)
|
||||||
{
|
{
|
||||||
/* HACK: the following is a hack for cases where the
|
/* HACK: the following is a hack for cases where the
|
||||||
* 'local' addresses aren't properly recognised, as is
|
* 'local' addresses aren't properly recognised, as is
|
||||||
@@ -360,7 +362,7 @@ Process * getProcess (Connection * connection, char * devicename)
|
|||||||
Packet * reversepacket = connection->refpacket->newInverted();
|
Packet * reversepacket = connection->refpacket->newInverted();
|
||||||
inode = conninode[reversepacket->gethashstring()];
|
inode = conninode[reversepacket->gethashstring()];
|
||||||
|
|
||||||
if (inode == NULL)
|
if (inode == 0)
|
||||||
{
|
{
|
||||||
delete reversepacket;
|
delete reversepacket;
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
@@ -374,7 +376,7 @@ Process * getProcess (Connection * connection, char * devicename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process * proc = getProcess(*inode, devicename);
|
Process * proc = getProcess(inode, devicename);
|
||||||
proc->connections = new ConnList (connection, proc->connections);
|
proc->connections = new ConnList (connection, proc->connections);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,16 +66,18 @@ public:
|
|||||||
assert (uid >= 0);
|
assert (uid >= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO free m_name and m_devicename again in constructor */
|
|
||||||
~Process ()
|
~Process ()
|
||||||
{
|
{
|
||||||
|
free (name);
|
||||||
|
free (devicename);
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
std::cout << "PROC: Process deleted at " << this << std::endl;
|
std::cout << "PROC: Process deleted at " << this << std::endl;
|
||||||
}
|
}
|
||||||
int getLastPacket ();
|
int getLastPacket ();
|
||||||
|
|
||||||
const char * name;
|
char * name;
|
||||||
const char * devicename;
|
char * devicename;
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
unsigned long inode;
|
unsigned long inode;
|
||||||
|
|||||||
Reference in New Issue
Block a user