added library build mode

This commit is contained in:
Mohamed Boussaffa
2016-03-03 04:07:26 +08:00
parent c0b69e51af
commit 53234af7ab
9 changed files with 332 additions and 30 deletions

2
.gitignore vendored
View File

@@ -3,3 +3,5 @@ decpcap_test
TAGS
*.o
*~
nethogs.project

92
MakeLib.mk Normal file
View File

@@ -0,0 +1,92 @@
VERSION := 0
SUBVERSION := 8
MINORVERSION := 2-SNAPSHOT
#prefix := /usr
prefix := /usr/local
sbin := $(prefix)/lib
all: libnethogs
# nethogs_testsum
LDFLAGS+= -shared
ODIR_BASE := objs/lib
ifeq ($(DEBUG),1)
$(info debug mode)
ODIR:=$(ODIR_BASE)/debug
CFLAGS?=-Wall -Wextra -O0 -g -fPIC
CXXFLAGS?=--std=c++11 --std=c++11 -Wall -Wextra -O0 -g -fPIC
else
$(info release mode)
ODIR:=$(ODIR_BASE)/release
CFLAGS?=-Wall -Wextra -O3 -fPIC
CXXFLAGS?=---std=c++11 Wall -Wextra -O3 -fPIC
endif
OBJ_NAMES= libnethogs.o packet.o connection.o process.o refresh.o decpcap.o inode2prog.o conninode.o devices.o
OBJS=$(addprefix $(ODIR)/,$(OBJ_NAMES))
#$(info $(OBJS))
.PHONY: tgz
.PHONY: uninstall
install: libnethogs
install -d -m 755 $(DESTDIR)$(sbin)
install -m 755 libnethogs $(DESTDIR)$(sbin)
@echo
@echo "Installed libnethogs to $(DESTDIR)$(sbin)"
@echo
@echo "You might have to add this directory to your PATH and/or refresh your shells' path cache with a command like 'hash -r'."
uninstall:
rm $(DESTDIR)$(sbin)/libnethogs
libnethogs: $(OBJS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o libnethogs.so -lpcap
#-lefence
$(ODIR)/refresh.o: refresh.cpp refresh.h nethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c refresh.cpp
$(ODIR)/process.o: process.cpp process.h nethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c process.cpp
$(ODIR)/packet.o: packet.cpp packet.h nethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c packet.cpp
$(ODIR)/connection.o: connection.cpp connection.h nethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c connection.cpp
$(ODIR)/decpcap.o: decpcap.c decpcap.h
@mkdir -p $(ODIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c decpcap.c
$(ODIR)/inode2prog.o: inode2prog.cpp inode2prog.h nethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c inode2prog.cpp
$(ODIR)/conninode.o: conninode.cpp nethogs.h conninode.h
@mkdir -p $(ODIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c conninode.cpp
$(ODIR)/devices.o: devices.cpp devices.h
@mkdir -p $(ODIR)
$(CXX) $(CXXFLAGS) -o $@ -c devices.cpp
$(ODIR)/libnethogs.o: libnethogs.cpp libnethogs.h
@mkdir -p $(ODIR)
$(CXX) $(CXXFLAGS) -o $@ -c libnethogs.cpp -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\"
.PHONY: clean
clean:
rm -f $(OBJS)
rm -f libnethogs

185
libnethogs.cpp Normal file
View File

@@ -0,0 +1,185 @@
#include "libnethogs.h"
#include "nethogs.cpp"
#include <pthread.h>
#include <iostream>
#include <mutex>
#include <atomic>
#include <memory>
#include <thread>
//////////////////////////////
extern ProcList * processes;
extern Process * unknowntcp;
extern Process * unknownudp;
extern Process * unknownip;
//////////////////////////////
static std::shared_ptr<std::thread> monitor_thread_ptr;
static std::atomic_bool monitor_thread_run_flag(false);
bool NethogsMonitor::_trace = false;
bool NethogsMonitor::_promisc = false;
void NethogsMonitor::threadProc()
{
device * devices = get_default_devices();
if ( devices == NULL )
{
std::cerr << "Not devices to monitor" << std::endl;
return;
}
handle * handles = NULL;
device * current_dev = devices;
while (current_dev != NULL)
{
if( !getLocal(current_dev->name, _trace) )
{
std::cerr << "getifaddrs failed while establishing local IP." << std::endl;
continue;
}
char errbuf[PCAP_ERRBUF_SIZE];
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
*
* update: version 0.7.2, which is in debian stable now, should be ok
* also.
*/
if (dp_setnonblock (newhandle, 1, errbuf) == -1)
{
fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
}
handles = new handle (newhandle, current_dev->name, handles);
}
else
{
fprintf(stderr, "Error opening handler for device %s\n", current_dev->name);
}
current_dev = current_dev->next;
}
signal (SIGALRM, &alarm_cb);
alarm (refreshdelay);
fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
// Main loop:
//
// Walks though the 'handles' list, which contains handles opened in non-blocking mode.
// This causes the CPU utilisation to go up to 100%. This is tricky:
while (monitor_thread_run_flag)
{
bool packets_read = false;
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)
{
std::cerr << "Error dispatching: " << retval << std::endl;
}
else if (retval != 0)
{
packets_read = true;
}
current_handle = current_handle->next;
}
if (needrefresh)
{
needrefresh = false;
}
// If no packets were read at all this iteration, pause to prevent 100%
// CPU utilisation;
if (!packets_read)
{
usleep(100);
}
}
}
void NethogsMonitor::handleUpdate()
{
refreshconninode();
refreshcount++;
ProcList * curproc = processes;
ProcList * previousproc = NULL;
int nproc = processes->size();
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());
/* 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)
{
previousproc->next = curproc->next;
curproc = curproc->next;
} else {
processes = curproc->getNext();
curproc = processes;
}
delete todelete;
delete p_todelete;
nproc--;
//continue;
}
else
{
//uid_t uid = curproc->getVal()->getUid();
previousproc = curproc;
curproc = curproc->next;
}
}
}
void NethogsMonitor::start()
{
bool expected = false;
if( monitor_thread_run_flag.compare_exchange_strong(expected, true) )
{
monitor_thread_ptr = std::make_shared<std::thread>(&threadProc);
}
}
void NethogsMonitor::stop()
{
bool expected = true;
if( monitor_thread_run_flag.compare_exchange_strong(expected, false) )
{
monitor_thread_ptr->join();
}
}

18
libnethogs.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef NETHOGSMINITOR_H
#define NETHOGSMINITOR_H
class NethogsMonitor
{
NethogsMonitor();
public:
static void start();
static void stop();
private:
static void threadProc();
static void handleUpdate();
static bool _trace;
static bool _promisc;
};
#endif // NETHOGSMINITOR_H

BIN
libnethogs.so Executable file

Binary file not shown.

View File

@@ -30,6 +30,32 @@ static void help(bool iserror)
output << " m: switch between total (KB, B, MB) and KB/s mode\n";
}
void quit_cb (int /* i */)
{
procclean();
if ((!tracemode) && (!DEBUG))
exit_ui();
exit(0);
}
void forceExit(bool success, const char *msg, ...)
{
if ((!tracemode)&&(!DEBUG)){
exit_ui();
}
va_list argp;
va_start(argp, msg);
vfprintf(stderr, msg, argp);
va_end(argp);
std::cerr << std::endl;
if (success)
exit(EXIT_SUCCESS);
else
exit(EXIT_FAILURE);
}
int main (int argc, char** argv)
{
process_init();
@@ -111,7 +137,11 @@ int main (int argc, char** argv)
handle * handles = NULL;
device * current_dev = devices;
while (current_dev != NULL) {
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)

View File

@@ -227,32 +227,6 @@ int process_ip6 (u_char * userdata, const dp_header * /* header */, const u_char
return false;
}
void quit_cb (int /* i */)
{
procclean();
if ((!tracemode) && (!DEBUG))
exit_ui();
exit(0);
}
void forceExit(bool success, const char *msg, ...)
{
if ((!tracemode)&&(!DEBUG)){
exit_ui();
}
va_list argp;
va_start(argp, msg);
vfprintf(stderr, msg, argp);
va_end(argp);
std::cerr << std::endl;
if (success)
exit(EXIT_SUCCESS);
else
exit(EXIT_FAILURE);
}
class handle {
public:
handle (dp_handle * m_handle, const char * m_devicename = NULL,

View File

@@ -48,11 +48,11 @@ local_addr * local_addrs = NULL;
* uses getifaddrs to get addresses of this device, and adds them to the
* local_addrs-list.
*/
void getLocal (const char *device, bool tracemode)
bool getLocal (const char *device, bool tracemode)
{
struct ifaddrs *ifaddr, *ifa;
if(getifaddrs(&ifaddr) == -1) {
forceExit(false, "getifaddrs failed while establishing local IP.");
return false;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
@@ -81,6 +81,7 @@ void getLocal (const char *device, bool tracemode)
}
}
}
return true;
}
typedef u_int32_t tcp_seq;

View File

@@ -39,7 +39,7 @@ enum direction {
/* To initialise this module, call getLocal with the currently
* monitored device (e.g. "eth0:1") */
void getLocal (const char *device, bool tracemode);
bool getLocal (const char *device, bool tracemode);
class Packet
{