Loading ccsrc/Framework/Layer.hh +9 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <vector> #include "Params.hh" #include "loggers.hh" class OCTETSTRING; Loading @@ -23,7 +24,14 @@ class Layer { virtual void receiveData(const OCTETSTRING& data, const Params& info) {}; protected: void toAllLayers(std::vector<Layer*>&layers, const OCTETSTRING& data, const Params& info) {}; inline void toAllLayers(std::vector<Layer*>&layers, const OCTETSTRING& data, const Params& info) { // loggers::loggers::log_msg(">>> Layer::toAllLayer: ", data); loggers::loggers::log(">>> Layer::toAllLayer: %d", layers.size()); for (std::vector<Layer*>::const_iterator it = layers.cbegin(); it != layers.cend(); ++it) { Layer * p = *it; p->receiveData(data, info); } // End of 'for' statement }; inline void toAllUpperLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } inline void toAllLowerLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } inline void receiveToAllLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } Loading ccsrc/Protocols/ETH/EthernetLayer.cc +13 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,19 @@ void EthernetLayer::sendData(const OCTETSTRING& data, const Params& params) { } void EthernetLayer::receiveData(const OCTETSTRING& data, const Params& info) { loggers::loggers::log_msg(">>> EthernetLayer::receiveData: ", data); // Extract dest MAC Address OCTETSTRING dst = data << 6; loggers::loggers::log_msg("EthernetLayer::receiveData: dst: ", dst); // Extract source MAC Address OCTETSTRING src = data << 6; loggers::loggers::log_msg("EthernetLayer::receiveData: src: ", src); // Extract ethertype OCTETSTRING type = data << 2; loggers::loggers::log_msg("EthernetLayer::receiveData: type: ", type); // Update params loggers::loggers::log_msg("<<< EthernetLayer::receiveData: ", data); } class EthernetFactory: public LayerFactory { Loading ccsrc/Protocols/Pcap/PcapLayer.cc +167 −23 Original line number Diff line number Diff line #include "PORT.hh" #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <thread> #include <chrono> #include "Port.hh" #include "PcapLayer.hh" #include "loggers.hh" Loading @@ -8,22 +15,159 @@ PcapLayer::PcapLayer(const std::string & type, const std::string & param) : Pcap // Setup parameters Params::convert(_params, param); _params.log(); // char error_buffer[64]; // pcap_if_t devices = NULL; // // if (pcap_findalldevs(devices, error_buffer) == -1) { // // Add throw exception // } // // _pcap_h = pcap_get_selectable(_device); // Prepare capture processing char error_buffer[PCAP_ERRBUF_SIZE]; std::map<std::string, std::string>::const_iterator it = _params.find(std::string("nic")); if ((it != _params.end()) && !it->second.empty()) { // Use online capture // Fetch the network address and network mask /*bpf_u_int32 mask; // subnet mask bpf_u_int32 net; // ip address if (pcap_lookupnet(_params["nic"].c_str(), &net, &mask, error_buffer) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: PcapLayer::PcapLayer: Failed to fetch newtork address for device %s", _params["nic"].c_str()); } loggers::loggers::log("PcapLayer::PcapLayer: Device %s Network address: %d", _params["nic"].c_str(), net);*/ // Open the device _device = pcap_open_live(_params["nic"].c_str(), 65536, 1, 1000, error_buffer); // TODO Replace hard coded values by PcapLayer::<constants> if (_device == NULL) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open device %s", _params["nic"].c_str()); } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to set blocking mode: %s", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); if (_pcap_h == -1) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to get device handler"); } } else { // Check file name it = _params.find(std::string("file")); if ((it != _params.end()) && !it->second.empty()) { // Use offline capture struct stat s = {0}; if ((stat(_params["file"].c_str(), &s) != 0) || !S_ISREG(s.st_mode)) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to acces PCAP file %s", _params["file"].c_str()); } // File exist, open it _device = pcap_open_offline(_params["file"].c_str(), error_buffer); if (_device == NULL) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer); } // else, continue } else { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer); } } // Setup filter std::string filter; it = _params.find(std::string("filter")); if ((it != _params.end()) && !it->second.empty()) { filter = _params["filter"]; } // else nothing to do loggers::loggers::log("PcapLayer::PcapLayer: Filter: %s", filter.c_str()); if (!filter.empty()) { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to compile PCAP filter"); } if (pcap_setfilter(_device, &f) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to set PCAP filter"); } pcap_freecode(&f); } // Pass the device file handler to the polling procedure if (_pcap_h != -1) { Handler_Add_Fd_Read(_pcap_h); } else { // Create a pipe if (pipe2(_fd, O_NONBLOCK) == -1) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to create a pipe: %s", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::loggers::log("PcapLayer::PcapLayer: Call handler with descriptor %d", _fd[0]); Handler_Add_Fd_Read(_fd[0]); if (pthread_create(&_thread_id, NULL, &PcapLayer::run, (void *)this) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to compile PCAP filter"); } // Start a working thread to dispatch packet to a pipe while (_running == FALSE) { std::this_thread::sleep_for(std::chrono::seconds(1)); } loggers::loggers::log("<<< PcapLayer::PcapLayer"); } } // End of ctor PcapLayer::~PcapLayer() { loggers::loggers::log(">>> PcapLayer::~PcapLayer"); if (_device != NULL) { if (_fd[0] != -1) { // TODO To be refined :-( _running = FALSE; // Wait for the working thread to terminate pthread_join(_thread_id, NULL); loggers::loggers::log("PcapLayer::~PcapLayer: Thread were stops"); // Cleanup close(_fd[0]); close(_fd[1]); } pcap_close(_device); } } // End of dtor void * PcapLayer::run(void *p_this) { loggers::loggers::log(">>> PcapLayer::run: Class pointer: %p", p_this); PcapLayer& p = *static_cast<PcapLayer *>(p_this); p._running = TRUE; p._resume = TRUE; while (p._running) { if (p._resume == TRUE) { write(p._fd[1], "\n", 1); p._resume = FALSE; } std::this_thread::sleep_for(std::chrono::milliseconds(200)); } loggers::loggers::log("<<< PcapLayer::run"); return NULL; } void PcapLayer::sendData(const OCTETSTRING& data, const Params& params) { loggers::loggers::log_msg(">>> PcapLayer::sendData: ", data); } void PcapLayer::receiveData(const OCTETSTRING& data, const Params& info) { void PcapLayer::receiveData(const OCTETSTRING& data, const Params& params) { //loggers::loggers::log(">>> PcapLayer::receiveData: Received %d bytes", data.lengthof()); //loggers::loggers::log_to_hexa("Packet dump", data); // Pass the packet to the upper layers toAllUpperLayers(data, params); } void PcapLayer::Handle_Fd_Event_Readable(int fd) { //loggers::loggers::log(">>> PcapLayer::Handle_Fd_Event_Readable: %d", fd); struct pcap_pkthdr *pkt_header; const u_char *pkt_data; int result = pcap_next_ex(_device, &pkt_header, &pkt_data); if (result == 1) { // Succeed if (pkt_header->caplen > 14) { // Reject too small packet //loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: %.6d - %d", pkt_header->ts.tv_usec, pkt_header->len); // Fill parameters from PCAP layer Params params; params.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(pkt_header->ts.tv_usec))); // Process the packet at this layer this->receiveData(OCTETSTRING(pkt_header->len, pkt_data), params); } } // else, skip the packet // Specific to offline mode if (_fd[0] != -1) { // Check if offline mode is used //loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: Read pipe"); char c[2]; read(_fd[0], &c, 1); if (result == -2) { // End of file, therminate worker thread _running = FALSE; } else { // Get next packet loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: pcap_next_ex failed: result=%d", result); _resume = TRUE; } } // else, nothing to do } class PcapFactory: public LayerFactory { Loading ccsrc/Protocols/Pcap/PcapLayer.hh +18 −11 Original line number Diff line number Diff line #pragma once //#include <pcap.h> #include <pthread.h> #include <pcap/pcap.h> #include "Layer.hh" #include "Params.hh" Loading @@ -9,16 +10,22 @@ class PORT; class PcapLayer : public PORT, public Layer { Params _params; // pcap_t *_device; pcap_t *_device; int _pcap_h; pthread_t _thread_id; bool _running; bool _resume; int _fd[2]; virtual void Handle_Fd_Event_Readable(int fd) {}; static void * run(void *p_this); public: inline PcapLayer() : PORT("PcapLayer"), Layer(), _params(), /*_device(NULL),*/ _pcap_h(-1) {} inline PcapLayer() : PORT("PcapLayer"), Layer(), _params(), _device(NULL), _pcap_h(-1), _thread_id(-1), _running(FALSE), _resume(FALSE) { _fd[0] = -1; _fd[1] = -1; }; PcapLayer(const std::string & type, const std::string & param); virtual ~PcapLayer() {} virtual ~PcapLayer(); virtual void sendData(const OCTETSTRING& data, const Params& params); virtual void receiveData(const OCTETSTRING& data, const Params& info); void Handle_Fd_Event_Readable(int fd); }; Loading
ccsrc/Framework/Layer.hh +9 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <vector> #include "Params.hh" #include "loggers.hh" class OCTETSTRING; Loading @@ -23,7 +24,14 @@ class Layer { virtual void receiveData(const OCTETSTRING& data, const Params& info) {}; protected: void toAllLayers(std::vector<Layer*>&layers, const OCTETSTRING& data, const Params& info) {}; inline void toAllLayers(std::vector<Layer*>&layers, const OCTETSTRING& data, const Params& info) { // loggers::loggers::log_msg(">>> Layer::toAllLayer: ", data); loggers::loggers::log(">>> Layer::toAllLayer: %d", layers.size()); for (std::vector<Layer*>::const_iterator it = layers.cbegin(); it != layers.cend(); ++it) { Layer * p = *it; p->receiveData(data, info); } // End of 'for' statement }; inline void toAllUpperLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } inline void toAllLowerLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } inline void receiveToAllLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); } Loading
ccsrc/Protocols/ETH/EthernetLayer.cc +13 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,19 @@ void EthernetLayer::sendData(const OCTETSTRING& data, const Params& params) { } void EthernetLayer::receiveData(const OCTETSTRING& data, const Params& info) { loggers::loggers::log_msg(">>> EthernetLayer::receiveData: ", data); // Extract dest MAC Address OCTETSTRING dst = data << 6; loggers::loggers::log_msg("EthernetLayer::receiveData: dst: ", dst); // Extract source MAC Address OCTETSTRING src = data << 6; loggers::loggers::log_msg("EthernetLayer::receiveData: src: ", src); // Extract ethertype OCTETSTRING type = data << 2; loggers::loggers::log_msg("EthernetLayer::receiveData: type: ", type); // Update params loggers::loggers::log_msg("<<< EthernetLayer::receiveData: ", data); } class EthernetFactory: public LayerFactory { Loading
ccsrc/Protocols/Pcap/PcapLayer.cc +167 −23 Original line number Diff line number Diff line #include "PORT.hh" #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <thread> #include <chrono> #include "Port.hh" #include "PcapLayer.hh" #include "loggers.hh" Loading @@ -8,22 +15,159 @@ PcapLayer::PcapLayer(const std::string & type, const std::string & param) : Pcap // Setup parameters Params::convert(_params, param); _params.log(); // char error_buffer[64]; // pcap_if_t devices = NULL; // // if (pcap_findalldevs(devices, error_buffer) == -1) { // // Add throw exception // } // // _pcap_h = pcap_get_selectable(_device); // Prepare capture processing char error_buffer[PCAP_ERRBUF_SIZE]; std::map<std::string, std::string>::const_iterator it = _params.find(std::string("nic")); if ((it != _params.end()) && !it->second.empty()) { // Use online capture // Fetch the network address and network mask /*bpf_u_int32 mask; // subnet mask bpf_u_int32 net; // ip address if (pcap_lookupnet(_params["nic"].c_str(), &net, &mask, error_buffer) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: PcapLayer::PcapLayer: Failed to fetch newtork address for device %s", _params["nic"].c_str()); } loggers::loggers::log("PcapLayer::PcapLayer: Device %s Network address: %d", _params["nic"].c_str(), net);*/ // Open the device _device = pcap_open_live(_params["nic"].c_str(), 65536, 1, 1000, error_buffer); // TODO Replace hard coded values by PcapLayer::<constants> if (_device == NULL) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open device %s", _params["nic"].c_str()); } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to set blocking mode: %s", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); if (_pcap_h == -1) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to get device handler"); } } else { // Check file name it = _params.find(std::string("file")); if ((it != _params.end()) && !it->second.empty()) { // Use offline capture struct stat s = {0}; if ((stat(_params["file"].c_str(), &s) != 0) || !S_ISREG(s.st_mode)) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to acces PCAP file %s", _params["file"].c_str()); } // File exist, open it _device = pcap_open_offline(_params["file"].c_str(), error_buffer); if (_device == NULL) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer); } // else, continue } else { loggers::loggers::error("PcapLayer::PcapLayer: Failed to open PCAP file %s", error_buffer); } } // Setup filter std::string filter; it = _params.find(std::string("filter")); if ((it != _params.end()) && !it->second.empty()) { filter = _params["filter"]; } // else nothing to do loggers::loggers::log("PcapLayer::PcapLayer: Filter: %s", filter.c_str()); if (!filter.empty()) { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to compile PCAP filter"); } if (pcap_setfilter(_device, &f) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to set PCAP filter"); } pcap_freecode(&f); } // Pass the device file handler to the polling procedure if (_pcap_h != -1) { Handler_Add_Fd_Read(_pcap_h); } else { // Create a pipe if (pipe2(_fd, O_NONBLOCK) == -1) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to create a pipe: %s", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::loggers::log("PcapLayer::PcapLayer: Call handler with descriptor %d", _fd[0]); Handler_Add_Fd_Read(_fd[0]); if (pthread_create(&_thread_id, NULL, &PcapLayer::run, (void *)this) != 0) { loggers::loggers::error("PcapLayer::PcapLayer: Failed to compile PCAP filter"); } // Start a working thread to dispatch packet to a pipe while (_running == FALSE) { std::this_thread::sleep_for(std::chrono::seconds(1)); } loggers::loggers::log("<<< PcapLayer::PcapLayer"); } } // End of ctor PcapLayer::~PcapLayer() { loggers::loggers::log(">>> PcapLayer::~PcapLayer"); if (_device != NULL) { if (_fd[0] != -1) { // TODO To be refined :-( _running = FALSE; // Wait for the working thread to terminate pthread_join(_thread_id, NULL); loggers::loggers::log("PcapLayer::~PcapLayer: Thread were stops"); // Cleanup close(_fd[0]); close(_fd[1]); } pcap_close(_device); } } // End of dtor void * PcapLayer::run(void *p_this) { loggers::loggers::log(">>> PcapLayer::run: Class pointer: %p", p_this); PcapLayer& p = *static_cast<PcapLayer *>(p_this); p._running = TRUE; p._resume = TRUE; while (p._running) { if (p._resume == TRUE) { write(p._fd[1], "\n", 1); p._resume = FALSE; } std::this_thread::sleep_for(std::chrono::milliseconds(200)); } loggers::loggers::log("<<< PcapLayer::run"); return NULL; } void PcapLayer::sendData(const OCTETSTRING& data, const Params& params) { loggers::loggers::log_msg(">>> PcapLayer::sendData: ", data); } void PcapLayer::receiveData(const OCTETSTRING& data, const Params& info) { void PcapLayer::receiveData(const OCTETSTRING& data, const Params& params) { //loggers::loggers::log(">>> PcapLayer::receiveData: Received %d bytes", data.lengthof()); //loggers::loggers::log_to_hexa("Packet dump", data); // Pass the packet to the upper layers toAllUpperLayers(data, params); } void PcapLayer::Handle_Fd_Event_Readable(int fd) { //loggers::loggers::log(">>> PcapLayer::Handle_Fd_Event_Readable: %d", fd); struct pcap_pkthdr *pkt_header; const u_char *pkt_data; int result = pcap_next_ex(_device, &pkt_header, &pkt_data); if (result == 1) { // Succeed if (pkt_header->caplen > 14) { // Reject too small packet //loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: %.6d - %d", pkt_header->ts.tv_usec, pkt_header->len); // Fill parameters from PCAP layer Params params; params.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(pkt_header->ts.tv_usec))); // Process the packet at this layer this->receiveData(OCTETSTRING(pkt_header->len, pkt_data), params); } } // else, skip the packet // Specific to offline mode if (_fd[0] != -1) { // Check if offline mode is used //loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: Read pipe"); char c[2]; read(_fd[0], &c, 1); if (result == -2) { // End of file, therminate worker thread _running = FALSE; } else { // Get next packet loggers::loggers::log("PcapLayer::Handle_Fd_Event_Readable: pcap_next_ex failed: result=%d", result); _resume = TRUE; } } // else, nothing to do } class PcapFactory: public LayerFactory { Loading
ccsrc/Protocols/Pcap/PcapLayer.hh +18 −11 Original line number Diff line number Diff line #pragma once //#include <pcap.h> #include <pthread.h> #include <pcap/pcap.h> #include "Layer.hh" #include "Params.hh" Loading @@ -9,16 +10,22 @@ class PORT; class PcapLayer : public PORT, public Layer { Params _params; // pcap_t *_device; pcap_t *_device; int _pcap_h; pthread_t _thread_id; bool _running; bool _resume; int _fd[2]; virtual void Handle_Fd_Event_Readable(int fd) {}; static void * run(void *p_this); public: inline PcapLayer() : PORT("PcapLayer"), Layer(), _params(), /*_device(NULL),*/ _pcap_h(-1) {} inline PcapLayer() : PORT("PcapLayer"), Layer(), _params(), _device(NULL), _pcap_h(-1), _thread_id(-1), _running(FALSE), _resume(FALSE) { _fd[0] = -1; _fd[1] = -1; }; PcapLayer(const std::string & type, const std::string & param); virtual ~PcapLayer() {} virtual ~PcapLayer(); virtual void sendData(const OCTETSTRING& data, const Params& params); virtual void receiveData(const OCTETSTRING& data, const Params& info); void Handle_Fd_Event_Readable(int fd); };