Commit 95494388 authored by garciay's avatar garciay
Browse files

Layers ongoing

parent 487062a3
......@@ -5,6 +5,7 @@
#include <vector>
#include "Params.hh"
#include "loggers.hh"
class OCTETSTRING;
......@@ -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); }
......
......@@ -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 {
......
#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"
PcapLayer::PcapLayer(const std::string & type, const std::string & param) : PcapLayer() {
loggers::loggers::log(">>> PcapLayer::PcapLayer: %s, %s", type.c_str(), param.c_str());
// 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);
loggers::loggers::log(">>> PcapLayer::PcapLayer: %s, %s", type.c_str(), param.c_str());
// Setup parameters
Params::convert(_params, param);
_params.log();
// 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);
loggers::loggers::log_msg(">>> PcapLayer::sendData: ", data);
}
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::receiveData(const OCTETSTRING& data, const Params& info) {
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 {
static PcapFactory _f;
static PcapFactory _f;
public:
PcapFactory();
virtual Layer * createLayer(const std::string & type,
const std::string & param);
PcapFactory();
virtual Layer * createLayer(const std::string & type,
const std::string & param);
};
PcapFactory::PcapFactory() {
// register factory
loggers::loggers::log(">>> PcapFactory::PcapFactory");
LayerStackBuilder::RegisterLayerFactory("PCAP", this);
// register factory
loggers::loggers::log(">>> PcapFactory::PcapFactory");
LayerStackBuilder::RegisterLayerFactory("PCAP", this);
}
Layer * PcapFactory::createLayer(const std::string & type, const std::string & param) {
return new PcapLayer(type, param);
return new PcapLayer(type, param);
}
PcapFactory PcapFactory::_f;
#pragma once
//#include <pcap.h>
#include <pthread.h>
#include <pcap/pcap.h>
#include "Layer.hh"
#include "Params.hh"
......@@ -8,17 +9,23 @@
class PORT;
class PcapLayer : public PORT, public Layer {
Params _params;
// pcap_t *_device;
int _pcap_h;
Params _params;
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) {};
public:
inline PcapLayer() : PORT("PcapLayer"), Layer(), _params(), /*_device(NULL),*/ _pcap_h(-1) {}
PcapLayer(const std::string & type, const std::string & param);
virtual ~PcapLayer() {}
static void * run(void *p_this);
public:
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 void sendData(const OCTETSTRING& data, const Params& params);
virtual void receiveData(const OCTETSTRING& data, const Params& info);
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);
};
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment