X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/a05654cf045d0e8ecc104b019145f627ad6ce4eb..80aca6d78d4ff5d514216fe96c44e2ee75c4e933:/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp index 7fa7fb68..323bd7bf 100644 --- a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp @@ -21,27 +21,36 @@ #include "pcap_cap.h" #include "stg/traffcounter.h" -#include "stg/plugin_creator.h" #include "stg/common.h" #include "stg/raw_ip_packet.h" +#include + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- 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(); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -PLUGIN * GetPlugin() +extern "C" STG::Plugin* GetPlugin() { -return pcc.GetPlugin(); + static PCAP_CAP plugin; + return &plugin; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -52,22 +61,50 @@ return "pcap_cap v.1.0"; } //----------------------------------------------------------------------------- PCAP_CAP::PCAP_CAP() - : errorStr(), - thread(), - nonstop(false), - isRunning(false), - handle(NULL), + : isRunning(false), traffCnt(NULL), - logger(GetPluginLogger(GetStgLogger(), "cap_pcap")) + logger(STG::PluginLogger::get("pcap_cap")) { } //----------------------------------------------------------------------------- +int PCAP_CAP::ParseSettings() +{ +devices.erase(devices.begin(), devices.end()); + +if (settings.moduleParams.empty()) + { + devices.push_back(DEV()); + logger("Defaulting to pseudo-device 'any'."); + 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 +121,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,26 +167,18 @@ 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; } - } - } - -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; + ++it; } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); + return 0; } //----------------------------------------------------------------------------- @@ -158,7 +187,7 @@ int PCAP_CAP::Stop() if (!isRunning) return 0; -nonstop = false; +m_thread.request_stop(); //5 seconds to thread stops itself for (int i = 0; i < 25 && isRunning; i++) @@ -168,69 +197,70 @@ for (int i = 0; i < 25 && isRunning; i++) } //after 5 seconds waiting thread still running. now killing it if (isRunning) + m_thread.detach(); +else + m_thread.join(); + +for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it) { - 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); - } + pcap_freecode(&it->filter); + pcap_close(it->handle); } return 0; } //----------------------------------------------------------------------------- -void * PCAP_CAP::Run(void * d) +void PCAP_CAP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -PCAP_CAP * dc = static_cast(d); -dc->isRunning = true; +isRunning = true; -struct ETH_IP -{ -uint16_t ethHdr[8]; -RAW_PACKET rp; -char padding[4]; -char padding1[8]; -}; +fd_set fds; +FD_ZERO(&fds); +int maxFd = 0; +for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it) + { + FD_SET(it->fd, &fds); + maxFd = std::max(maxFd, it->fd); + } -char ethip[sizeof(ETH_IP)]; +while (!token.stop_requested()) + { + fd_set rfds = fds; + struct timeval tv = {0, 500000}; -memset(ðip, 0, sizeof(ETH_IP)); + if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0) + TryRead(rfds); + } -ETH_IP * ethIP = static_cast(static_cast(ðip)); -ethIP->rp.dataLen = -1; +isRunning = false; +} -char * iface = 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); +} -while (dc->nonstop) +void PCAP_CAP::TryReadDev(const DEV & dev) +{ +struct pcap_pkthdr * header; +const u_char * packet; +if (pcap_next_ex(dev.handle, &header, &packet) == -1) { - - if (ethIP->ethHdr[7] != 0x8) - continue; - - dc->traffCnt->Process(ethIP->rp); + printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle)); + return; } -dc->isRunning = false; -return NULL; +const ETH * eth = reinterpret_cast(packet); +if (eth->ether_type != 0x8) + return; + +STG::RawPacket ip; +memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket)); +traffCnt->process(ip); }