From a05654cf045d0e8ecc104b019145f627ad6ce4eb Mon Sep 17 00:00:00 2001 From: Maxim Mamontov Date: Thu, 5 Jun 2014 08:55:35 +0300 Subject: [PATCH] Initial adding of PCap capturer. --- .../stargazer/plugins/capture/pcap/Makefile | 13 + .../plugins/capture/pcap/pcap_cap.cpp | 236 ++++++++++++++++++ .../stargazer/plugins/capture/pcap/pcap_cap.h | 90 +++++++ 3 files changed, 339 insertions(+) create mode 100644 projects/stargazer/plugins/capture/pcap/Makefile create mode 100644 projects/stargazer/plugins/capture/pcap/pcap_cap.cpp create mode 100644 projects/stargazer/plugins/capture/pcap/pcap_cap.h diff --git a/projects/stargazer/plugins/capture/pcap/Makefile b/projects/stargazer/plugins/capture/pcap/Makefile new file mode 100644 index 00000000..3eff306f --- /dev/null +++ b/projects/stargazer/plugins/capture/pcap/Makefile @@ -0,0 +1,13 @@ +include ../../../../../Makefile.conf + +PROG = mod_cap_pcap.so + +SRCS = ./pcap_cap.cpp + +LIBS += -lpcap $(LIB_THREAD) + +STGLIBS = common \ + logger + +include ../../Makefile.in + diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp new file mode 100644 index 00000000..7fa7fb68 --- /dev/null +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp @@ -0,0 +1,236 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +* Author : Maxim Mamontov +*/ + +#include "pcap_cap.h" + +#include "stg/traffcounter.h" +#include "stg/plugin_creator.h" +#include "stg/common.h" +#include "stg/raw_ip_packet.h" + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +namespace +{ +PLUGIN_CREATOR pcc; + +const size_t SNAP_LEN 1518; +} + +extern "C" PLUGIN * GetPlugin(); +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +PLUGIN * GetPlugin() +{ +return pcc.GetPlugin(); +} +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +std::string PCAP_CAP::GetVersion() const +{ +return "pcap_cap v.1.0"; +} +//----------------------------------------------------------------------------- +PCAP_CAP::PCAP_CAP() + : errorStr(), + thread(), + nonstop(false), + isRunning(false), + handle(NULL), + traffCnt(NULL), + logger(GetPluginLogger(GetStgLogger(), "cap_pcap")) +{ +} +//----------------------------------------------------------------------------- +int PCAP_CAP::Start() +{ +if (isRunning) + return 0; + +DEV_MAP::const_iterator it(devices.begin()); +while (it != devices.end()) + { + bpf_u_int32 mask; + bpf_u_int32 net; + char errbuf[PCAP_ERRBUF_SIZE]; + + /* get network number and mask associated with capture device */ + if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1) + { + errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf; + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + /* open capture device */ + it->handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); + if (it->handle == NULL) + { + errorStr = "Couldn't open device " + it->device + ": " + errbuf; + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + if (pcap_setnonblock(it->handle, true, errbuf) == -1) + { + errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf; + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + /* make sure we're capturing on an Ethernet device [2] */ + if (pcap_datalink(it->handle) != DLT_EN10MB) + { + errorStr = it->device + " is not an Ethernet"; + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + /* compile the filter expression */ + if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1) + { + errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle); + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + /* apply the compiled filter */ + if (pcap_setfilter(it->handle, &it->filter) == -1) + { + errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle); + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + + it->fd = pcap_get_selectable_fd(it->handle); + if (it->fd == -1) + { + { + errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle); + logger(errorStr); + printfd(__FILE__, "%s\n", errorStr.c_str()); + return -1; + } + } + } + +nonstop = true; + +if (pthread_create(&thread, NULL, Run, this)) + { + errorStr = "Cannot create thread."; + logger("Cannot create thread."); + printfd(__FILE__, "Cannot create thread\n"); + return -1; + } + +return 0; +} +//----------------------------------------------------------------------------- +int PCAP_CAP::Stop() +{ +if (!isRunning) + return 0; + +nonstop = false; + +//5 seconds to thread stops itself +for (int i = 0; i < 25 && isRunning; i++) + { + struct timespec ts = {0, 200000000}; + nanosleep(&ts, NULL); + } +//after 5 seconds waiting thread still running. now killing it +if (isRunning) + { + if (pthread_kill(thread, SIGUSR1)) + { + errorStr = "Cannot kill thread."; + logger("Cannot send signal to thread."); + return -1; + } + for (int i = 0; i < 25 && isRunning; ++i) + { + struct timespec ts = {0, 200000000}; + nanosleep(&ts, NULL); + } + if (isRunning) + { + errorStr = "PCAP_CAP not stopped."; + logger("Cannot stop thread."); + printfd(__FILE__, "Cannot stop thread\n"); + return -1; + } + else + { + pthread_join(thread, NULL); + } + } + +return 0; +} +//----------------------------------------------------------------------------- +void * PCAP_CAP::Run(void * d) +{ +sigset_t signalSet; +sigfillset(&signalSet); +pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + +PCAP_CAP * dc = static_cast(d); +dc->isRunning = true; + +struct ETH_IP +{ +uint16_t ethHdr[8]; +RAW_PACKET rp; +char padding[4]; +char padding1[8]; +}; + +char ethip[sizeof(ETH_IP)]; + +memset(ðip, 0, sizeof(ETH_IP)); + +ETH_IP * ethIP = static_cast(static_cast(ðip)); +ethIP->rp.dataLen = -1; + +char * iface = NULL; + +while (dc->nonstop) + { + + if (ethIP->ethHdr[7] != 0x8) + continue; + + dc->traffCnt->Process(ethIP->rp); + } + +dc->isRunning = false; +return NULL; +} diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.h b/projects/stargazer/plugins/capture/pcap/pcap_cap.h new file mode 100644 index 00000000..b39f736a --- /dev/null +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.h @@ -0,0 +1,90 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +* Author : Maxim Mamontov +*/ + +#ifndef PCAP_CAP_H +#define PCAP_CAP_H + +#include "stg/plugin.h" +#include "stg/module_settings.h" +#include "stg/logger.h" + +#include +#include + +#include +#include + +class USERS; +class TARIFFS; +class ADMINS; +class TRAFFCOUNTER; +class SETTINGS; + +class TRAFFCOUNTER; + +struct DEV +{ + std::string device; + std::string filterExpression; + pcap_t * handle; + struct bpf_program filter; + int fd; +}; + +typedef std::vector DEV_MAP; + +class PCAP_CAP : public PLUGIN { +public: + PCAP_CAP(); + virtual ~PCAP_CAP() {} + + void SetTraffcounter(TRAFFCOUNTER * tc) { traffCnt = tc; } + + int Start(); + int Stop(); + int Reload() { return 0; } + bool IsRunning() { return isRunning; } + + int ParseSettings() { return 0; } + const std::string & GetStrError() const { return errorStr; } + std::string GetVersion() const; + uint16_t GetStartPosition() const { return 40; } + uint16_t GetStopPosition() const { return 40; } + +private: + PCAP_CAP(const PCAP_CAP & rvalue); + PCAP_CAP & operator=(const PCAP_CAP & rvalue); + + static void * Run(void *); + + mutable std::string errorStr; + + pthread_t thread; + bool nonstop; + bool isRunning; + DEV_MAP devices; + + TRAFFCOUNTER * traffCnt; + + PLUGIN_LOGGER logger; +}; +//----------------------------------------------------------------------------- + +#endif -- 2.44.2