From f5776429a3145d59f5b131c25d0f9428ae947f4e Mon Sep 17 00:00:00 2001 From: Maxim Mamontov Date: Thu, 5 Jun 2014 23:31:26 +0300 Subject: [PATCH 1/1] Fixed issues in cap_pcap. --- projects/stargazer/build | 19 +++ .../plugins/capture/pcap/pcap_cap.cpp | 124 +++++++++++++----- .../stargazer/plugins/capture/pcap/pcap_cap.h | 14 +- stglibs/logger.lib/include/stg/logger.h | 3 + stglibs/logger.lib/logger.cpp | 57 ++++---- 5 files changed, 162 insertions(+), 55 deletions(-) diff --git a/projects/stargazer/build b/projects/stargazer/build index ec14eaad..770401bb 100755 --- a/projects/stargazer/build +++ b/projects/stargazer/build @@ -342,6 +342,18 @@ else fi fi +printf "Checking for -lpcap... " +$CC $CFLAGS $LDFLAGS build_check.c -lpcap -o fake > /dev/null 2> /dev/null +if [ $? != 0 ] +then + CHECK_PCAP=no + printf "no\n" +else + CHECK_PCAP=yes + printf "yes\n" +fi +rm -f fake + if [ "$OS" = "linux" ] then printf "Checking for linux/netfilter_ipv4/ip_queue.h... " @@ -397,6 +409,12 @@ then configuration/rpcconfig" fi +if [ "$CHECK_PCAP" = "yes" ] +then + PLUGINS="$PLUGINS + capture/pcap" +fi + printf "OS=$OS\n" > $CONFFILE printf "STG_TIME=yes\n" >> $CONFFILE printf "DEBUG=$DEBUG\n" >> $CONFFILE @@ -412,6 +430,7 @@ printf "CHECK_FBCLIENT=$CHECK_FBCLIENT\n" >> $CONFFILE printf "CHECK_MYSQLCLIENT=$CHECK_MYSQLCLIENT\n" >> $CONFFILE printf "CHECK_PQ=$CHECK_PQ\n" >> $CONFFILE printf "CHECK_XMLRPC=$CHECK_XMLRPC\n" >> $CONFFILE +printf "CHECK_PCAP=$CHECK_PCAP\n" >> $CONFFILE printf "DEFS=$DEFS\n" >> $CONFFILE printf "STG_LIBS=" >> $CONFFILE for lib in $STG_LIBS diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp index 7fa7fb68..57a5a878 100644 --- a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp @@ -25,6 +25,8 @@ #include "stg/common.h" #include "stg/raw_ip_packet.h" +#include + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -32,7 +34,16 @@ namespace { PLUGIN_CREATOR pcc; -const size_t SNAP_LEN 1518; +const size_t SNAP_LEN = 1518; +const size_t ETHER_ADDR_LEN = 6; + +struct ETH +{ +u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */ +u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */ +u_short ether_type; /* IP? ARP? RARP? etc */ +}; + } extern "C" PLUGIN * GetPlugin(); @@ -56,18 +67,49 @@ PCAP_CAP::PCAP_CAP() thread(), nonstop(false), isRunning(false), - handle(NULL), traffCnt(NULL), logger(GetPluginLogger(GetStgLogger(), "cap_pcap")) { } //----------------------------------------------------------------------------- +int PCAP_CAP::ParseSettings() +{ +devices.erase(devices.begin(), devices.end()); + +if (settings.moduleParams.empty()) + { + devices.push_back(DEV()); + logger("Defaulting to pseudo-device 'all'."); + return 0; + } + +for (size_t i = 0; i < settings.moduleParams.size(); i++) + if (settings.moduleParams[i].param == "interfaces") + for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++) + devices.push_back(DEV(settings.moduleParams[i].value[j])); + +for (size_t i = 0; i < settings.moduleParams.size(); i++) + if (settings.moduleParams[i].param == "filters") + for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++) + if (j < devices.size()) + devices[j].filterExpression = settings.moduleParams[i].value[j]; + +if (devices.empty()) + { + devices.push_back(DEV()); + logger("Defaulting to pseudo-device 'all'."); + return 0; + } + +return 0; +} +//----------------------------------------------------------------------------- int PCAP_CAP::Start() { if (isRunning) return 0; -DEV_MAP::const_iterator it(devices.begin()); +DEV_MAP::iterator it(devices.begin()); while (it != devices.end()) { bpf_u_int32 mask; @@ -84,7 +126,7 @@ while (it != devices.end()) } /* open capture device */ - it->handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); + it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf); if (it->handle == NULL) { errorStr = "Couldn't open device " + it->device + ": " + errbuf; @@ -130,14 +172,14 @@ while (it != devices.end()) 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; } - } + + ++it; } nonstop = true; @@ -187,10 +229,14 @@ if (isRunning) printfd(__FILE__, "Cannot stop thread\n"); return -1; } - else - { - pthread_join(thread, NULL); - } + } + +pthread_join(thread, NULL); + +for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it) + { + pcap_freecode(&it->filter); + pcap_close(it->handle); } return 0; @@ -205,32 +251,50 @@ 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; +fd_set fds; +FD_ZERO(&fds); +int maxFd = 0; +for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it) + { + FD_SET(it->fd, &fds); + maxFd = std::max(maxFd, it->fd); + } while (dc->nonstop) { + fd_set rfds = fds; + struct timeval tv = {0, 500000}; - if (ethIP->ethHdr[7] != 0x8) - continue; - - dc->traffCnt->Process(ethIP->rp); + if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0) + dc->TryRead(rfds); } dc->isRunning = false; return NULL; } + +void PCAP_CAP::TryRead(const fd_set & set) +{ +for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it) + if (FD_ISSET(it->fd, &set)) + TryReadDev(*it); +} + +void PCAP_CAP::TryReadDev(const DEV & dev) +{ +struct pcap_pkthdr * header; +const u_char * packet; +if (pcap_next_ex(dev.handle, &header, &packet) == -1) + { + printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle)); + return; + } + +const ETH * eth = reinterpret_cast(packet); +if (eth->ether_type != 0x8) + return; + +RAW_PACKET ip; +memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket)); +traffCnt->Process(ip); +} diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.h b/projects/stargazer/plugins/capture/pcap/pcap_cap.h index b39f736a..bf050c17 100644 --- a/projects/stargazer/plugins/capture/pcap/pcap_cap.h +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.h @@ -30,6 +30,7 @@ #include #include +#include class USERS; class TARIFFS; @@ -41,6 +42,11 @@ class TRAFFCOUNTER; struct DEV { + DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {} + DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {} + DEV(const std::string & d, const std::string & f) + : device(d), filterExpression(f), handle(NULL), fd(-1) {} + std::string device; std::string filterExpression; pcap_t * handle; @@ -62,7 +68,9 @@ public: int Reload() { return 0; } bool IsRunning() { return isRunning; } - int ParseSettings() { return 0; } + void SetSettings(const MODULE_SETTINGS & s) { settings = s; } + int ParseSettings(); + const std::string & GetStrError() const { return errorStr; } std::string GetVersion() const; uint16_t GetStartPosition() const { return 40; } @@ -72,6 +80,9 @@ private: PCAP_CAP(const PCAP_CAP & rvalue); PCAP_CAP & operator=(const PCAP_CAP & rvalue); + void TryRead(const fd_set & set); + void TryReadDev(const DEV & dev); + static void * Run(void *); mutable std::string errorStr; @@ -79,6 +90,7 @@ private: pthread_t thread; bool nonstop; bool isRunning; + MODULE_SETTINGS settings; DEV_MAP devices; TRAFFCOUNTER * traffCnt; diff --git a/stglibs/logger.lib/include/stg/logger.h b/stglibs/logger.lib/include/stg/logger.h index c55801ac..115d1fb3 100644 --- a/stglibs/logger.lib/include/stg/logger.h +++ b/stglibs/logger.lib/include/stg/logger.h @@ -30,6 +30,7 @@ public: ~STG_LOGGER(); void SetLogFileName(const std::string & fn); void operator()(const char * fmt, ...) const; + void operator()(const std::string & line) const { LogString(line.c_str()); } private: STG_LOGGER(); @@ -37,6 +38,7 @@ private: STG_LOGGER & operator=(const STG_LOGGER & rvalue); const char * LogDate(time_t t) const; + void LogString(const char * str) const; std::string fileName; mutable pthread_mutex_t mutex; @@ -49,6 +51,7 @@ friend PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER & logger, const std::strin public: PLUGIN_LOGGER(const PLUGIN_LOGGER & rhs); void operator()(const char * fmt, ...) const; + void operator()(const std::string & line) const; private: PLUGIN_LOGGER(const STG_LOGGER & logger, const std::string & pn); diff --git a/stglibs/logger.lib/logger.cpp b/stglibs/logger.lib/logger.cpp index 14c09591..6289618e 100644 --- a/stglibs/logger.lib/logger.cpp +++ b/stglibs/logger.lib/logger.cpp @@ -43,10 +43,33 @@ va_start(vl, fmt); vsnprintf(buff, sizeof(buff), fmt, vl); va_end(vl); -FILE * f; +LogString(buff); +} +//----------------------------------------------------------------------------- +const char * STG_LOGGER::LogDate(time_t t) const +{ +static char s[32]; +if (t == 0) + t = time(NULL); + +struct tm * tt = localtime(&t); + +snprintf(s, 32, "%d-%s%d-%s%d %s%d:%s%d:%s%d", + tt->tm_year + 1900, + tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1, + tt->tm_mday < 10 ? "0" : "", tt->tm_mday, + tt->tm_hour < 10 ? "0" : "", tt->tm_hour, + tt->tm_min < 10 ? "0" : "", tt->tm_min, + tt->tm_sec < 10 ? "0" : "", tt->tm_sec); + +return s; +} +//----------------------------------------------------------------------------- +void STG_LOGGER::LogString(const char * str) const +{ if (!fileName.empty()) { - f = fopen(fileName.c_str(), "at"); + FILE * f = fopen(fileName.c_str(), "at"); if (f) { #ifdef STG_TIME @@ -55,44 +78,25 @@ if (!fileName.empty()) fprintf(f, "%s", LogDate(time(NULL))); #endif fprintf(f, " -- "); - fprintf(f, "%s", buff); + fprintf(f, "%s", str); fprintf(f, "\n"); fclose(f); } else { openlog("stg", LOG_NDELAY, LOG_USER); - syslog(LOG_CRIT, "%s", buff); + syslog(LOG_CRIT, "%s", str); closelog(); } } else { openlog("stg", LOG_NDELAY, LOG_USER); - syslog(LOG_CRIT, "%s", buff); + syslog(LOG_CRIT, "%s", str); closelog(); } } //----------------------------------------------------------------------------- -const char * STG_LOGGER::LogDate(time_t t) const -{ -static char s[32]; -if (t == 0) - t = time(NULL); - -struct tm * tt = localtime(&t); - -snprintf(s, 32, "%d-%s%d-%s%d %s%d:%s%d:%s%d", - tt->tm_year + 1900, - tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1, - tt->tm_mday < 10 ? "0" : "", tt->tm_mday, - tt->tm_hour < 10 ? "0" : "", tt->tm_hour, - tt->tm_min < 10 ? "0" : "", tt->tm_min, - tt->tm_sec < 10 ? "0" : "", tt->tm_sec); - -return s; -} -//----------------------------------------------------------------------------- PLUGIN_LOGGER::PLUGIN_LOGGER(const STG_LOGGER & logger, const std::string & pn) : STG_LOGGER(), pluginName(pn) @@ -119,6 +123,11 @@ va_end(vl); STG_LOGGER::operator()("[%s] %s", pluginName.c_str(), buff); } //----------------------------------------------------------------------------- +void PLUGIN_LOGGER::operator()(const std::string & line) const +{ +STG_LOGGER::operator()("[%s] %s", pluginName.c_str(), line.c_str()); +} +//----------------------------------------------------------------------------- PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER & logger, const std::string & pluginName) { return PLUGIN_LOGGER(logger, pluginName); -- 2.44.2