Use clang-format to format (somewhat) LLVM-style (fixes #44)

This commit is contained in:
Arnout Engelen
2016-03-21 00:31:48 +01:00
parent ac045b487a
commit e74935da1f
24 changed files with 2369 additions and 2561 deletions

View File

@@ -30,7 +30,9 @@ nethogs:
decpcap_test:
$(MAKE) -f MakeApp.mk $@
.PHONY: clean
clean:
$(MAKE) -f MakeApp.mk $@
$(MAKE) -f MakeLib.mk $@
format:
clang-format -i *.c *.cpp *.h

View File

@@ -44,22 +44,16 @@ After that, simply
Coding standards
----------------
Can anyone recommend a sensible set? :)
We use the [http://llvm.org/docs/CodingStandards.html](LLVM coding standards),
with the exception that we do allow 'return' after 'else' if it makes the code
more readable.
For now:
* '{'
* on a new line for function definitions
* on a new line for enums
* on the same line for conditionals/loops
* omitted when possible
* use tab for indentation
* use doxygen/javadoc-style comments.
* for multiline doxygen docs, add a newline after '/**'
* case
* classes: camelcased, start uppercase
* enums: camelcased, start uppercase
* functions: camelcased, start lowercase
* local variables: camelcased, start lowercase
Not all code currently adheres to this standard. Pull requests fixing style
are welcome, and do write new code in the proper style, but please do not
mix style fixes and new functionality in one pull request.
When writing new code, at least run 'make format' to have clang-format fix
some superficial style aspects.
libnethogs
----------

View File

@@ -15,54 +15,49 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <iostream>
#include <cassert>
#ifdef __APPLE__
#include <sys/malloc.h>
#include <sys/malloc.h>
#else
#include <malloc.h>
#include <malloc.h>
#endif
#include "nethogs.h"
#include "connection.h"
#include "process.h"
ConnList * connections = NULL;
ConnList *connections = NULL;
void PackList::add (Packet * p)
{
if (content == NULL)
{
content = new PackListNode (new Packet (*p));
void PackList::add(Packet *p) {
if (content == NULL) {
content = new PackListNode(new Packet(*p));
return;
}
if (content->val->time.tv_sec == p->time.tv_sec)
{
if (content->val->time.tv_sec == p->time.tv_sec) {
content->val->len += p->len;
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);
}
/* sums up the total bytes used and removes 'old' packets */
u_int32_t PackList::sumanddel (timeval t)
{
u_int32_t PackList::sumanddel(timeval t) {
u_int32_t retval = 0;
PackListNode * current = content;
PackListNode * previous = NULL;
PackListNode *current = content;
PackListNode *previous = NULL;
while (current != NULL)
{
//std::cout << "Comparing " << current->val->time.tv_sec << " <= " << t.tv_sec - PERIOD << endl;
if (current->val->time.tv_sec <= t.tv_sec - PERIOD)
{
while (current != NULL) {
// std::cout << "Comparing " << current->val->time.tv_sec << " <= " <<
// t.tv_sec - PERIOD << endl;
if (current->val->time.tv_sec <= t.tv_sec - PERIOD) {
if (current == content)
content = NULL;
else if (previous != NULL)
@@ -78,23 +73,21 @@ u_int32_t PackList::sumanddel (timeval t)
}
/* packet may be deleted by caller */
Connection::Connection (Packet * packet)
{
assert (packet != NULL);
connections = new ConnList (this, connections);
sent_packets = new PackList ();
recv_packets = new PackList ();
Connection::Connection(Packet *packet) {
assert(packet != NULL);
connections = new ConnList(this, connections);
sent_packets = new PackList();
recv_packets = new PackList();
sumSent = 0;
sumRecv = 0;
if (DEBUG)
{
std::cout << "New connection, with package len " << packet->len << std::endl;
if (DEBUG) {
std::cout << "New connection, with package len " << packet->len
<< std::endl;
}
if (packet->Outgoing())
{
if (packet->Outgoing()) {
sumSent += packet->len;
sent_packets->add(packet);
refpacket = new Packet (*packet);
refpacket = new Packet(*packet);
} else {
sumRecv += packet->len;
recv_packets->add(packet);
@@ -105,8 +98,7 @@ Connection::Connection (Packet * packet)
std::cout << "New reference packet created at " << refpacket << std::endl;
}
Connection::~Connection ()
{
Connection::~Connection() {
if (DEBUG)
std::cout << "Deleting connection" << std::endl;
/* refpacket is not a pointer to one of the packets in the lists
@@ -117,24 +109,19 @@ Connection::~Connection ()
if (recv_packets != NULL)
delete recv_packets;
ConnList * curr_conn = connections;
ConnList * prev_conn = NULL;
while (curr_conn != NULL)
{
if (curr_conn->getVal() == this)
{
ConnList * todelete = curr_conn;
ConnList *curr_conn = connections;
ConnList *prev_conn = NULL;
while (curr_conn != NULL) {
if (curr_conn->getVal() == this) {
ConnList *todelete = curr_conn;
curr_conn = curr_conn->getNext();
if (prev_conn == NULL)
{
if (prev_conn == NULL) {
connections = curr_conn;
} else {
prev_conn->setNext(curr_conn);
}
delete (todelete);
}
else
{
} else {
prev_conn = curr_conn;
curr_conn = curr_conn->getNext();
}
@@ -142,42 +129,33 @@ 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;
if (packet->Outgoing())
{
if (DEBUG)
{
if (packet->Outgoing()) {
if (DEBUG) {
std::cout << "Outgoing: " << packet->len << std::endl;
}
sumSent += packet->len;
sent_packets->add (packet);
}
else
{
if (DEBUG)
{
sent_packets->add(packet);
} else {
if (DEBUG) {
std::cout << "Incoming: " << packet->len << std::endl;
}
sumRecv += packet->len;
if (DEBUG)
{
if (DEBUG) {
std::cout << "sumRecv now: " << sumRecv << std::endl;
}
recv_packets->add (packet);
recv_packets->add(packet);
}
}
Connection * findConnectionWithMatchingSource(Packet * packet) {
Connection *findConnectionWithMatchingSource(Packet *packet) {
assert(packet->Outgoing());
ConnList * current = connections;
while (current != NULL)
{
ConnList *current = connections;
while (current != NULL) {
/* the reference packet is always outgoing */
if (packet->matchSource(current->getVal()->refpacket))
{
if (packet->matchSource(current->getVal()->refpacket)) {
return current->getVal();
}
@@ -186,13 +164,11 @@ Connection * findConnectionWithMatchingSource(Packet * packet) {
return NULL;
}
Connection * findConnectionWithMatchingRefpacketOrSource(Packet * packet) {
ConnList * current = connections;
while (current != NULL)
{
Connection *findConnectionWithMatchingRefpacketOrSource(Packet *packet) {
ConnList *current = connections;
while (current != NULL) {
/* the reference packet is always *outgoing* */
if (packet->match(current->getVal()->refpacket))
{
if (packet->match(current->getVal()->refpacket)) {
return current->getVal();
}
@@ -206,14 +182,13 @@ Connection * findConnectionWithMatchingRefpacketOrSource(Packet * packet) {
* a packet belongs to a connection if it matches
* to its reference packet
*/
Connection * findConnection (Packet * packet)
{
Connection *findConnection(Packet *packet) {
if (packet->Outgoing())
return findConnectionWithMatchingRefpacketOrSource(packet);
else
{
Packet * invertedPacket = packet->newInverted();
Connection * result = findConnectionWithMatchingRefpacketOrSource(invertedPacket);
else {
Packet *invertedPacket = packet->newInverted();
Connection *result =
findConnectionWithMatchingRefpacketOrSource(invertedPacket);
delete invertedPacket;
return result;
@@ -229,9 +204,8 @@ Connection * findConnection (Packet * packet)
* Returns sum of sent packages (by address)
* sum of recieved packages (by address)
*/
void Connection::sumanddel (timeval t, u_int32_t * recv, u_int32_t * sent)
{
(*sent)=(*recv)=0;
void Connection::sumanddel(timeval t, u_int32_t *recv, u_int32_t *sent) {
(*sent) = (*recv) = 0;
*sent = sent_packets->sumanddel(t);
*recv = recv_packets->sumanddel(t);

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __CONNECTION_H
@@ -24,59 +25,50 @@
#include <iostream>
#include "packet.h"
class PackListNode
{
class PackListNode {
public:
PackListNode (Packet * m_val, PackListNode * m_next = NULL)
{
PackListNode(Packet *m_val, PackListNode *m_next = NULL) {
val = m_val;
next = m_next;
}
~PackListNode ()
{
~PackListNode() {
delete val;
if (next != NULL)
delete next;
}
PackListNode * next;
Packet * val;
PackListNode *next;
Packet *val;
};
class PackList
{
class PackList {
public:
PackList ()
{
content = NULL;
}
PackList (Packet * m_val)
{
assert (m_val != NULL);
PackList() { content = NULL; }
PackList(Packet *m_val) {
assert(m_val != NULL);
content = new PackListNode(m_val);
}
~PackList ()
{
~PackList() {
if (content != NULL)
delete content;
}
/* 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:
PackListNode * content;
PackListNode *content;
};
class Connection
{
class Connection {
public:
/* constructs a connection, makes a copy of
* the packet as 'refpacket', and adds the
* packet to the packlist */
/* packet may be deleted by caller */
Connection (Packet * packet);
Connection(Packet *packet);
~Connection();
@@ -85,30 +77,30 @@ public:
* when it is 'merged with' (added to) another
* packet
*/
void add (Packet * packet);
void add(Packet *packet);
int getLastPacket ()
{ return lastpacket; }
int getLastPacket() { return lastpacket; }
/* sums up the total bytes used
* and removes 'old' packets. */
void sumanddel(timeval curtime, u_int32_t * recv, u_int32_t * sent);
void sumanddel(timeval curtime, u_int32_t *recv, u_int32_t *sent);
/* for checking if a packet is part of this connection */
/* the reference packet is always *outgoing*. */
Packet * refpacket;
Packet *refpacket;
/* total sum or sent/received bytes */
u_int32_t sumSent;
u_int32_t sumRecv;
private:
PackList * sent_packets;
PackList * recv_packets;
PackList *sent_packets;
PackList *recv_packets;
int lastpacket;
};
/* Find the connection this packet belongs to */
/* (the calling code may free the packet afterwards) */
Connection * findConnection (Packet * packet);
Connection *findConnection(Packet *packet);
#endif

View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <netinet/in.h>
#include <map>
#include <cstdio>
@@ -29,32 +29,35 @@
#include "conninode.h"
#if defined __APPLE__
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#endif
extern local_addr * local_addrs;
extern local_addr *local_addrs;
/*
* connection-inode table. takes information from /proc/net/tcp.
* key contains source ip, source port, destination ip, destination
* 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;
/*
* 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
* 10: 020310AC:1770 9DD8A9C3:A525 01 00000000:00000000 00:00000000 00000000 0 0 2119 1 c0f4f0c0 206 40 10 3 -1
* 11: 020310AC:0404 936B2ECF:0747 01 00000000:00000000 00:00000000 00000000 1000 0 2109 1 c0f4fc00 368 40 20 2 -1
* sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt
*uid timeout inode
* 10: 020310AC:1770 9DD8A9C3:A525 01 00000000:00000000 00:00000000 00000000
*0 0 2119 1 c0f4f0c0 206 40 10 3 -1
* 11: 020310AC:0404 936B2ECF:0747 01 00000000:00000000 00:00000000 00000000
*1000 0 2109 1 c0f4fc00 368 40 20 2 -1
*
* and of the form:
* 2: 0000000000000000FFFF0000020310AC:0016 0000000000000000FFFF00009DD8A9C3:A526 01 00000000:00000000 02:000A7214 00000000 0 0 2525 2 c732eca0 201 40 1 2 -1
* 2: 0000000000000000FFFF0000020310AC:0016
*0000000000000000FFFF00009DD8A9C3:A526 01 00000000:00000000 02:000A7214
*00000000 0 0 2525 2 c732eca0 201 40 1 2 -1
*
*/
void addtoconninode (char * buffer)
{
void addtoconninode(char *buffer) {
short int sa_family;
struct in6_addr result_addr_local;
struct in6_addr result_addr_remote;
@@ -65,14 +68,15 @@ void addtoconninode (char * buffer)
struct in6_addr in6_remote;
// 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);
if (matches != 5) {
fprintf(stderr,"Unexpected buffer: '%s'\n",buffer);
fprintf(stderr, "Unexpected buffer: '%s'\n", buffer);
exit(0);
}
@@ -82,59 +86,56 @@ void addtoconninode (char * buffer)
return;
}
if (strlen(local_addr) > 8)
{
if (strlen(local_addr) > 8) {
/* this is an IPv6-style row */
/* Demangle what the kernel gives us */
sscanf(local_addr, "%08X%08X%08X%08X",
&in6_local.s6_addr32[0], &in6_local.s6_addr32[1],
&in6_local.s6_addr32[2], &in6_local.s6_addr32[3]);
sscanf(rem_addr, "%08X%08X%08X%08X",
&in6_remote.s6_addr32[0], &in6_remote.s6_addr32[1],
&in6_remote.s6_addr32[2], &in6_remote.s6_addr32[3]);
sscanf(local_addr, "%08X%08X%08X%08X", &in6_local.s6_addr32[0],
&in6_local.s6_addr32[1], &in6_local.s6_addr32[2],
&in6_local.s6_addr32[3]);
sscanf(rem_addr, "%08X%08X%08X%08X", &in6_remote.s6_addr32[0],
&in6_remote.s6_addr32[1], &in6_remote.s6_addr32[2],
&in6_remote.s6_addr32[3]);
if ((in6_local.s6_addr32[0] == 0x0) && (in6_local.s6_addr32[1] == 0x0)
&& (in6_local.s6_addr32[2] == 0xFFFF0000))
{
if ((in6_local.s6_addr32[0] == 0x0) && (in6_local.s6_addr32[1] == 0x0) &&
(in6_local.s6_addr32[2] == 0xFFFF0000)) {
/* IPv4-compatible address */
result_addr_local = *((struct in6_addr*) &(in6_local.s6_addr32[3]));
result_addr_remote = *((struct in6_addr*) &(in6_remote.s6_addr32[3]));
result_addr_local = *((struct in6_addr *)&(in6_local.s6_addr32[3]));
result_addr_remote = *((struct in6_addr *)&(in6_remote.s6_addr32[3]));
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;
}
}
else
{
} else {
/* this is an IPv4-style row */
sscanf(local_addr, "%X", (unsigned int *) &result_addr_local);
sscanf(rem_addr, "%X", (unsigned int *) &result_addr_remote);
sscanf(local_addr, "%X", (unsigned int *)&result_addr_local);
sscanf(rem_addr, "%X", (unsigned int *)&result_addr_remote);
sa_family = AF_INET;
}
char * hashkey = (char *) malloc (HASHKEYSIZE * sizeof(char));
char * local_string = (char*) malloc (50);
char * remote_string = (char*) malloc (50);
char *hashkey = (char *)malloc(HASHKEYSIZE * sizeof(char));
char *local_string = (char *)malloc(50);
char *remote_string = (char *)malloc(50);
inet_ntop(sa_family, &result_addr_local, local_string, 49);
inet_ntop(sa_family, &result_addr_remote, remote_string, 49);
snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, local_port, remote_string, rem_port);
free (local_string);
snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string,
local_port, remote_string, rem_port);
free(local_string);
//if (DEBUG)
// if (DEBUG)
// fprintf (stderr, "Hashkey: %s\n", hashkey);
//std::cout << "Adding to conninode\n" << std::endl;
// std::cout << "Adding to conninode\n" << std::endl;
conninode[hashkey] = inode;
@@ -146,16 +147,17 @@ void addtoconninode (char * buffer)
current_local_addr != NULL;
current_local_addr = current_local_addr->next) {
/* TODO maybe only add the ones with the same sa_family */
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[hashkey] = inode;
}
free (hashkey);
free (remote_string);
free(hashkey);
free(remote_string);
}
/* opens /proc/net/tcp[6] and adds its contents line by line */
int addprocinfo (const char * filename) {
FILE * procinfo = fopen (filename, "r");
int addprocinfo(const char *filename) {
FILE *procinfo = fopen(filename, "r");
char buffer[8192];
@@ -164,8 +166,7 @@ int addprocinfo (const char * filename) {
fgets(buffer, sizeof(buffer), procinfo);
do
{
do {
if (fgets(buffer, sizeof(buffer), procinfo))
addtoconninode(buffer);
} while (!feof(procinfo));
@@ -175,27 +176,21 @@ int addprocinfo (const char * filename) {
return 1;
}
void refreshconninode() {
/* we don't forget old mappings, just overwrite */
// delete conninode;
// conninode = new HashTable (256);
void refreshconninode ()
{
/* we don't forget old mappings, just overwrite */
//delete conninode;
//conninode = new HashTable (256);
#if defined(__APPLE__)
#if defined(__APPLE__)
addprocinfo("net.inet.tcp.pcblist");
#else
if (! addprocinfo ("/proc/net/tcp"))
{
#else
if (!addprocinfo("/proc/net/tcp")) {
std::cout << "Error: couldn't open /proc/net/tcp\n";
exit(0);
}
addprocinfo ("/proc/net/tcp6");
#endif
addprocinfo("/proc/net/tcp6");
#endif
//if (DEBUG)
// if (DEBUG)
// reviewUnknown();
}

View File

@@ -15,8 +15,9 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
// handling the connection->inode mapping
void refreshconninode ();
void refreshconninode();

314
cui.cpp
View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
/* NetHogs console UI */
#include <string>
#include <pwd.h>
@@ -33,14 +33,14 @@
#include "nethogs.h"
#include "process.h"
std::string * caption;
std::string *caption;
extern const char version[];
extern ProcList * processes;
extern ProcList *processes;
extern timeval curtime;
extern Process * unknowntcp;
extern Process * unknownudp;
extern Process * unknownip;
extern Process *unknowntcp;
extern Process *unknownudp;
extern Process *unknownip;
extern bool sortRecv;
@@ -58,42 +58,41 @@ const int COLUMN_WIDTH_SENT = 11;
const int COLUMN_WIDTH_RECEIVED = 11;
const int COLUMN_WIDTH_UNIT = 6;
const char * COLUMN_FORMAT_PID = "%7d";
const char * COLUMN_FORMAT_SENT = "%11.3f";
const char * COLUMN_FORMAT_RECEIVED = "%11.3f";
const char *COLUMN_FORMAT_PID = "%7d";
const char *COLUMN_FORMAT_SENT = "%11.3f";
const char *COLUMN_FORMAT_RECEIVED = "%11.3f";
class Line
{
class Line {
public:
Line (const char * name, double n_recv_value, double n_sent_value, pid_t pid, uid_t uid, const char * n_devicename)
{
assert (pid >= 0);
assert (pid <= PID_MAX);
Line(const char *name, double n_recv_value, double n_sent_value, pid_t pid,
uid_t uid, const char *n_devicename) {
assert(pid >= 0);
assert(pid <= PID_MAX);
m_name = name;
sent_value = n_sent_value;
recv_value = n_recv_value;
devicename = n_devicename;
m_pid = pid;
m_uid = uid;
assert (m_pid >= 0);
assert(m_pid >= 0);
}
void show (int row, unsigned int proglen);
void log ();
void show(int row, unsigned int proglen);
void log();
double sent_value;
double recv_value;
private:
const char * m_name;
const char * devicename;
const char *m_name;
const char *devicename;
pid_t m_pid;
uid_t m_uid;
};
#include <sstream>
std::string itoa(int i)
{
std::string itoa(int i) {
std::stringstream out;
out << i;
return out.str();
@@ -102,9 +101,8 @@ std::string itoa(int i)
/**
* @returns the username that corresponds to this uid
*/
std::string uid2username (uid_t uid)
{
struct passwd * pwd = NULL;
std::string uid2username(uid_t uid) {
struct passwd *pwd = NULL;
errno = 0;
/* points to a static memory area, should not be freed */
@@ -114,17 +112,21 @@ std::string uid2username (uid_t uid)
if (errno == 0)
return itoa(uid);
else
forceExit(false, "Error calling getpwuid(3) for uid %d: %d %s", uid, errno, strerror(errno));
forceExit(false, "Error calling getpwuid(3) for uid %d: %d %s", uid,
errno, strerror(errno));
else
return std::string(pwd->pw_name);
}
/**
* Render the provided text at the specified location, truncating if the length of the text exceeds a maximum. If the
* text must be truncated, the string ".." will be rendered, followed by max_len - 2 characters of the provided text.
* Render the provided text at the specified location, truncating if the length
* of the text exceeds a maximum. If the
* text must be truncated, the string ".." will be rendered, followed by max_len
* - 2 characters of the provided text.
*/
static void mvaddstr_truncate_leading(int row, int col, const char* str, std::size_t str_len, std::size_t max_len)
{
static void mvaddstr_truncate_leading(int row, int col, const char *str,
std::size_t str_len,
std::size_t max_len) {
if (str_len < max_len) {
mvaddstr(row, col, str);
} else {
@@ -134,11 +136,14 @@ static void mvaddstr_truncate_leading(int row, int col, const char* str, std::si
}
/**
* Render the provided text at the specified location, truncating if the length of the text exceeds a maximum. If the
* text must be truncated, the text will be rendered up to max_len - 2 characters and then ".." will be rendered.
* Render the provided text at the specified location, truncating if the length
* of the text exceeds a maximum. If the
* text must be truncated, the text will be rendered up to max_len - 2
* characters and then ".." will be rendered.
*/
static void mvaddstr_truncate_trailing(int row, int col, const char* str, std::size_t str_len, std::size_t max_len)
{
static void mvaddstr_truncate_trailing(int row, int col, const char *str,
std::size_t str_len,
std::size_t max_len) {
if (str_len < max_len) {
mvaddstr(row, col, str);
} else {
@@ -147,10 +152,9 @@ static void mvaddstr_truncate_trailing(int row, int col, const char* str, std::s
}
}
void Line::show (int row, unsigned int proglen)
{
assert (m_pid >= 0);
assert (m_pid <= PID_MAX);
void Line::show(int row, unsigned int proglen) {
assert(m_pid >= 0);
assert(m_pid <= PID_MAX);
const int column_offset_pid = 0;
const int column_offset_user = column_offset_pid + COLUMN_WIDTH_PID + 1;
@@ -158,104 +162,89 @@ void Line::show (int row, unsigned int proglen)
const int column_offset_dev = column_offset_program + proglen + 2;
const int column_offset_sent = column_offset_dev + COLUMN_WIDTH_DEV + 1;
const int column_offset_received = column_offset_sent + COLUMN_WIDTH_SENT + 1;
const int column_offset_unit = column_offset_received + COLUMN_WIDTH_RECEIVED + 1;
const int column_offset_unit =
column_offset_received + COLUMN_WIDTH_RECEIVED + 1;
// PID column
if (m_pid == 0)
mvaddch (row, column_offset_pid + COLUMN_WIDTH_PID - 1, '?');
mvaddch(row, column_offset_pid + COLUMN_WIDTH_PID - 1, '?');
else
mvprintw (row, column_offset_pid, COLUMN_FORMAT_PID, m_pid);
mvprintw(row, column_offset_pid, COLUMN_FORMAT_PID, m_pid);
std::string username = uid2username(m_uid);
mvaddstr_truncate_trailing (row, column_offset_user, username.c_str(), username.size(), COLUMN_WIDTH_USER);
mvaddstr_truncate_trailing(row, column_offset_user, username.c_str(),
username.size(), COLUMN_WIDTH_USER);
mvaddstr_truncate_leading (row, column_offset_program, m_name, strlen (m_name), proglen);
mvaddstr_truncate_leading(row, column_offset_program, m_name, strlen(m_name),
proglen);
mvaddstr (row, column_offset_dev, devicename);
mvaddstr(row, column_offset_dev, devicename);
mvprintw (row, column_offset_sent, COLUMN_FORMAT_SENT, sent_value);
mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, sent_value);
mvprintw (row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value);
if (viewMode == VIEWMODE_KBPS)
{
mvaddstr (row, column_offset_unit, "KB/sec");
}
else if (viewMode == VIEWMODE_TOTAL_MB)
{
mvaddstr (row, column_offset_unit, "MB ");
}
else if (viewMode == VIEWMODE_TOTAL_KB)
{
mvaddstr (row, column_offset_unit, "KB ");
}
else if (viewMode == VIEWMODE_TOTAL_B)
{
mvaddstr (row, column_offset_unit, "B ");
mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value);
if (viewMode == VIEWMODE_KBPS) {
mvaddstr(row, column_offset_unit, "KB/sec");
} else if (viewMode == VIEWMODE_TOTAL_MB) {
mvaddstr(row, column_offset_unit, "MB ");
} else if (viewMode == VIEWMODE_TOTAL_KB) {
mvaddstr(row, column_offset_unit, "KB ");
} else if (viewMode == VIEWMODE_TOTAL_B) {
mvaddstr(row, column_offset_unit, "B ");
}
}
void Line::log() {
std::cout << m_name << '/' << m_pid << '/' << m_uid << "\t" << sent_value << "\t" << recv_value << std::endl;
std::cout << m_name << '/' << m_pid << '/' << m_uid << "\t" << sent_value
<< "\t" << recv_value << std::endl;
}
int GreatestFirst (const void * ma, const void * mb)
{
Line ** pa = (Line **)ma;
Line ** pb = (Line **)mb;
Line * a = *pa;
Line * b = *pb;
int GreatestFirst(const void *ma, const void *mb) {
Line **pa = (Line **)ma;
Line **pb = (Line **)mb;
Line *a = *pa;
Line *b = *pb;
double aValue;
if (sortRecv)
{
if (sortRecv) {
aValue = a->recv_value;
}
else
{
} else {
aValue = a->sent_value;
}
double bValue;
if (sortRecv)
{
if (sortRecv) {
bValue = b->recv_value;
}
else
{
} else {
bValue = b->sent_value;
}
if (aValue > bValue)
{
if (aValue > bValue) {
return -1;
}
if (aValue == bValue)
{
if (aValue == bValue) {
return 0;
}
return 1;
}
void init_ui ()
{
WINDOW * screen = initscr();
void init_ui() {
WINDOW *screen = initscr();
raw();
noecho();
cbreak();
nodelay(screen, TRUE);
caption = new std::string ("NetHogs");
caption = new std::string("NetHogs");
caption->append(getVersion());
//caption->append(", running at ");
// caption->append(", running at ");
}
void exit_ui ()
{
void exit_ui() {
clear();
endwin();
delete caption;
}
void ui_tick ()
{
void ui_tick() {
switch (getch()) {
case 'q':
/* quit */
@@ -276,27 +265,27 @@ void ui_tick ()
}
}
void show_trace(Line * lines[], int nproc) {
void show_trace(Line *lines[], int nproc) {
std::cout << "\nRefreshing:\n";
/* print them */
for (int i=0; i<nproc; i++)
{
for (int i = 0; i < nproc; i++) {
lines[i]->log();
delete lines[i];
}
/* print the 'unknown' connections, for debugging */
ConnList * curr_unknownconn = unknowntcp->connections;
ConnList *curr_unknownconn = unknowntcp->connections;
while (curr_unknownconn != NULL) {
std::cout << "Unknown connection: " <<
curr_unknownconn->getVal()->refpacket->gethashstring() << std::endl;
std::cout << "Unknown connection: "
<< curr_unknownconn->getVal()->refpacket->gethashstring()
<< std::endl;
curr_unknownconn = curr_unknownconn->getNext();
}
}
void show_ncurses(Line * lines[], int nproc) {
void show_ncurses(Line *lines[], int nproc) {
int rows; // number of terminal rows
int cols; // number of terminal columns
unsigned int proglen; // max length of the "PROGRAM" column
@@ -308,60 +297,62 @@ void show_ncurses(Line * lines[], int nproc) {
if (cols < 62) {
clear();
mvprintw(0,0, "The terminal is too narrow! Please make it wider.\nI'll wait...");
mvprintw(0, 0,
"The terminal is too narrow! Please make it wider.\nI'll wait...");
return;
}
if (cols > PROGNAME_WIDTH) cols = PROGNAME_WIDTH;
if (cols > PROGNAME_WIDTH)
cols = PROGNAME_WIDTH;
proglen = cols - 55;
clear();
mvprintw (0, 0, "%s", caption->c_str());
mvprintw(0, 0, "%s", caption->c_str());
attron(A_REVERSE);
mvprintw (2, 0, " PID USER %-*.*s DEV SENT RECEIVED ", proglen, proglen, "PROGRAM");
mvprintw(2, 0,
" PID USER %-*.*s DEV SENT RECEIVED ",
proglen, proglen, "PROGRAM");
attroff(A_REVERSE);
/* print them */
int i;
for (i=0; i<nproc; i++)
{
if (i+3 < rows)
lines[i]->show(i+3, proglen);
for (i = 0; i < nproc; i++) {
if (i + 3 < rows)
lines[i]->show(i + 3, proglen);
recv_global += lines[i]->recv_value;
sent_global += lines[i]->sent_value;
delete lines[i];
}
attron(A_REVERSE);
int totalrow = std::min(rows-1, 3+1+i);
mvprintw (totalrow, 0, " TOTAL %-*.*s %11.3f %11.3f ", proglen, proglen, " ", sent_global, recv_global);
if (viewMode == VIEWMODE_KBPS)
{
mvprintw (3+1+i, cols - COLUMN_WIDTH_UNIT, "KB/sec ");
int totalrow = std::min(rows - 1, 3 + 1 + i);
mvprintw(totalrow, 0, " TOTAL %-*.*s %11.3f %11.3f ",
proglen, proglen, " ", sent_global, recv_global);
if (viewMode == VIEWMODE_KBPS) {
mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "KB/sec ");
} else if (viewMode == VIEWMODE_TOTAL_B) {
mvprintw (3+1+i, cols - COLUMN_WIDTH_UNIT, "B ");
mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "B ");
} else if (viewMode == VIEWMODE_TOTAL_KB) {
mvprintw (3+1+i, cols - COLUMN_WIDTH_UNIT, "KB ");
mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "KB ");
} else if (viewMode == VIEWMODE_TOTAL_MB) {
mvprintw (3+1+i, cols - COLUMN_WIDTH_UNIT, "MB ");
mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "MB ");
}
attroff(A_REVERSE);
mvprintw (totalrow+1, 0, "");
mvprintw(totalrow + 1, 0, "");
refresh();
}
// Display all processes and relevant network traffic using show function
void do_refresh()
{
void do_refresh() {
refreshconninode();
refreshcount++;
ProcList * curproc = processes;
ProcList * previousproc = NULL;
ProcList *curproc = processes;
ProcList *previousproc = NULL;
int nproc = processes->size();
/* initialise to null pointers */
Line * lines [nproc];
Line *lines[nproc];
int n = 0;
#ifndef NDEBUG
@@ -370,27 +361,25 @@ void do_refresh()
lines[i] = NULL;
#endif
while (curproc != NULL)
{
while (curproc != NULL) {
// walk though its connections, summing up their data, and
// throwing away connections that haven't received a package
// in the last PROCESSTIMEOUT seconds.
assert (curproc != NULL);
assert (curproc->getVal() != NULL);
assert (nproc == processes->size());
assert(curproc != NULL);
assert(curproc->getVal() != NULL);
assert(nproc == processes->size());
/* remove timed-out processes (unless it's one of the the unknown process) */
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec)
&& (curproc->getVal() != unknowntcp)
&& (curproc->getVal() != unknownudp)
&& (curproc->getVal() != unknownip))
{
/* remove timed-out processes (unless it's one of the the unknown process)
*/
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <=
curtime.tv_sec) &&
(curproc->getVal() != unknowntcp) &&
(curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) {
if (DEBUG)
std::cout << "PROC: Deleting process\n";
ProcList * todelete = curproc;
Process * p_todelete = curproc->getVal();
if (previousproc)
{
ProcList *todelete = curproc;
Process *p_todelete = curproc->getVal();
if (previousproc) {
previousproc->next = curproc->next;
curproc = curproc->next;
} else {
@@ -400,59 +389,48 @@ void do_refresh()
delete todelete;
delete p_todelete;
nproc--;
//continue;
}
else
{
// continue;
} else {
// add a non-timed-out process to the list of stuff to show
float value_sent = 0,
value_recv = 0;
float value_sent = 0, value_recv = 0;
if (viewMode == VIEWMODE_KBPS)
{
//std::cout << "kbps viemode" << std::endl;
curproc->getVal()->getkbps (&value_recv, &value_sent);
}
else if (viewMode == VIEWMODE_TOTAL_KB)
{
//std::cout << "total viemode" << std::endl;
if (viewMode == VIEWMODE_KBPS) {
// std::cout << "kbps viemode" << std::endl;
curproc->getVal()->getkbps(&value_recv, &value_sent);
} else if (viewMode == VIEWMODE_TOTAL_KB) {
// std::cout << "total viemode" << std::endl;
curproc->getVal()->gettotalkb(&value_recv, &value_sent);
}
else if (viewMode == VIEWMODE_TOTAL_MB)
{
//std::cout << "total viemode" << std::endl;
} else if (viewMode == VIEWMODE_TOTAL_MB) {
// std::cout << "total viemode" << std::endl;
curproc->getVal()->gettotalmb(&value_recv, &value_sent);
}
else if (viewMode == VIEWMODE_TOTAL_B)
{
//std::cout << "total viemode" << std::endl;
} else if (viewMode == VIEWMODE_TOTAL_B) {
// std::cout << "total viemode" << std::endl;
curproc->getVal()->gettotalb(&value_recv, &value_sent);
}
else
{
} else {
forceExit(false, "Invalid viewMode: %d", viewMode);
}
uid_t uid = curproc->getVal()->getUid();
assert (curproc->getVal()->pid >= 0);
assert (n < nproc);
assert(curproc->getVal()->pid >= 0);
assert(n < nproc);
lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent,
lines[n] =
new Line(curproc->getVal()->name, value_recv, value_sent,
curproc->getVal()->pid, uid, curproc->getVal()->devicename);
previousproc = curproc;
curproc = curproc->next;
n++;
#ifndef NDEBUG
assert (nproc == processes->size());
assert(nproc == processes->size());
if (curproc == NULL)
assert (n-1 < nproc);
assert(n - 1 < nproc);
else
assert (n < nproc);
assert(n < nproc);
#endif
}
}
/* sort the accumulated lines */
qsort (lines, nproc, sizeof(Line *), GreatestFirst);
qsort(lines, nproc, sizeof(Line *), GreatestFirst);
if (tracemode || DEBUG)
show_trace(lines, nproc);

11
cui.h
View File

@@ -15,15 +15,16 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
/* NetHogs console UI */
void do_refresh ();
void init_ui ();
void exit_ui ();
void do_refresh();
void init_ui();
void exit_ui();
/* periodically gives some CPU-time to the UI */
void ui_tick ();
void ui_tick();

192
decpcap.c
View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -34,14 +34,13 @@
/* functions to set up a handle (which is basically just a pcap handle) */
struct dp_handle * dp_fillhandle(pcap_t * phandle)
{
struct dp_handle * retval = (struct dp_handle *) malloc (sizeof (struct dp_handle));
struct dp_handle *dp_fillhandle(pcap_t *phandle) {
struct dp_handle *retval =
(struct dp_handle *)malloc(sizeof(struct dp_handle));
int i;
retval->pcap_handle = phandle;
for (i = 0; i < dp_n_packet_types; i++)
{
for (i = 0; i < dp_n_packet_types; i++) {
retval->callback[i] = NULL;
}
@@ -66,24 +65,21 @@ struct dp_handle * dp_fillhandle(pcap_t * phandle)
return retval;
}
struct dp_handle * dp_open_offline(char * fname, char * ebuf)
{
pcap_t * temp = pcap_open_offline(fname, ebuf);
struct dp_handle *dp_open_offline(char *fname, char *ebuf) {
pcap_t *temp = pcap_open_offline(fname, ebuf);
if (temp == NULL)
{
if (temp == NULL) {
return NULL;
}
return dp_fillhandle(temp);
}
struct dp_handle * dp_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf)
{
pcap_t * temp = pcap_open_live(device, snaplen, promisc, to_ms, errbuf);
struct dp_handle *dp_open_live(const char *device, int snaplen, int promisc,
int to_ms, char *errbuf) {
pcap_t *temp = pcap_open_live(device, snaplen, promisc, to_ms, errbuf);
if (temp == NULL)
{
if (temp == NULL) {
return NULL;
}
@@ -92,48 +88,44 @@ struct dp_handle * dp_open_live(const char * device, int snaplen, int promisc, i
/* functions to add callbacks */
void dp_addcb (struct dp_handle * handle, enum dp_packet_type type, dp_callback callback)
{
void dp_addcb(struct dp_handle *handle, enum dp_packet_type type,
dp_callback callback) {
handle->callback[type] = callback;
}
/* functions for parsing the payloads */
void dp_parse_tcp (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
//const struct tcphdr * tcp = (struct tcphdr *) packet;
//u_char * payload = (u_char *) packet + sizeof (struct tcphdr);
void dp_parse_tcp(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
// const struct tcphdr * tcp = (struct tcphdr *) packet;
// u_char * payload = (u_char *) packet + sizeof (struct tcphdr);
if (handle->callback[dp_packet_tcp] != NULL)
{
int done = (handle->callback[dp_packet_tcp])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_tcp] != NULL) {
int done =
(handle->callback[dp_packet_tcp])(handle->userdata, header, packet);
if (done)
return;
}
// TODO: maybe `pass on' payload to lower-level protocol parsing
}
void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
const struct ip * ip = (struct ip *) packet;
if (DP_DEBUG)
{
void dp_parse_ip(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
const struct ip *ip = (struct ip *)packet;
if (DP_DEBUG) {
fprintf(stdout, "Looking at packet with length %ud\n", header->len);
}
u_char * payload = (u_char *) packet + sizeof (struct ip);
u_char *payload = (u_char *)packet + sizeof(struct ip);
if (handle->callback[dp_packet_ip] != NULL)
{
int done = (handle->callback[dp_packet_ip])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_ip] != NULL) {
int done =
(handle->callback[dp_packet_ip])(handle->userdata, header, packet);
if (done)
return;
}
switch (ip->ip_p)
{
switch (ip->ip_p) {
case IPPROTO_TCP:
dp_parse_tcp (handle, header, payload);
dp_parse_tcp(handle, header, payload);
break;
default:
// TODO: maybe support for non-tcp IP packets
@@ -141,22 +133,20 @@ void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_c
}
}
void dp_parse_ip6 (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
const struct ip6_hdr * ip6 = (struct ip6_hdr *) packet;
u_char * payload = (u_char *) packet + sizeof (struct ip6_hdr);
void dp_parse_ip6(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
const struct ip6_hdr *ip6 = (struct ip6_hdr *)packet;
u_char *payload = (u_char *)packet + sizeof(struct ip6_hdr);
if (handle->callback[dp_packet_ip6] != NULL)
{
int done = (handle->callback[dp_packet_ip6])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_ip6] != NULL) {
int done =
(handle->callback[dp_packet_ip6])(handle->userdata, header, packet);
if (done)
return;
}
switch ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt)
{
switch ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt) {
case IPPROTO_TCP:
dp_parse_tcp (handle, header, payload);
dp_parse_tcp(handle, header, payload);
break;
default:
// TODO: maybe support for non-tcp ipv6 packets
@@ -164,17 +154,16 @@ void dp_parse_ip6 (struct dp_handle * handle, const dp_header * header, const u_
}
}
void dp_parse_ethernet (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
const struct ether_header * ethernet = (struct ether_header *)packet;
u_char * payload = (u_char *) packet + sizeof (struct ether_header);
void dp_parse_ethernet(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
const struct ether_header *ethernet = (struct ether_header *)packet;
u_char *payload = (u_char *)packet + sizeof(struct ether_header);
u_int16_t protocol = 0;
/* call handle if it exists */
if (handle->callback[dp_packet_ethernet] != NULL)
{
int done = (handle->callback[dp_packet_ethernet])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_ethernet] != NULL) {
int done = (handle->callback[dp_packet_ethernet])(handle->userdata, header,
packet);
/* return if handle decides we're done */
if (done)
@@ -183,13 +172,12 @@ void dp_parse_ethernet (struct dp_handle * handle, const dp_header * header, con
/* parse payload */
protocol = ntohs(ethernet->ether_type);
switch (protocol)
{
switch (protocol) {
case ETHERTYPE_IP:
dp_parse_ip (handle, header, payload);
dp_parse_ip(handle, header, payload);
break;
case ETHERTYPE_IPV6:
dp_parse_ip6 (handle, header, payload);
dp_parse_ip6(handle, header, payload);
break;
default:
// TODO: maybe support for other protocols apart from IPv4 and IPv6
@@ -212,17 +200,16 @@ struct ppp_header {
u_int16_t packettype;
};
void dp_parse_ppp (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
const struct ppp_header * ppp = (struct ppp_header *) packet;
u_char * payload = (u_char *) packet + sizeof (struct ppp_header);
void dp_parse_ppp(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
const struct ppp_header *ppp = (struct ppp_header *)packet;
u_char *payload = (u_char *)packet + sizeof(struct ppp_header);
u_int16_t protocol = 0;
/* call handle if it exists */
if (handle->callback[dp_packet_ppp] != NULL)
{
int done = (handle->callback[dp_packet_ppp])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_ppp] != NULL) {
int done =
(handle->callback[dp_packet_ppp])(handle->userdata, header, packet);
/* return if handle decides we're done */
if (done)
@@ -231,13 +218,12 @@ void dp_parse_ppp (struct dp_handle * handle, const dp_header * header, const u_
/* parse payload */
protocol = ntohs(ppp->packettype);
switch (protocol)
{
switch (protocol) {
case ETHERTYPE_IP:
dp_parse_ip (handle, header, payload);
dp_parse_ip(handle, header, payload);
break;
case ETHERTYPE_IPV6:
dp_parse_ip6 (handle, header, payload);
dp_parse_ip6(handle, header, payload);
break;
default:
// TODO: support for other than IPv4 and IPv6
@@ -256,17 +242,16 @@ struct sll_header {
u_int16_t sll_protocol; /* protocol */
};
void dp_parse_linux_cooked (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{
const struct sll_header * sll = (struct sll_header *) packet;
u_char * payload = (u_char *) packet + sizeof (struct sll_header);
void dp_parse_linux_cooked(struct dp_handle *handle, const dp_header *header,
const u_char *packet) {
const struct sll_header *sll = (struct sll_header *)packet;
u_char *payload = (u_char *)packet + sizeof(struct sll_header);
u_int16_t protocol = 0;
/* call handle if it exists */
if (handle->callback[dp_packet_sll] != NULL)
{
int done = (handle->callback[dp_packet_sll])
(handle->userdata, header, packet);
if (handle->callback[dp_packet_sll] != NULL) {
int done =
(handle->callback[dp_packet_sll])(handle->userdata, header, packet);
/* return if handle decides we're done */
if (done)
@@ -275,13 +260,12 @@ void dp_parse_linux_cooked (struct dp_handle * handle, const dp_header * header,
/* parse payload */
protocol = ntohs(sll->sll_protocol);
switch (protocol)
{
switch (protocol) {
case ETHERTYPE_IP:
dp_parse_ip (handle, header, payload);
dp_parse_ip(handle, header, payload);
break;
case ETHERTYPE_IPV6:
dp_parse_ip6 (handle, header, payload);
dp_parse_ip6(handle, header, payload);
break;
default:
// TODO: support for other than IPv4 / IPv6
@@ -290,48 +274,48 @@ void dp_parse_linux_cooked (struct dp_handle * handle, const dp_header * header,
}
/* functions to do the monitoring */
void dp_pcap_callback (u_char * u_handle, const struct pcap_pkthdr * header, const u_char * packet)
{
struct dp_handle * handle = (struct dp_handle *) u_handle;
void dp_pcap_callback(u_char *u_handle, const struct pcap_pkthdr *header,
const u_char *packet) {
struct dp_handle *handle = (struct dp_handle *)u_handle;
struct dp_header;
/* make a copy of the userdata for every packet */
u_char * userdata_copy = (u_char *) malloc (handle->userdata_size);
memcpy (userdata_copy, handle->userdata, handle->userdata_size);
u_char *userdata_copy = (u_char *)malloc(handle->userdata_size);
memcpy(userdata_copy, handle->userdata, handle->userdata_size);
switch (handle->linktype) {
case (DLT_EN10MB):
dp_parse_ethernet (handle, header, packet);
dp_parse_ethernet(handle, header, packet);
break;
case (DLT_PPP):
dp_parse_ppp (handle, header, packet);
dp_parse_ppp(handle, header, packet);
break;
case (DLT_LINUX_SLL):
dp_parse_linux_cooked (handle, header, packet);
dp_parse_linux_cooked(handle, header, packet);
break;
case (DLT_RAW):
case (DLT_NULL):
// hope for the best
dp_parse_ip (handle, header, packet);
dp_parse_ip(handle, header, packet);
break;
default:
fprintf(stdout, "Unknown linktype %d", handle->linktype);
break;
}
free (userdata_copy);
free(userdata_copy);
}
int dp_dispatch (struct dp_handle * handle, int count, u_char *user, int size) {
int dp_dispatch(struct dp_handle *handle, int count, u_char *user, int size) {
handle->userdata = user;
handle->userdata_size = size;
return pcap_dispatch (handle->pcap_handle, count, dp_pcap_callback, (u_char *)handle);
return pcap_dispatch(handle->pcap_handle, count, dp_pcap_callback,
(u_char *)handle);
}
int dp_setnonblock (struct dp_handle * handle, int i, char * errbuf) {
return pcap_setnonblock (handle->pcap_handle, i, errbuf);
int dp_setnonblock(struct dp_handle *handle, int i, char *errbuf) {
return pcap_setnonblock(handle->pcap_handle, i, errbuf);
}
char * dp_geterr (struct dp_handle * handle)
{
return pcap_geterr (handle->pcap_handle);
char *dp_geterr(struct dp_handle *handle) {
return pcap_geterr(handle->pcap_handle);
}

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __DECPCAP_H
@@ -54,36 +55,38 @@ typedef struct pcap_pkthdr dp_header;
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];
pcap_t *pcap_handle;
dp_callback callback[dp_n_packet_types];
int linktype;
u_char * userdata;
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(const char * device, int snaplen, int promisc, int to_ms, char * errbuf);
struct dp_handle * dp_open_offline(char * fname, char * ebuf);
struct dp_handle *dp_open_live(const char *device, int snaplen, int promisc,
int to_ms, char *errbuf);
struct dp_handle *dp_open_offline(char *fname, char *ebuf);
/* functions to add callbacks */
void dp_addcb (struct dp_handle * handle, enum dp_packet_type type, dp_callback callback);
void dp_addcb(struct dp_handle *handle, enum dp_packet_type type,
dp_callback callback);
/* functions to parse payloads */
void dp_parse (enum dp_packet_type type, void * packet);
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);
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);
int dp_datalink(struct dp_handle *handle);
int dp_setnonblock (struct dp_handle * handle, int i, char * errbuf);
int dp_setnonblock(struct dp_handle *handle, int i, char *errbuf);
char * dp_geterr (struct dp_handle * handle);
char *dp_geterr(struct dp_handle *handle);
#endif

View File

@@ -15,36 +15,34 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <iostream>
extern "C" {
#include "decpcap.h"
#include "decpcap.h"
}
int process_tcp (u_char * /* userdata */, const dp_header * /* header */, const u_char * /* m_packet */) {
int process_tcp(u_char * /* userdata */, const dp_header * /* header */,
const u_char * /* m_packet */) {
std::cout << "Callback for processing TCP packet called" << std::endl;
return 0;
}
int main (int argc, char ** argv)
{
if (argc < 2)
{
int main(int argc, char **argv) {
if (argc < 2) {
std::cout << "Please, enter a filename" << std::endl;
}
char* errbuf = new char[DP_ERRBUF_SIZE];
char *errbuf = new char[DP_ERRBUF_SIZE];
dp_handle * newhandle = dp_open_offline(argv[1], errbuf);
dp_addcb (newhandle, dp_packet_tcp, process_tcp);
int ret = dp_dispatch (newhandle, -1, NULL, 0);
if (ret == -1)
{
dp_handle *newhandle = dp_open_offline(argv[1], errbuf);
dp_addcb(newhandle, dp_packet_tcp, process_tcp);
int ret = dp_dispatch(newhandle, -1, NULL, 0);
if (ret == -1) {
std::cout << "Error dispatching: " << dp_geterr(newhandle);
}
}

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
@@ -28,7 +29,7 @@
#include <net/if.h>
#include <ifaddrs.h>
bool selected(int devc, char** devicenames, char* devicename) {
bool selected(int devc, char **devicenames, char *devicename) {
if (devc == 0)
return true;
@@ -39,9 +40,8 @@ bool selected(int devc, char** devicenames, char* devicename) {
return false;
}
bool already_seen(device* devices, char* devicename) {
for (class device* current_device = devices;
current_device != NULL;
bool already_seen(device *devices, char *devicename) {
for (class device *current_device = devices; current_device != NULL;
current_device = current_device->next) {
if (strcmp(current_device->name, devicename) == 0)
return true;
@@ -52,29 +52,26 @@ bool already_seen(device* devices, char* devicename) {
// The interface is up, not a loopback and running?
bool up_running(int ifa_flags) {
std::cout << "up: " << (ifa_flags & IFF_UP) << std::endl;
return !(ifa_flags & IFF_LOOPBACK) &&
(ifa_flags & IFF_UP) &&
return !(ifa_flags & IFF_LOOPBACK) && (ifa_flags & IFF_UP) &&
(ifa_flags & IFF_RUNNING);
}
/**
* This function can return null, if no good interface is found
* When 'all' is set to 'false', the function avoids loopback interface and down/not running interfaces
* When 'all' is set to 'false', the function avoids loopback interface and
* down/not running interfaces
*/
device * get_devices(int devc, char** devicenames, bool all)
{
device *get_devices(int devc, char **devicenames, bool all) {
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1)
{
if (getifaddrs(&ifaddr) == -1) {
std::cerr << "Fail to get interface addresses" << std::endl;
// perror("getifaddrs");
return NULL;
}
device* devices = NULL;
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
device *devices = NULL;
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
if (!selected(devc, devicenames, ifa->ifa_name))
@@ -84,13 +81,11 @@ device * get_devices(int devc, char** devicenames, bool all)
if (!all && !up_running(ifa->ifa_flags))
continue;
devices = new device(strdup(ifa->ifa_name),devices);
devices = new device(strdup(ifa->ifa_name), devices);
}
freeifaddrs(ifaddr);
return devices;
}
device * get_default_devices() {
return get_devices(0, NULL, false);
}
device *get_default_devices() { return get_devices(0, NULL, false); }

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
@@ -26,16 +27,16 @@
class device {
public:
device (const char * m_name, device * m_next = NULL)
{
name = m_name; next = m_next;
device(const char *m_name, device *m_next = NULL) {
name = m_name;
next = m_next;
}
const char * name;
device * next;
const char *name;
device *next;
};
/** get all devices that are up, running and not loopback */
device * get_default_devices();
device *get_default_devices();
/**
* Get all specified devices.
@@ -44,6 +45,6 @@ device * get_default_devices();
* when 'all' is set, also return loopback interfaces and interfaces
* that are down or not running
*/
device * get_devices(int devc, char** devv, bool all);
device *get_devices(int devc, char **devv, bool all);
#endif

View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <sys/types.h>
#include <cerrno>
#include <cstring>
@@ -42,22 +42,23 @@ extern bool bughuntmode;
// Not sure, but assuming there's no more PID's than go into 64 unsigned bits..
const int MAX_PID_LENGTH = 20;
// Max length of filenames in /proc/<pid>/fd/*. These are numeric, so 10 digits seems like a safe assumption.
// Max length of filenames in /proc/<pid>/fd/*. These are numeric, so 10 digits
// seems like a safe assumption.
const int MAX_FDLINK = 10;
/* maps from inode to program-struct */
std::map <unsigned long, prg_node *> inodeproc;
std::map<unsigned long, prg_node *> inodeproc;
bool is_number (const char * string) {
bool is_number(const char *string) {
while (*string) {
if (!isdigit (*string))
if (!isdigit(*string))
return false;
string++;
}
return true;
}
unsigned long str2ulong (const char * ptr) {
unsigned long str2ulong(const char *ptr) {
unsigned long retval = 0;
while ((*ptr >= '0') && (*ptr <= '9')) {
@@ -68,7 +69,7 @@ unsigned long str2ulong (const char * ptr) {
return retval;
}
int str2int (const char * ptr) {
int str2int(const char *ptr) {
int retval = 0;
while ((*ptr >= '0') && (*ptr <= '9')) {
@@ -79,7 +80,7 @@ int str2int (const char * ptr) {
return retval;
}
static std::string read_file (int fd) {
static std::string read_file(int fd) {
char buf[255];
std::string content;
@@ -94,11 +95,12 @@ static std::string read_file (int fd) {
return content;
}
static std::string read_file (const char* filepath) {
static std::string read_file(const char *filepath) {
int fd = open(filepath, O_RDONLY);
if (fd < 0) {
std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno));
std::fprintf(stderr, "Error opening %s: %s\n", filepath,
std::strerror(errno));
std::exit(3);
return NULL;
}
@@ -106,14 +108,15 @@ static std::string read_file (const char* filepath) {
std::string contents = read_file(fd);
if (close(fd)) {
std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno));
std::fprintf(stderr, "Error opening %s: %s\n", filepath,
std::strerror(errno));
std::exit(34);
}
return contents;
}
std::string getprogname (pid_t pid) {
std::string getprogname(pid_t pid) {
const int maxfilenamelen = 14 + MAX_PID_LENGTH + 1;
char filename[maxfilenamelen];
@@ -121,11 +124,11 @@ std::string getprogname (pid_t pid) {
return read_file(filename);
}
void setnode (unsigned long inode, pid_t pid) {
prg_node * current_value = inodeproc[inode];
void setnode(unsigned long inode, pid_t pid) {
prg_node *current_value = inodeproc[inode];
if (current_value == NULL || current_value->pid != pid) {
prg_node * newnode = new prg_node;
prg_node *newnode = new prg_node;
newnode->inode = inode;
newnode->pid = pid;
newnode->name = getprogname(pid);
@@ -135,7 +138,7 @@ void setnode (unsigned long inode, pid_t pid) {
}
}
void get_info_by_linkname (const char * pid, const char * linkname) {
void get_info_by_linkname(const char *pid, const char *linkname) {
if (strncmp(linkname, "socket:[", 8) == 0) {
setnode(str2ulong(linkname + 8), str2int(pid));
}
@@ -145,106 +148,99 @@ void get_info_by_linkname (const char * pid, const char * linkname) {
* for all inodes belonging to this PID
* (/proc/pid/fd/42)
* */
void get_info_for_pid(const char * pid) {
void get_info_for_pid(const char *pid) {
char dirname[10 + MAX_PID_LENGTH];
size_t dirlen = 10 + strlen(pid);
snprintf(dirname, dirlen, "/proc/%s/fd", pid);
DIR * dir = opendir(dirname);
DIR *dir = opendir(dirname);
if (!dir)
{
if (bughuntmode)
{
std::cout << "Couldn't open dir " << dirname << ": " << strerror(errno) << "\n";
if (!dir) {
if (bughuntmode) {
std::cout << "Couldn't open dir " << dirname << ": " << strerror(errno)
<< "\n";
}
return;
}
/* walk through /proc/%s/fd/... */
dirent * entry;
dirent *entry;
while ((entry = readdir(dir))) {
if (entry->d_type != DT_LNK)
continue;
//std::cout << "Looking at: " << entry->d_name << std::endl;
// std::cout << "Looking at: " << entry->d_name << std::endl;
size_t fromlen = dirlen + strlen(entry->d_name) + 1;
char fromname[10 + MAX_PID_LENGTH + 1 + MAX_FDLINK];
snprintf (fromname, fromlen, "%s/%s", dirname, entry->d_name);
snprintf(fromname, fromlen, "%s/%s", dirname, entry->d_name);
//std::cout << "Linking from: " << fromname << std::endl;
// std::cout << "Linking from: " << fromname << std::endl;
int linklen = 80;
char linkname [linklen];
int usedlen = readlink(fromname, linkname, linklen-1);
if (usedlen == -1)
{
char linkname[linklen];
int usedlen = readlink(fromname, linkname, linklen - 1);
if (usedlen == -1) {
continue;
}
assert (usedlen < linklen);
assert(usedlen < linklen);
linkname[usedlen] = '\0';
get_info_by_linkname (pid, linkname);
get_info_by_linkname(pid, linkname);
}
closedir(dir);
}
/* updates the `inodeproc' inode-to-prg_node mapping
* for all processes in /proc */
void reread_mapping () {
DIR * proc = opendir ("/proc");
void reread_mapping() {
DIR *proc = opendir("/proc");
if (proc == 0) {
std::cerr << "Error reading /proc, neede to get inode-to-pid-maping\n";
exit(1);
}
dirent * entry;
dirent *entry;
while ((entry = readdir(proc))) {
if (entry->d_type != DT_DIR) continue;
if (entry->d_type != DT_DIR)
continue;
if (! is_number (entry->d_name)) continue;
if (!is_number(entry->d_name))
continue;
get_info_for_pid(entry->d_name);
}
closedir(proc);
}
struct prg_node * findPID (unsigned long inode)
{
struct prg_node *findPID(unsigned long inode) {
/* we first look in inodeproc */
struct prg_node * node = inodeproc[inode];
struct prg_node *node = inodeproc[inode];
if (node != NULL)
{
if (bughuntmode)
{
if (node != NULL) {
if (bughuntmode) {
std::cout << ":) Found pid in inodeproc table" << std::endl;
}
return node;
}
#ifndef __APPLE__
#ifndef __APPLE__
reread_mapping();
#endif
#endif
struct prg_node * retval = inodeproc[inode];
if (bughuntmode)
{
if (retval == NULL)
{
struct prg_node *retval = inodeproc[inode];
if (bughuntmode) {
if (retval == NULL) {
std::cout << ":( No pid after inodeproc refresh" << std::endl;
}
else
{
} else {
std::cout << ":) Found pid after inodeproc refresh" << std::endl;
}
}
return retval;
}
void prg_cache_clear() {};
void prg_cache_clear(){};
/*void main () {
std::cout << "Fooo\n";

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __INODE2PROG_h
@@ -33,11 +34,11 @@ struct prg_node {
std::string name;
};
struct prg_node * findPID (unsigned long inode);
struct prg_node *findPID(unsigned long inode);
void prg_cache_clear();
// reread the inode-to-prg_node-mapping
void reread_mapping ();
void reread_mapping();
#endif

View File

@@ -1,6 +1,5 @@
extern "C"
{
#include "libnethogs.h"
extern "C" {
#include "libnethogs.h"
}
#include "nethogs.cpp"
@@ -13,31 +12,30 @@ extern "C"
#include <errno.h>
//////////////////////////////
extern ProcList * processes;
extern Process * unknowntcp;
extern Process * unknownudp;
extern Process * unknownip;
extern ProcList *processes;
extern Process *unknowntcp;
extern Process *unknownudp;
extern Process *unknownip;
//////////////////////////////
//The self_pipe is used to interrupt the select() in the main loop
static std::pair<int,int> self_pipe = std::make_pair(-1, -1);
// The self_pipe is used to interrupt the select() in the main loop
static std::pair<int, int> self_pipe = std::make_pair(-1, -1);
static bool monitor_run_flag = false;
typedef std::map<void*, NethogsMonitorRecord> NethogsRecordMap;
typedef std::map<void *, NethogsMonitorRecord> NethogsRecordMap;
static NethogsRecordMap monitor_record_map;
static int monitor_refresh_delay = 1;
static time_t monitor_last_refresh_time = 0;
//selectable file descriptors for the main loop
// selectable file descriptors for the main loop
static fd_set pc_loop_fd_set;
static std::vector<int> pc_loop_fd_list;
static bool pc_loop_use_select = true;
static handle * handles = NULL;
static handle *handles = NULL;
static std::pair<int, int> create_self_pipe()
{
static std::pair<int, int> create_self_pipe() {
int pfd[2];
if (pipe(pfd) == -1)
return std::make_pair(-1, -1);
@@ -51,73 +49,63 @@ static std::pair<int, int> create_self_pipe()
return std::make_pair(pfd[0], pfd[1]);
}
static bool wait_for_next_trigger()
{
if( pc_loop_use_select )
{
static bool wait_for_next_trigger() {
if (pc_loop_use_select) {
FD_ZERO(&pc_loop_fd_set);
int nfds = 0;
for(std::vector<int>::const_iterator it=pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it)
{
for (std::vector<int>::const_iterator it = pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it) {
int const fd = *it;
nfds = std::max(nfds, *it + 1);
FD_SET(fd, &pc_loop_fd_set);
}
timeval timeout = {monitor_refresh_delay, 0};
if( select(nfds, &pc_loop_fd_set, 0, 0, &timeout) != -1 )
{
if( FD_ISSET(self_pipe.first, &pc_loop_fd_set) )
{
if (select(nfds, &pc_loop_fd_set, 0, 0, &timeout) != -1) {
if (FD_ISSET(self_pipe.first, &pc_loop_fd_set)) {
return false;
}
}
}
else
{
} else {
// If select() not possible, pause to prevent 100%
usleep(1000);
}
return true;
}
static int nethogsmonitor_init()
{
static int nethogsmonitor_init() {
process_init();
device * devices = get_default_devices();
if ( devices == NULL )
{
device *devices = get_default_devices();
if (devices == NULL) {
std::cerr << "No devices to monitor" << std::endl;
return NETHOGS_STATUS_NO_DEVICE;
}
device * current_dev = devices;
device *current_dev = devices;
bool promiscuous = false;
int nb_devices = 0;
int nb_failed_devices = 0;
while (current_dev != NULL)
{
while (current_dev != NULL) {
++nb_devices;
if( !getLocal(current_dev->name, false) )
{
std::cerr << "getifaddrs failed while establishing local IP." << std::endl;
if (!getLocal(current_dev->name, false)) {
std::cerr << "getifaddrs failed while establishing local IP."
<< std::endl;
++nb_failed_devices;
continue;
}
char errbuf[PCAP_ERRBUF_SIZE];
dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promiscuous, 100, errbuf);
if (newhandle != NULL)
{
dp_addcb (newhandle, dp_packet_ip, process_ip);
dp_addcb (newhandle, dp_packet_ip6, process_ip6);
dp_addcb (newhandle, dp_packet_tcp, process_tcp);
dp_addcb (newhandle, dp_packet_udp, process_udp);
dp_handle *newhandle =
dp_open_live(current_dev->name, BUFSIZ, promiscuous, 100, errbuf);
if (newhandle != NULL) {
dp_addcb(newhandle, dp_packet_ip, process_ip);
dp_addcb(newhandle, dp_packet_ip6, process_ip6);
dp_addcb(newhandle, dp_packet_tcp, process_tcp);
dp_addcb(newhandle, dp_packet_udp, process_udp);
/* The following code solves sf.net bug 1019381, but is only available
* in newer versions (from 0.8 it seems) of libpcap
@@ -125,53 +113,43 @@ static int nethogsmonitor_init()
* update: version 0.7.2, which is in debian stable now, should be ok
* also.
*/
if (dp_setnonblock (newhandle, 1, errbuf) == -1)
{
if (dp_setnonblock(newhandle, 1, errbuf) == -1) {
fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
}
handles = new handle (newhandle, current_dev->name, handles);
handles = new handle(newhandle, current_dev->name, handles);
if( pc_loop_use_select )
{
//some devices may not support pcap_get_selectable_fd
if (pc_loop_use_select) {
// some devices may not support pcap_get_selectable_fd
int const fd = pcap_get_selectable_fd(newhandle->pcap_handle);
if( fd != -1 )
{
if (fd != -1) {
pc_loop_fd_list.push_back(fd);
}
else
{
} else {
pc_loop_use_select = false;
pc_loop_fd_list.clear();
fprintf(stderr, "failed to get selectable_fd for %s\n", current_dev->name);
fprintf(stderr, "failed to get selectable_fd for %s\n",
current_dev->name);
}
}
}
else
{
fprintf(stderr, "ERROR: opening handler for device %s: %s\n", current_dev->name, strerror(errno));
} else {
fprintf(stderr, "ERROR: opening handler for device %s: %s\n",
current_dev->name, strerror(errno));
++nb_failed_devices;
}
current_dev = current_dev->next;
}
if(nb_devices == nb_failed_devices)
{
if (nb_devices == nb_failed_devices) {
return NETHOGS_STATUS_FAILURE;
}
//use the Self-Pipe trick to interrupt the select() in the main loop
if( pc_loop_use_select )
{
// use the Self-Pipe trick to interrupt the select() in the main loop
if (pc_loop_use_select) {
self_pipe = create_self_pipe();
if( self_pipe.first == -1 || self_pipe.second == -1 )
{
if (self_pipe.first == -1 || self_pipe.second == -1) {
std::cerr << "Error creating pipe file descriptors\n";
pc_loop_use_select = false;
}
else
{
} else {
pc_loop_fd_list.push_back(self_pipe.first);
}
}
@@ -179,74 +157,67 @@ static int nethogsmonitor_init()
return NETHOGS_STATUS_OK;
}
static void nethogsmonitor_handle_update(NethogsMonitorCallback cb)
{
static void nethogsmonitor_handle_update(NethogsMonitorCallback cb) {
refreshconninode();
refreshcount++;
ProcList * curproc = processes;
ProcList * previousproc = NULL;
ProcList *curproc = processes;
ProcList *previousproc = NULL;
int nproc = processes->size();
while (curproc != NULL)
{
while (curproc != NULL) {
// walk though its connections, summing up their data, and
// throwing away connections that haven't received a package
// in the last PROCESSTIMEOUT seconds.
assert (curproc != NULL);
assert (curproc->getVal() != NULL);
assert (nproc == processes->size());
assert(curproc != NULL);
assert(curproc->getVal() != NULL);
assert(nproc == processes->size());
/* remove timed-out processes (unless it's one of the the unknown process) */
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec)
&& (curproc->getVal() != unknowntcp)
&& (curproc->getVal() != unknownudp)
&& (curproc->getVal() != unknownip))
{
/* remove timed-out processes (unless it's one of the the unknown process)
*/
if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <=
curtime.tv_sec) &&
(curproc->getVal() != unknowntcp) &&
(curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) {
if (DEBUG)
std::cout << "PROC: Deleting process\n";
NethogsRecordMap::iterator it = monitor_record_map.find(curproc);
if( it != monitor_record_map.end() )
{
NethogsMonitorRecord& data = it->second;
if (it != monitor_record_map.end()) {
NethogsMonitorRecord &data = it->second;
(*cb)(NETHOGS_APP_ACTION_REMOVE, &data);
monitor_record_map.erase(curproc);
}
ProcList * todelete = curproc;
Process * p_todelete = curproc->getVal();
if (previousproc)
{
ProcList *todelete = curproc;
Process *p_todelete = curproc->getVal();
if (previousproc) {
previousproc->next = curproc->next;
curproc = curproc->next;
} else
{
} else {
processes = curproc->getNext();
curproc = processes;
}
delete todelete;
delete p_todelete;
nproc--;
//continue;
}
else
{
// continue;
} else {
const u_int32_t uid = curproc->getVal()->getUid();
u_int32_t sent_bytes;
u_int32_t recv_bytes;
float sent_kbs;
float recv_kbs;
curproc->getVal()->getkbps (&recv_kbs, &sent_kbs);
curproc->getVal()->gettotal (&recv_bytes, &sent_bytes);
curproc->getVal()->getkbps(&recv_kbs, &sent_kbs);
curproc->getVal()->gettotal(&recv_bytes, &sent_bytes);
//notify update
bool const new_data = (monitor_record_map.find(curproc) == monitor_record_map.end());
// notify update
bool const new_data =
(monitor_record_map.find(curproc) == monitor_record_map.end());
NethogsMonitorRecord &data = monitor_record_map[curproc];
bool data_change = false;
if( new_data )
{
if (new_data) {
data_change = true;
static int record_id = 0;
++record_id;
@@ -258,102 +229,90 @@ static void nethogsmonitor_handle_update(NethogsMonitorCallback cb)
data.device_name = curproc->getVal()->devicename;
#define NHM_UPDATE_ONE_FIELD(TO,FROM) if((TO)!=(FROM)) { TO = FROM; data_change = true; }
#define NHM_UPDATE_ONE_FIELD(TO, FROM) \
if ((TO) != (FROM)) { \
TO = FROM; \
data_change = true; \
}
NHM_UPDATE_ONE_FIELD( data.uid, uid )
NHM_UPDATE_ONE_FIELD( data.sent_bytes, sent_bytes )
NHM_UPDATE_ONE_FIELD( data.recv_bytes, recv_bytes )
NHM_UPDATE_ONE_FIELD( data.sent_kbs, sent_kbs )
NHM_UPDATE_ONE_FIELD( data.recv_kbs, recv_kbs )
NHM_UPDATE_ONE_FIELD(data.uid, uid)
NHM_UPDATE_ONE_FIELD(data.sent_bytes, sent_bytes)
NHM_UPDATE_ONE_FIELD(data.recv_bytes, recv_bytes)
NHM_UPDATE_ONE_FIELD(data.sent_kbs, sent_kbs)
NHM_UPDATE_ONE_FIELD(data.recv_kbs, recv_kbs)
#undef NHM_UPDATE_ONE_FIELD
#undef NHM_UPDATE_ONE_FIELD
if( data_change )
{
if (data_change) {
(*cb)(NETHOGS_APP_ACTION_SET, &data);
}
//next
// next
previousproc = curproc;
curproc = curproc->next;
}
}
}
static void nethogsmonitor_clean_up()
{
//clean up
handle * current_handle = handles;
while (current_handle != NULL)
{
static void nethogsmonitor_clean_up() {
// clean up
handle *current_handle = handles;
while (current_handle != NULL) {
pcap_close(current_handle->content->pcap_handle);
current_handle = current_handle->next;
}
//close file descriptors
for(std::vector<int>::const_iterator it=pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it)
{
// close file descriptors
for (std::vector<int>::const_iterator it = pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it) {
close(*it);
}
procclean();
}
int nethogsmonitor_loop(NethogsMonitorCallback cb)
{
if( monitor_run_flag )
{
int nethogsmonitor_loop(NethogsMonitorCallback cb) {
if (monitor_run_flag) {
return NETHOGS_STATUS_FAILURE;
}
int return_value = nethogsmonitor_init();
if( return_value != NETHOGS_STATUS_OK )
{
if (return_value != NETHOGS_STATUS_OK) {
return return_value;
}
monitor_run_flag = true;
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
struct dpargs *userdata = (dpargs *)malloc(sizeof(struct dpargs));
// Main loop
while (monitor_run_flag)
{
while (monitor_run_flag) {
bool packets_read = false;
handle * current_handle = handles;
while (current_handle != NULL)
{
handle *current_handle = handles;
while (current_handle != NULL) {
userdata->device = current_handle->devicename;
userdata->sa_family = AF_UNSPEC;
int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
if (retval < 0)
{
int retval = dp_dispatch(current_handle->content, -1, (u_char *)userdata,
sizeof(struct dpargs));
if (retval < 0) {
std::cerr << "Error dispatching: " << retval << std::endl;
}
else if (retval != 0)
{
} else if (retval != 0) {
packets_read = true;
}
else
{
} else {
gettimeofday(&curtime, NULL);
}
current_handle = current_handle->next;
}
time_t const now = ::time(NULL);
if( monitor_last_refresh_time + monitor_refresh_delay <= now )
{
if (monitor_last_refresh_time + monitor_refresh_delay <= now) {
monitor_last_refresh_time = now;
nethogsmonitor_handle_update(cb);
}
if (!packets_read)
{
if( !wait_for_next_trigger() )
{
if (!packets_read) {
if (!wait_for_next_trigger()) {
break;
}
}
@@ -364,8 +323,7 @@ int nethogsmonitor_loop(NethogsMonitorCallback cb)
return NETHOGS_STATUS_OK;
}
void nethogsmonitor_breakloop()
{
void nethogsmonitor_breakloop() {
monitor_run_flag = false;
write(self_pipe.second, "x", 1);
}

View File

@@ -8,46 +8,51 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#define NETHOGS_DSO_VISIBLE __attribute__ ((visibility ("default")))
#define NETHOGS_DSO_HIDDEN __attribute__ ((visibility ("hidden")))
#define NETHOGS_DSO_VISIBLE __attribute__((visibility("default")))
#define NETHOGS_DSO_HIDDEN __attribute__((visibility("hidden")))
#define NETHOGS_APP_ACTION_SET 1
#define NETHOGS_APP_ACTION_REMOVE 2
#define NETHOGS_STATUS_OK 0
#define NETHOGS_STATUS_FAILURE 1 //generic error
#define NETHOGS_STATUS_NO_DEVICE 2 //no device foundr
#define NETHOGS_STATUS_FAILURE 1 // generic error
#define NETHOGS_STATUS_NO_DEVICE 2 // no device foundr
typedef struct NethogsMonitorRecord
{
typedef struct NethogsMonitorRecord {
int record_id;
const char* name;
const char *name;
int pid;
uint32_t uid;
const char* device_name;
const char *device_name;
uint32_t sent_bytes;
uint32_t recv_bytes;
float sent_kbs;
float recv_kbs;
} NethogsMonitorRecord;
/**
* @brief Defines a callback to handle updates about applications
* @param action NETHOGS_APP_ACTION_SET if data is beeing added or updated,
* NETHOGS_APP_ACTION_REMOVE if data is beeing removed.
* the record_id member is used to uniquely identify the data beeing update or removed.
* @param data a pointer to an application usage data. the pointer remains valid until
* the callback is called with NETHOGS_APP_ACTION_REMOVE for the same pointer.
* the user should not modify the content of the structure pointed by data.
* the record_id member is used to uniquely identify the data beeing
* update or removed.
* @param data a pointer to an application usage data. the pointer remains valid
* until
* the callback is called with NETHOGS_APP_ACTION_REMOVE for the same
* pointer.
* the user should not modify the content of the structure pointed by
* data.
*/
typedef void(*NethogsMonitorCallback)(int action, NethogsMonitorRecord const* data);
typedef void (*NethogsMonitorCallback)(int action,
NethogsMonitorRecord const *data);
/**
* @brief Enter the process monitoring loop and reports updates using the
* callback provided as parameter.
* This call will block until nethogsmonitor_breakloop() is called or a failure occurs.
* @param cb A pointer to a callback function following the NethogsMonitorCallback definition
* This call will block until nethogsmonitor_breakloop() is called or a failure
* occurs.
* @param cb A pointer to a callback function following the
* NethogsMonitorCallback definition
*/
NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb);

183
main.cpp
View File

@@ -2,39 +2,40 @@
#include <fcntl.h>
#include <vector>
//The self_pipe is used to interrupt the select() in the main loop
static std::pair<int,int> self_pipe = std::make_pair(-1, -1);
// The self_pipe is used to interrupt the select() in the main loop
static std::pair<int, int> self_pipe = std::make_pair(-1, -1);
static time_t last_refresh_time = 0;
//selectable file descriptors for the main loop
// selectable file descriptors for the main loop
static fd_set pc_loop_fd_set;
static std::vector<int> pc_loop_fd_list;
static bool pc_loop_use_select = true;
static void versiondisplay(void) { std::cout << version << "\n"; }
static void versiondisplay(void)
{
std::cout << version << "\n";
}
static void help(bool iserror) {
std::ostream &output = (iserror ? std::cerr : std::cout);
static void help(bool iserror)
{
std::ostream & output = (iserror ? std::cerr : std::cout);
//output << "usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n";
output << "usage: nethogs [-V] [-h] [-b] [-d seconds] [-v mode] [-c count] [-t] [-p] [-s] [device [device [device ...]]]\n";
// output << "usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [-f (eth|ppp))]
// [device [device [device ...]]]\n";
output << "usage: nethogs [-V] [-h] [-b] [-d seconds] [-v mode] [-c count] "
"[-t] [-p] [-s] [device [device [device ...]]]\n";
output << " -V : prints version.\n";
output << " -h : prints this help.\n";
output << " -b : bughunt mode - implies tracemode.\n";
output << " -d : delay for update refresh rate in seconds. default is 1.\n";
output << " -v : view mode (0 = KB/s, 1 = total KB, 2 = total B, 3 = total MB). default is 0.\n";
output << " -d : delay for update refresh rate in seconds. default "
"is 1.\n";
output << " -v : view mode (0 = KB/s, 1 = total KB, 2 = total B, 3 "
"= total MB). default is 0.\n";
output << " -c : number of updates. default is 0 (unlimited).\n";
output << " -t : tracemode.\n";
//output << " -f : format of packets on interface, default is eth.\n";
// output << " -f : format of packets on interface, default is
// eth.\n";
output << " -p : sniff in promiscious mode (not recommended).\n";
output << " -s : sort output by sent column.\n";
output << " -a : monitor all devices, even loopback/stopped ones.\n";
output << " device : device(s) to monitor. default is all interfaces up and running excluding loopback\n";
output << " device : device(s) to monitor. default is all "
"interfaces up and running excluding loopback\n";
output << std::endl;
output << "When nethogs is running, press:\n";
output << " q: quit\n";
@@ -43,22 +44,16 @@ static void help(bool iserror)
output << " m: switch between total (KB, B, MB) and KB/s mode\n";
}
void quit_cb (int /* i */)
{
if( self_pipe.second != -1 )
{
void quit_cb(int /* i */) {
if (self_pipe.second != -1) {
write(self_pipe.second, "x", 1);
}
else
{
} else {
exit(0);
}
}
void forceExit(bool success, const char *msg, ...)
{
if ((!tracemode)&&(!DEBUG)){
void forceExit(bool success, const char *msg, ...) {
if ((!tracemode) && (!DEBUG)) {
exit_ui();
}
@@ -74,8 +69,7 @@ void forceExit(bool success, const char *msg, ...)
exit(EXIT_FAILURE);
}
std::pair<int, int> create_self_pipe()
{
std::pair<int, int> create_self_pipe() {
int pfd[2];
if (pipe(pfd) == -1)
return std::make_pair(-1, -1);
@@ -89,43 +83,33 @@ std::pair<int, int> create_self_pipe()
return std::make_pair(pfd[0], pfd[1]);
}
bool wait_for_next_trigger()
{
if( pc_loop_use_select )
{
bool wait_for_next_trigger() {
if (pc_loop_use_select) {
FD_ZERO(&pc_loop_fd_set);
int nfds = 0;
for(std::vector<int>::const_iterator it=pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it)
{
for (std::vector<int>::const_iterator it = pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it) {
int const fd = *it;
nfds = std::max(nfds, *it + 1);
FD_SET(fd, &pc_loop_fd_set);
}
timeval timeout = {refreshdelay, 0};
if( select(nfds, &pc_loop_fd_set, 0, 0, &timeout) != -1 )
{
if( FD_ISSET(self_pipe.first, &pc_loop_fd_set) )
{
if (select(nfds, &pc_loop_fd_set, 0, 0, &timeout) != -1) {
if (FD_ISSET(self_pipe.first, &pc_loop_fd_set)) {
return false;
}
}
}
else
{
} else {
// If select() not possible, pause to prevent 100%
usleep(1000);
}
return true;
}
void clean_up()
{
//close file descriptors
for(std::vector<int>::const_iterator it=pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it)
{
void clean_up() {
// close file descriptors
for (std::vector<int>::const_iterator it = pc_loop_fd_list.begin();
it != pc_loop_fd_list.end(); ++it) {
close(*it);
}
@@ -134,8 +118,7 @@ void clean_up()
exit_ui();
}
int main (int argc, char** argv)
{
int main(int argc, char **argv) {
process_init();
int promisc = 0;
@@ -143,7 +126,7 @@ int main (int argc, char** argv)
int opt;
while ((opt = getopt(argc, argv, "Vahbtpd:v:c:sa")) != -1) {
switch(opt) {
switch (opt) {
case 'V':
versiondisplay();
exit(0);
@@ -181,47 +164,44 @@ int main (int argc, char** argv)
}
}
device * devices = get_devices(argc - optind, argv + optind, all);
device *devices = get_devices(argc - optind, argv + optind, all);
if (devices == NULL)
forceExit(false, "No devices to monitor. Use '-a' to allow monitoring loopback interfaces or devices that are not up/running");
forceExit(false, "No devices to monitor. Use '-a' to allow monitoring "
"loopback interfaces or devices that are not up/running");
if ((!tracemode) && (!DEBUG)){
if ((!tracemode) && (!DEBUG)) {
init_ui();
}
if (NEEDROOT && (geteuid() != 0))
forceExit(false, "You need to be root to run NetHogs!");
//use the Self-Pipe trick to interrupt the select() in the main loop
// use the Self-Pipe trick to interrupt the select() in the main loop
self_pipe = create_self_pipe();
if( self_pipe.first == -1 || self_pipe.second == -1 )
{
if (self_pipe.first == -1 || self_pipe.second == -1) {
forceExit(false, "Error creating pipe file descriptors\n");
}
else
{
//add the self-pipe to allow interrupting select()
} else {
// add the self-pipe to allow interrupting select()
pc_loop_fd_list.push_back(self_pipe.first);
}
char errbuf[PCAP_ERRBUF_SIZE];
handle * handles = NULL;
device * current_dev = devices;
handle *handles = NULL;
device *current_dev = devices;
while (current_dev != NULL) {
if( !getLocal(current_dev->name, tracemode) )
{
if (!getLocal(current_dev->name, tracemode)) {
forceExit(false, "getifaddrs failed while establishing local IP.");
}
dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf);
if (newhandle != NULL)
{
dp_addcb (newhandle, dp_packet_ip, process_ip);
dp_addcb (newhandle, dp_packet_ip6, process_ip6);
dp_addcb (newhandle, dp_packet_tcp, process_tcp);
dp_addcb (newhandle, dp_packet_udp, process_udp);
dp_handle *newhandle =
dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf);
if (newhandle != NULL) {
dp_addcb(newhandle, dp_packet_ip, process_ip);
dp_addcb(newhandle, dp_packet_ip6, process_ip6);
dp_addcb(newhandle, dp_packet_tcp, process_tcp);
dp_addcb(newhandle, dp_packet_udp, process_udp);
/* The following code solves sf.net bug 1019381, but is only available
* in newer versions (from 0.8 it seems) of libpcap
@@ -229,51 +209,48 @@ int main (int argc, char** argv)
* update: version 0.7.2, which is in debian stable now, should be ok
* also.
*/
if (dp_setnonblock (newhandle, 1, errbuf) == -1)
{
if (dp_setnonblock(newhandle, 1, errbuf) == -1) {
fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
}
handles = new handle (newhandle, current_dev->name, handles);
handles = new handle(newhandle, current_dev->name, handles);
if( pc_loop_use_select )
{
//some devices may not support pcap_get_selectable_fd
if (pc_loop_use_select) {
// some devices may not support pcap_get_selectable_fd
int const fd = pcap_get_selectable_fd(newhandle->pcap_handle);
if( fd != -1 )
{
if (fd != -1) {
pc_loop_fd_list.push_back(fd);
}
else
{
} else {
pc_loop_use_select = false;
pc_loop_fd_list.clear();
fprintf(stderr, "failed to get selectable_fd for %s\n", current_dev->name);
fprintf(stderr, "failed to get selectable_fd for %s\n",
current_dev->name);
}
}
}
else
{
fprintf(stderr, "Error opening handler for device %s\n", current_dev->name);
} else {
fprintf(stderr, "Error opening handler for device %s\n",
current_dev->name);
}
current_dev = current_dev->next;
}
signal (SIGINT, &quit_cb);
signal(SIGINT, &quit_cb);
fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
fprintf(
stderr,
"Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
struct dpargs *userdata = (dpargs *)malloc(sizeof(struct dpargs));
// Main loop:
while (1)
{
while (1) {
bool packets_read = false;
for (handle * current_handle = handles; current_handle != NULL; current_handle = current_handle->next)
{
for (handle *current_handle = handles; current_handle != NULL;
current_handle = current_handle->next) {
userdata->device = current_handle->devicename;
userdata->sa_family = AF_UNSPEC;
int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
int retval = dp_dispatch(current_handle->content, -1, (u_char *)userdata,
sizeof(struct dpargs));
if (retval < 0)
std::cerr << "Error dispatching: " << retval << std::endl;
else if (retval != 0)
@@ -281,11 +258,9 @@ int main (int argc, char** argv)
}
time_t const now = ::time(NULL);
if( last_refresh_time + refreshdelay <= now )
{
if (last_refresh_time + refreshdelay <= now) {
last_refresh_time = now;
if ((!DEBUG)&&(!tracemode))
{
if ((!DEBUG) && (!tracemode)) {
// handle user input
ui_tick();
}
@@ -294,7 +269,7 @@ int main (int argc, char** argv)
// if not packets, do a select() until next packet
if (!packets_read)
if( !wait_for_next_trigger() )
if (!wait_for_next_trigger())
// Shutdown requested - exit the loop
break;
}

View File

@@ -15,7 +15,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
@@ -40,7 +41,7 @@
#include "cui.h"
extern "C" {
#include "decpcap.h"
#include "decpcap.h"
}
#include "packet.h"
@@ -48,7 +49,7 @@ extern "C" {
#include "process.h"
#include "devices.h"
extern Process * unknownudp;
extern Process *unknownudp;
unsigned refreshdelay = 1;
unsigned refreshlimit = 0;
@@ -64,18 +65,16 @@ const char version[] = " version " VERSION "." SUBVERSION "." MINORVERSION;
timeval curtime;
bool local_addr::contains (const in_addr_t & n_addr) {
if ((sa_family == AF_INET)
&& (n_addr == addr))
bool local_addr::contains(const in_addr_t &n_addr) {
if ((sa_family == AF_INET) && (n_addr == addr))
return true;
if (next == NULL)
return false;
return next->contains(n_addr);
}
bool local_addr::contains(const struct in6_addr & n_addr) {
if (sa_family == AF_INET6)
{
bool local_addr::contains(const struct in6_addr &n_addr) {
if (sa_family == AF_INET6) {
/*
if (DEBUG) {
char addy [50];
@@ -86,9 +85,8 @@ bool local_addr::contains(const struct in6_addr & n_addr) {
std::cerr << addy << std::endl;
}
*/
//if (addr6.s6_addr == n_addr.s6_addr)
if (memcmp (&addr6, &n_addr, sizeof(struct in6_addr)) == 0)
{
// if (addr6.s6_addr == n_addr.s6_addr)
if (memcmp(&addr6, &n_addr, sizeof(struct in6_addr)) == 0) {
if (DEBUG)
std::cerr << "Match!" << std::endl;
return true;
@@ -100,7 +98,7 @@ bool local_addr::contains(const struct in6_addr & n_addr) {
}
struct dpargs {
const char * device;
const char *device;
int sa_family;
in_addr ip_src;
in_addr ip_dst;
@@ -108,49 +106,50 @@ struct dpargs {
in6_addr ip6_dst;
};
const char* getVersion()
{
return version;
}
const char *getVersion() { return version; }
int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) {
struct dpargs * args = (struct dpargs *) userdata;
struct tcphdr * tcp = (struct tcphdr *) m_packet;
int process_tcp(u_char *userdata, const dp_header *header,
const u_char *m_packet) {
struct dpargs *args = (struct dpargs *)userdata;
struct tcphdr *tcp = (struct tcphdr *)m_packet;
curtime = header->ts;
/* get info from userdata, then call getPacket */
Packet * packet;
switch (args->sa_family)
{
Packet *packet;
switch (args->sa_family) {
case AF_INET:
#ifdef __APPLE__
packet = new Packet (args->ip_src, ntohs(tcp->th_sport), args->ip_dst, ntohs(tcp->th_dport), header->len, header->ts);
#else
packet = new Packet (args->ip_src, ntohs(tcp->source), args->ip_dst, ntohs(tcp->dest), header->len, header->ts);
#endif
#ifdef __APPLE__
packet = new Packet(args->ip_src, ntohs(tcp->th_sport), args->ip_dst,
ntohs(tcp->th_dport), header->len, header->ts);
#else
packet = new Packet(args->ip_src, ntohs(tcp->source), args->ip_dst,
ntohs(tcp->dest), header->len, header->ts);
#endif
break;
case AF_INET6:
#ifdef __APPLE__
packet = new Packet (args->ip6_src, ntohs(tcp->th_sport), args->ip6_dst, ntohs(tcp->th_dport), header->len, header->ts);
#else
packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts);
#endif
#ifdef __APPLE__
packet = new Packet(args->ip6_src, ntohs(tcp->th_sport), args->ip6_dst,
ntohs(tcp->th_dport), header->len, header->ts);
#else
packet = new Packet(args->ip6_src, ntohs(tcp->source), args->ip6_dst,
ntohs(tcp->dest), header->len, header->ts);
#endif
break;
default:
std::cerr << "Invalid address family for TCP packet: " << args->sa_family << std::endl;
std::cerr << "Invalid address family for TCP packet: " << args->sa_family
<< std::endl;
return true;
}
Connection * connection = findConnection(packet);
Connection *connection = findConnection(packet);
if (connection != NULL)
{
if (connection != NULL) {
/* add packet to the connection */
connection->add(packet);
} else {
/* else: unknown connection, create new */
connection = new Connection (packet);
connection = new Connection(packet);
getProcess(connection, args->device);
}
delete packet;
@@ -159,46 +158,50 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p
return true;
}
int process_udp (u_char * userdata, const dp_header * header, const u_char * m_packet) {
struct dpargs * args = (struct dpargs *) userdata;
struct udphdr * udp = (struct udphdr *) m_packet;
int process_udp(u_char *userdata, const dp_header *header,
const u_char *m_packet) {
struct dpargs *args = (struct dpargs *)userdata;
struct udphdr *udp = (struct udphdr *)m_packet;
curtime = header->ts;
Packet * packet;
switch (args->sa_family)
{
Packet *packet;
switch (args->sa_family) {
case AF_INET:
#ifdef __APPLE__
packet = new Packet (args->ip_src, ntohs(udp->uh_sport), args->ip_dst, ntohs(udp->uh_dport), header->len, header->ts);
#else
packet = new Packet (args->ip_src, ntohs(udp->source), args->ip_dst, ntohs(udp->dest), header->len, header->ts);
#endif
#ifdef __APPLE__
packet = new Packet(args->ip_src, ntohs(udp->uh_sport), args->ip_dst,
ntohs(udp->uh_dport), header->len, header->ts);
#else
packet = new Packet(args->ip_src, ntohs(udp->source), args->ip_dst,
ntohs(udp->dest), header->len, header->ts);
#endif
break;
case AF_INET6:
#ifdef __APPLE__
packet = new Packet (args->ip6_src, ntohs(udp->uh_sport), args->ip6_dst, ntohs(udp->uh_dport), header->len, header->ts);
#else
packet = new Packet (args->ip6_src, ntohs(udp->source), args->ip6_dst, ntohs(udp->dest), header->len, header->ts);
#endif
#ifdef __APPLE__
packet = new Packet(args->ip6_src, ntohs(udp->uh_sport), args->ip6_dst,
ntohs(udp->uh_dport), header->len, header->ts);
#else
packet = new Packet(args->ip6_src, ntohs(udp->source), args->ip6_dst,
ntohs(udp->dest), header->len, header->ts);
#endif
break;
default:
std::cerr << "Invalid address family for UDP packet: " << args->sa_family << std::endl;
std::cerr << "Invalid address family for UDP packet: " << args->sa_family
<< std::endl;
return true;
}
//if (DEBUG)
// if (DEBUG)
// std::cout << "Got packet from " << packet->gethashstring() << std::endl;
Connection * connection = findConnection(packet);
Connection *connection = findConnection(packet);
if (connection != NULL)
{
if (connection != NULL) {
/* add packet to the connection */
connection->add(packet);
} else {
/* else: unknown connection, create new */
connection = new Connection (packet);
connection = new Connection(packet);
getProcess(connection, args->device);
}
delete packet;
@@ -207,9 +210,10 @@ int process_udp (u_char * userdata, const dp_header * header, const u_char * m_p
return true;
}
int process_ip (u_char * userdata, const dp_header * /* header */, const u_char * m_packet) {
struct dpargs * args = (struct dpargs *) userdata;
struct ip * ip = (struct ip *) m_packet;
int process_ip(u_char *userdata, const dp_header * /* header */,
const u_char *m_packet) {
struct dpargs *args = (struct dpargs *)userdata;
struct ip *ip = (struct ip *)m_packet;
args->sa_family = AF_INET;
args->ip_src = ip->ip_src;
args->ip_dst = ip->ip_dst;
@@ -218,9 +222,10 @@ int process_ip (u_char * userdata, const dp_header * /* header */, const u_char
return false;
}
int process_ip6 (u_char * userdata, const dp_header * /* header */, const u_char * m_packet) {
struct dpargs * args = (struct dpargs *) userdata;
const struct ip6_hdr * ip6 = (struct ip6_hdr *) m_packet;
int process_ip6(u_char *userdata, const dp_header * /* header */,
const u_char *m_packet) {
struct dpargs *args = (struct dpargs *)userdata;
const struct ip6_hdr *ip6 = (struct ip6_hdr *)m_packet;
args->sa_family = AF_INET6;
args->ip6_src = ip6->ip6_src;
args->ip6_dst = ip6->ip6_dst;
@@ -231,11 +236,13 @@ int process_ip6 (u_char * userdata, const dp_header * /* header */, const u_char
class handle {
public:
handle (dp_handle * m_handle, const char * m_devicename = NULL,
handle * m_next = NULL) {
content = m_handle; next = m_next; devicename = m_devicename;
handle(dp_handle *m_handle, const char *m_devicename = NULL,
handle *m_next = NULL) {
content = m_handle;
next = m_next;
devicename = m_devicename;
}
dp_handle * content;
const char * devicename;
handle * next;
dp_handle *content;
const char *devicename;
handle *next;
};

View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __NETHOGS_H
#define __NETHOGS_H
@@ -30,9 +30,9 @@
#include <cassert>
#include <cstring>
#ifdef __APPLE__
#include <sys/malloc.h>
#include <sys/malloc.h>
#else
#include <malloc.h>
#include <malloc.h>
#endif
#include <iostream>
@@ -74,44 +74,42 @@
#define VIEWMODE_TOTAL_MB 3
#define VIEWMODE_COUNT 4
#define NORETURN __attribute__ ((__noreturn__))
#define NORETURN __attribute__((__noreturn__))
void forceExit(bool success, const char *msg, ...) NORETURN;
class local_addr {
public:
/* ipv4 constructor takes an in_addr_t */
local_addr (in_addr_t m_addr, local_addr * m_next = NULL)
{
local_addr(in_addr_t m_addr, local_addr *m_next = NULL) {
addr = m_addr;
next = m_next;
sa_family = AF_INET;
string = (char*) malloc (16);
inet_ntop (AF_INET, &m_addr, string, 15);
string = (char *)malloc(16);
inet_ntop(AF_INET, &m_addr, string, 15);
}
/* this constructor takes an char address[33] */
local_addr (struct in6_addr *m_addr, local_addr * m_next = NULL)
{
local_addr(struct in6_addr *m_addr, local_addr *m_next = NULL) {
addr6 = *m_addr;
next = m_next;
sa_family = AF_INET6;
string = (char*) malloc (64);
inet_ntop (AF_INET6, &m_addr, string, 63);
string = (char *)malloc(64);
inet_ntop(AF_INET6, &m_addr, string, 63);
}
bool contains (const in_addr_t & n_addr);
bool contains (const struct in6_addr & n_addr);
char * string;
local_addr * next;
private:
bool contains(const in_addr_t &n_addr);
bool contains(const struct in6_addr &n_addr);
char *string;
local_addr *next;
private:
in_addr_t addr;
struct in6_addr addr6;
short int sa_family;
};
void quit_cb (int i);
void quit_cb(int i);
const char* getVersion();
const char *getVersion();
#endif

View File

@@ -15,20 +15,20 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include "nethogs.h"
#include <iostream>
#include "packet.h"
#include <netinet/tcp.h>
#include <netinet/in.h>
#ifdef __APPLE__
#include <sys/malloc.h>
#include <sys/malloc.h>
#else
#include <malloc.h>
#include <malloc.h>
#endif
#include <cassert>
#include <net/if.h>
@@ -39,7 +39,7 @@
#include <ifaddrs.h>
// #include "inet6.c"
local_addr * local_addrs = NULL;
local_addr *local_addrs = NULL;
/*
* getLocal
@@ -48,31 +48,30 @@ local_addr * local_addrs = NULL;
* uses getifaddrs to get addresses of this device, and adds them to the
* local_addrs-list.
*/
bool getLocal (const char *device, bool tracemode)
{
bool getLocal(const char *device, bool tracemode) {
struct ifaddrs *ifaddr, *ifa;
if(getifaddrs(&ifaddr) == -1) {
if (getifaddrs(&ifaddr) == -1) {
return false;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if(ifa->ifa_addr == NULL)
if (ifa->ifa_addr == NULL)
continue;
if(strcmp(ifa->ifa_name, device) != 0)
if (strcmp(ifa->ifa_name, device) != 0)
continue;
int family = ifa->ifa_addr->sa_family;
if(family == AF_INET){
struct sockaddr_in *addr = (struct sockaddr_in*)ifa->ifa_addr;
if (family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
local_addrs = new local_addr(addr->sin_addr.s_addr, local_addrs);
if (tracemode || DEBUG) {
printf("Adding local address: %s\n", inet_ntoa(addr->sin_addr));
}
}else if(family == AF_INET6){
struct sockaddr_in6 *addr = (struct sockaddr_in6*)ifa->ifa_addr;
} else if (family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ifa->ifa_addr;
local_addrs = new local_addr(&addr->sin6_addr, local_addrs);
if (tracemode || DEBUG) {
char host[512];
@@ -109,12 +108,12 @@ struct tcp_hdr {
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */
u_int th_x2 : 4, /* (unused) */
th_off : 4; /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */
u_int th_off : 4, /* data offset */
th_x2 : 4; /* (unused) */
#endif
u_char th_flags;
#define TH_FIN 0x01
@@ -125,26 +124,36 @@ struct tcp_hdr {
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
#define TH_FLAGS (TH_FIN | TH_SYN | TH_RST | TH_ACK | TH_URG | TH_ECE | TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
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;
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, 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;
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;
}
@@ -157,22 +166,26 @@ direction invert(direction dir) {
return dir_unknown;
}
Packet * Packet::newInverted () {
Packet *Packet::newInverted() {
direction new_direction = invert(dir);
if (sa_family == AF_INET)
return new Packet (dip, dport, sip, sport, len, time, new_direction);
return new Packet(dip, dport, sip, sport, len, time, new_direction);
else
return new Packet (dip6, dport, sip6, sport, len, time, new_direction);
return new Packet(dip6, dport, sip6, sport, len, time, new_direction);
}
/* 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;
/* 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;
sip6 = old_packet.sip6;
dip6 = old_packet.dip6;
dip = old_packet.dip; dport = old_packet.dport;
len = old_packet.len; time = old_packet.time;
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;
@@ -181,19 +194,18 @@ Packet::Packet (const Packet &old_packet) {
dir = old_packet.dir;
}
bool sameinaddr(in_addr one, in_addr other)
{
bool sameinaddr(in_addr one, in_addr other) {
return one.s_addr == other.s_addr;
}
bool Packet::isOlderThan (timeval t) {
bool Packet::isOlderThan(timeval t) {
std::cout << "Comparing " << time.tv_sec << " <= " << t.tv_sec << std::endl;
return (time.tv_sec <= t.tv_sec);
}
bool Packet::Outgoing () {
bool Packet::Outgoing() {
/* must be initialised with getLocal("eth0:1");) */
assert (local_addrs != NULL);
assert(local_addrs != NULL);
switch (dir) {
case dir_outgoing:
@@ -218,10 +230,10 @@ bool Packet::Outgoing () {
if (!islocal) {
std::cerr << "Neither dip nor sip are local: ";
char addy [50];
inet_ntop (AF_INET6, &sip6, addy, 49);
char addy[50];
inet_ntop(AF_INET6, &sip6, addy, 49);
std::cerr << addy << std::endl;
inet_ntop (AF_INET6, &dip6, addy, 49);
inet_ntop(AF_INET6, &dip6, addy, 49);
std::cerr << addy << std::endl;
return false;
@@ -234,48 +246,48 @@ bool Packet::Outgoing () {
return false;
}
/* 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. */
/* the calling code should take care of deletion of the hash string */
char * Packet::gethashstring ()
{
if (hashstring != NULL)
{
char *Packet::gethashstring() {
if (hashstring != NULL) {
return hashstring;
}
hashstring = (char *) malloc (HASHKEYSIZE * sizeof(char));
hashstring = (char *)malloc(HASHKEYSIZE * sizeof(char));
char * local_string = (char *) malloc (50);
char * remote_string = (char *) malloc (50);
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);
} else {
inet_ntop(sa_family, &sip6, local_string, 49);
inet_ntop(sa_family, &dip6, remote_string, 49);
inet_ntop(sa_family, &dip6, remote_string, 49);
}
if (Outgoing()) {
snprintf(hashstring, 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(hashstring, 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);
//if (DEBUG)
// std::cout << "Returning newly created hash string: " << hashstring << std::endl;
free(local_string);
free(remote_string);
// if (DEBUG)
// std::cout << "Returning newly created hash string: " << hashstring <<
//std::endl;
return hashstring;
}
/* 2 packets match if they have the same
* source and destination ports and IP's. */
bool Packet::match (Packet * other)
{
return (sport == other->sport) && (dport == other->dport)
&& (sameinaddr(sip, other->sip)) && (sameinaddr(dip, other->dip));
bool Packet::match(Packet *other) {
return (sport == other->sport) && (dport == other->dport) &&
(sameinaddr(sip, other->sip)) && (sameinaddr(dip, other->dip));
}
bool Packet::matchSource (Packet * other)
{
bool Packet::matchSource(Packet *other) {
return (sport == other->sport) && (sameinaddr(sip, other->sip));
}

View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __PACKET_H
#define __PACKET_H
@@ -31,18 +31,13 @@
#include <arpa/inet.h>
#include "nethogs.h"
enum direction {
dir_unknown,
dir_incoming,
dir_outgoing
};
enum direction { dir_unknown, dir_incoming, dir_outgoing };
/* To initialise this module, call getLocal with the currently
* monitored device (e.g. "eth0:1") */
bool getLocal (const char *device, bool tracemode);
bool getLocal(const char *device, bool tracemode);
class Packet
{
class Packet {
public:
in6_addr sip6;
in6_addr dip6;
@@ -53,34 +48,37 @@ public:
u_int32_t len;
timeval time;
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);
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);
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 ();
Packet *newInverted();
bool isOlderThan(timeval t);
/* is this packet coming from the local host? */
bool Outgoing ();
bool Outgoing();
bool match (Packet * other);
bool matchSource (Packet * other);
bool match(Packet *other);
bool matchSource(Packet *other);
/* returns '1.2.3.4:5-1.2.3.4:6'-style string */
char * gethashstring();
char *gethashstring();
private:
direction dir;
short int sa_family;
char * hashstring;
char *hashstring;
};
#endif

View File

@@ -15,17 +15,17 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#include <iostream>
#include <strings.h>
#include <string>
#include <ncurses.h>
#ifndef __APPLE__
#include <asm/types.h>
#include <asm/types.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -47,8 +47,7 @@ extern timeval curtime;
* key contains source ip, source port, destination ip, destination
* port in format: '1.2.3.4:5-1.2.3.4:5'
*/
extern std::map <std::string, unsigned long> conninode;
extern std::map<std::string, unsigned long> conninode;
/* this file includes:
* - calls to inodeproc to get the pid that belongs to that inode
@@ -61,50 +60,36 @@ extern std::map <std::string, unsigned long> conninode;
* * unknown IP traffic
* We must take care these never get removed from the list.
*/
Process * unknowntcp;
Process * unknownudp;
Process * unknownip;
ProcList * processes;
Process *unknowntcp;
Process *unknownudp;
Process *unknownip;
ProcList *processes;
/* We're migrating to having several `unknown' processes that are added as
* normal processes, instead of hard-wired unknown processes.
* This mapping maps from unknown processes descriptions to processes */
std::map <std::string, Process*> unknownprocs;
std::map<std::string, Process *> unknownprocs;
float tomb(u_int32_t bytes) { return ((double)bytes) / 1024 / 1024; }
float tokb(u_int32_t bytes) { return ((double)bytes) / 1024; }
float tomb (u_int32_t bytes)
{
return ((double)bytes) / 1024 / 1024;
}
float tokb (u_int32_t bytes)
{
return ((double)bytes) / 1024;
float tokbps(u_int32_t bytes) { return (((double)bytes) / PERIOD) / 1024; }
void process_init() {
unknowntcp = new Process(0, "", "unknown TCP");
// unknownudp = new Process (0, "", "unknown UDP");
// unknownip = new Process (0, "", "unknown IP");
processes = new ProcList(unknowntcp, NULL);
// processes = new ProcList (unknownudp, processes);
// processes = new ProcList (unknownip, processes);
}
float tokbps (u_int32_t bytes)
{
return (((double)bytes) / PERIOD) / 1024;
}
void process_init ()
{
unknowntcp = new Process (0, "", "unknown TCP");
//unknownudp = new Process (0, "", "unknown UDP");
//unknownip = new Process (0, "", "unknown IP");
processes = new ProcList (unknowntcp, NULL);
//processes = new ProcList (unknownudp, processes);
//processes = new ProcList (unknownip, processes);
}
int Process::getLastPacket()
{
int lastpacket=0;
ConnList * curconn=connections;
while (curconn != NULL)
{
assert (curconn != NULL);
assert (curconn->getVal() != NULL);
int Process::getLastPacket() {
int lastpacket = 0;
ConnList *curconn = connections;
while (curconn != NULL) {
assert(curconn != NULL);
assert(curconn->getVal() != NULL);
if (curconn->getVal()->getLastPacket() > lastpacket)
lastpacket = curconn->getVal()->getLastPacket();
curconn = curconn->getNext();
@@ -113,21 +98,18 @@ int Process::getLastPacket()
}
/** Get the kb/s values for this process */
void Process::getkbps (float * recvd, float * sent)
{
void Process::getkbps(float *recvd, float *sent) {
u_int32_t sum_sent = 0, sum_recv = 0;
/* walk though all this process's connections, and sum
* them up */
ConnList * curconn = this->connections;
ConnList * previous = NULL;
while (curconn != NULL)
{
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT)
{
ConnList *curconn = this->connections;
ConnList *previous = NULL;
while (curconn != NULL) {
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) {
/* stalled connection, remove. */
ConnList * todelete = curconn;
Connection * conn_todelete = curconn->getVal();
ConnList *todelete = curconn;
Connection *conn_todelete = curconn->getVal();
curconn = curconn->getNext();
if (todelete == this->connections)
this->connections = curconn;
@@ -135,9 +117,7 @@ void Process::getkbps (float * recvd, float * sent)
previous->setNext(curconn);
delete (todelete);
delete (conn_todelete);
}
else
{
} else {
u_int32_t sent = 0, recv = 0;
curconn->getVal()->sumanddel(curtime, &recv, &sent);
sum_sent += sent;
@@ -151,25 +131,22 @@ void Process::getkbps (float * recvd, float * sent)
}
/** get total values for this process */
void Process::gettotal( u_int32_t * recvd, u_int32_t * sent)
{
void Process::gettotal(u_int32_t *recvd, u_int32_t *sent) {
u_int32_t sum_sent = 0, sum_recv = 0;
ConnList * curconn = this->connections;
while (curconn != NULL)
{
Connection * conn = curconn->getVal();
ConnList *curconn = this->connections;
while (curconn != NULL) {
Connection *conn = curconn->getVal();
sum_sent += conn->sumSent;
sum_recv += conn->sumRecv;
curconn = curconn->getNext();
}
//std::cout << "Sum sent: " << sum_sent << std::endl;
//std::cout << "Sum recv: " << sum_recv << std::endl;
// std::cout << "Sum sent: " << sum_sent << std::endl;
// std::cout << "Sum recv: " << sum_recv << std::endl;
*recvd = sum_recv;
*sent = sum_sent;
}
void Process::gettotalmb(float * recvd, float * sent)
{
void Process::gettotalmb(float *recvd, float *sent) {
u_int32_t sum_sent = 0, sum_recv = 0;
gettotal(&sum_recv, &sum_sent);
*recvd = tomb(sum_recv);
@@ -177,31 +154,26 @@ void Process::gettotalmb(float * recvd, float * sent)
}
/** get total values for this process */
void Process::gettotalkb(float * recvd, float * sent)
{
void Process::gettotalkb(float *recvd, float *sent) {
u_int32_t sum_sent = 0, sum_recv = 0;
gettotal(&sum_recv, &sum_sent);
*recvd = tokb(sum_recv);
*sent = tokb(sum_sent);
}
void Process::gettotalb(float * recvd, float * sent)
{
void Process::gettotalb(float *recvd, float *sent) {
u_int32_t sum_sent = 0, sum_recv = 0;
gettotal(&sum_recv, &sum_sent);
//std::cout << "Total sent: " << sum_sent << std::endl;
// std::cout << "Total sent: " << sum_sent << std::endl;
*sent = sum_sent;
*recvd = sum_recv;
}
Process * findProcess (struct prg_node * node)
{
ProcList * current = processes;
while (current != NULL)
{
Process * currentproc = current->getVal();
assert (currentproc != NULL);
Process *findProcess(struct prg_node *node) {
ProcList *current = processes;
while (current != NULL) {
Process *currentproc = current->getVal();
assert(currentproc != NULL);
if (node->pid == currentproc->pid)
return current->getVal();
@@ -213,19 +185,17 @@ Process * findProcess (struct prg_node * node)
/* finds process based on inode, if any */
/* should be done quickly after arrival of the packet,
* otherwise findPID will be outdated */
Process * findProcess (unsigned long inode)
{
struct prg_node * node = findPID(inode);
Process *findProcess(unsigned long inode) {
struct prg_node *node = findPID(inode);
if (node == NULL)
return NULL;
return findProcess (node);
return findProcess(node);
}
int ProcList::size ()
{
int i=1;
int ProcList::size() {
int i = 1;
if (next != NULL)
i += next->size();
@@ -233,11 +203,9 @@ int ProcList::size ()
return i;
}
void check_all_procs ()
{
ProcList * curproc = processes;
while (curproc != NULL)
{
void check_all_procs() {
ProcList *curproc = processes;
while (curproc != NULL) {
curproc->getVal()->check();
curproc = curproc->getNext();
}
@@ -248,27 +216,25 @@ void check_all_procs ()
* if the inode is not associated with any PID, return NULL
* if the process is not yet in the proclist, add it
*/
Process * getProcess (unsigned long inode, const char * devicename)
{
struct prg_node * node = findPID(inode);
Process *getProcess(unsigned long inode, const char *devicename) {
struct prg_node *node = findPID(inode);
if (node == NULL)
{
if (node == NULL) {
if (DEBUG || bughuntmode)
std::cout << "No PID information for inode " << inode << std::endl;
return NULL;
}
Process * proc = findProcess (node);
Process *proc = findProcess(node);
if (proc != NULL)
return proc;
Process * newproc = new Process (inode, devicename, node->name.c_str());
Process *newproc = new Process(inode, devicename, node->name.c_str());
newproc->pid = node->pid;
char procdir [100];
sprintf(procdir , "/proc/%d", node->pid);
char procdir[100];
sprintf(procdir, "/proc/%d", node->pid);
struct stat stats;
int retval = stat(procdir, &stats);
@@ -294,7 +260,7 @@ Process * getProcess (unsigned long inode, const char * devicename)
if (!ROBUST)
assert(false);
}*/
processes = new ProcList (newproc, processes);
processes = new ProcList(newproc, processes);
return newproc;
}
@@ -305,55 +271,52 @@ Process * getProcess (unsigned long inode, const char * devicename)
* is made. If no process can be found even then, it's added to the
* 'unknown' process.
*/
Process * getProcess (Connection * connection, const char * devicename)
{
Process *getProcess(Connection *connection, const char *devicename) {
unsigned long inode = conninode[connection->refpacket->gethashstring()];
if (inode == 0)
{
if (inode == 0) {
// no? refresh and check conn/inode table
if (bughuntmode)
{
std::cout << "? new connection not in connection-to-inode table before refresh.\n";
if (bughuntmode) {
std::cout << "? new connection not in connection-to-inode table before "
"refresh.\n";
}
// refresh the inode->pid table first. Presumably processing the renewed connection->inode table
// is slow, making this worthwhile.
// We take the fact for granted that we might already know the inode->pid (unlikely anyway if we
// haven't seen the connection->inode yet though).
#ifndef __APPLE__
// refresh the inode->pid table first. Presumably processing the renewed
// connection->inode table
// is slow, making this worthwhile.
// We take the fact for granted that we might already know the inode->pid
// (unlikely anyway if we
// haven't seen the connection->inode yet though).
#ifndef __APPLE__
reread_mapping();
#endif
#endif
refreshconninode();
inode = conninode[connection->refpacket->gethashstring()];
if (bughuntmode)
{
if (inode == 0)
{
if (bughuntmode) {
if (inode == 0) {
std::cout << ":( inode for connection not found after refresh.\n";
}
else
{
} else {
std::cout << ":) inode for connection found after refresh.\n";
}
}
#if REVERSEHACK
if (inode == 0)
{
if (inode == 0) {
/* 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. */
Packet * reversepacket = connection->refpacket->newInverted();
Packet *reversepacket = connection->refpacket->newInverted();
inode = conninode[reversepacket->gethashstring()];
if (inode == 0)
{
if (inode == 0) {
delete reversepacket;
if (bughuntmode || DEBUG)
std::cout << "LOC: " << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n";
unknowntcp->connections = new ConnList (connection, unknowntcp->connections);
std::cout << "LOC: " << connection->refpacket->gethashstring()
<< " STILL not in connection-to-inode table - adding to "
"the unknown process\n";
unknowntcp->connections =
new ConnList(connection, unknowntcp->connections);
return unknowntcp;
}
@@ -361,32 +324,29 @@ Process * getProcess (Connection * connection, const char * devicename)
connection->refpacket = reversepacket;
}
#endif
}
else if (bughuntmode)
{
std::cout << ";) new connection in connection-to-inode table before refresh.\n";
} else if (bughuntmode) {
std::cout
<< ";) new connection in connection-to-inode table before refresh.\n";
}
if (bughuntmode)
{
if (bughuntmode) {
std::cout << " inode # " << inode << std::endl;
}
Process * proc = NULL;
Process *proc = NULL;
if (inode != 0)
proc = getProcess(inode, devicename);
if (proc == NULL) {
proc = new Process (inode, "", connection->refpacket->gethashstring());
processes = new ProcList (proc, processes);
proc = new Process(inode, "", connection->refpacket->gethashstring());
processes = new ProcList(proc, processes);
}
proc->connections = new ConnList (connection, proc->connections);
proc->connections = new ConnList(connection, proc->connections);
return proc;
}
void procclean ()
{
//delete conninode;
void procclean() {
// delete conninode;
prg_cache_clear();
}

128
process.h
View File

@@ -15,11 +15,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
*USA.
*
*/
#ifndef __PROCESS_H
#define __PROCESS_H
@@ -30,46 +30,37 @@
extern bool tracemode;
extern bool bughuntmode;
void check_all_procs ();
void check_all_procs();
class ConnList
{
class ConnList {
public:
ConnList (Connection * m_val, ConnList * m_next)
{
assert (m_val != NULL);
val = m_val; next = m_next;
ConnList(Connection *m_val, ConnList *m_next) {
assert(m_val != NULL);
val = m_val;
next = m_next;
}
~ConnList ()
{
~ConnList() {
/* does not delete its value, to allow a connection to
* remove itself from the global connlist in its destructor */
}
Connection * getVal ()
{
return val;
}
void setNext (ConnList * m_next)
{
next = m_next;
}
ConnList * getNext ()
{
return next;
}
Connection *getVal() { return val; }
void setNext(ConnList *m_next) { next = m_next; }
ConnList *getNext() { return next; }
private:
Connection * val;
ConnList * next;
Connection *val;
ConnList *next;
};
class Process
{
class Process {
public:
/* the process makes a copy of the name. the device name needs to be stable. */
Process (const unsigned long m_inode, const char * m_devicename, const char * m_name = NULL)
: inode (m_inode)
{
//std::cout << "ARN: Process created with dev " << m_devicename << std::endl;
/* the process makes a copy of the name. the device name needs to be stable.
*/
Process(const unsigned long m_inode, const char *m_devicename,
const char *m_name = NULL)
: inode(m_inode) {
// std::cout << "ARN: Process created with dev " << m_devicename <<
// std::endl;
if (DEBUG)
std::cout << "PROC: Process created at " << this << std::endl;
@@ -83,70 +74,59 @@ public:
pid = 0;
uid = 0;
}
void check () {
assert (pid >= 0);
}
void check() { assert(pid >= 0); }
~Process ()
{
free (name);
~Process() {
free(name);
if (DEBUG)
std::cout << "PROC: Process deleted at " << this << std::endl;
}
int getLastPacket ();
int getLastPacket();
void gettotal( u_int32_t * recvd, u_int32_t * sent);
void getkbps (float * recvd, float * sent);
void gettotalmb(float * recvd, float * sent);
void gettotalkb(float * recvd, float * sent);
void gettotalb (float * recvd, float * sent);
void gettotal(u_int32_t *recvd, u_int32_t *sent);
void getkbps(float *recvd, float *sent);
void gettotalmb(float *recvd, float *sent);
void gettotalkb(float *recvd, float *sent);
void gettotalb(float *recvd, float *sent);
char * name;
const char * devicename;
char *name;
const char *devicename;
int pid;
ConnList * connections;
uid_t getUid()
{
return uid;
}
ConnList *connections;
uid_t getUid() { return uid; }
void setUid(uid_t m_uid)
{
uid = m_uid;
}
void setUid(uid_t m_uid) { uid = m_uid; }
unsigned long getInode() { return inode; }
unsigned long getInode()
{
return inode;
}
private:
const unsigned long inode;
uid_t uid;
};
class ProcList
{
class ProcList {
public:
ProcList (Process * m_val, ProcList * m_next)
{
assert (m_val != NULL);
val = m_val; next = m_next;
ProcList(Process *m_val, ProcList *m_next) {
assert(m_val != NULL);
val = m_val;
next = m_next;
}
int size ();
Process * getVal () { return val; }
ProcList * getNext () { return next; }
ProcList * next;
int size();
Process *getVal() { return val; }
ProcList *getNext() { return next; }
ProcList *next;
private:
Process * val;
Process *val;
};
Process * getProcess (Connection * connection, const char * devicename = NULL);
Process *getProcess(Connection *connection, const char *devicename = NULL);
void process_init ();
void process_init();
void refreshconninode ();
void refreshconninode();
void procclean ();
void procclean();
#endif