Commit 399c4d07 authored by garciay's avatar garciay
Browse files

Start adding RawSocketLayer support

parent 1c70560c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
#if (OSTYPE != cygwin)

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -274,3 +276,6 @@ Layer * PcapFactory::createLayer(const std::string & type, const std::string & p
}

PcapFactory PcapFactory::_f;

#endif
+3 −0
Original line number Diff line number Diff line
#pragma once

#if (OSTYPE != cygwin)

#include <thread>
#include <mutex>
#include <pcap/pcap.h>
@@ -31,3 +33,4 @@ public:
  void Handle_Fd_Event_Readable(int fd);
};

#endif
+145 −0
Original line number Diff line number Diff line
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <chrono>

#include "Port.hh"

#include "RawSocketLayer.hh"
#include "loggers.hh"

RawSocketLayer::RawSocketLayer(const std::string& p_type, const std::string& param) : Layer(p_type), PORT(p_type.c_str()), _params(), _socket(-1), _time_key("RawSocketLayer::Handle_Fd_Event_Readable") {
  loggers::get_instance().log(">>> RawSocketLayer::RawSocketLayer: %s, %s", to_string().c_str(), param.c_str());
  memset(&_if_interface, 0x00, sizeof(struct ifreq));
  memset(&_if_mac_addr, 0x00, sizeof(struct ifreq));
  // Setup parameters
  Params::convert(_params, param);
  //_params.log();
  // Prepare capture processing
  if ((_socket = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    loggers::get_instance().error("RawSocketLayer::RawSocketLayer: Failed to create socket %d", errno);
  }

  Params::const_iterator it = _params.find(Params::nic); 
  if ((it != _params.end()) && !it->second.empty()) { // Use online capture
    snprintf(_if_interface.ifr_name, sizeof(_if_interface.ifr_name), it->second.c_str());
    setsockopt(_socket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&_if_interface, sizeof(struct ifreq));
  } else {
    loggers::get_instance().error("RawSocketLayer::RawSocketLayer: Failed to open device");
  }
  
  // Setup filter
  std::string filter = "";
  it = _params.find(Params::mac_src);
  if (it == _params.end()) { // Not found
    loggers::get_instance().error("RawSocketLayer::RawSocketLayer: mac_src parameter not found, cannot continue");
  } else {
    /***
    // Reject ITS messages sent by this component
    filter = "not ether src " + _params[Params::mac_src]; 
    // Accept ITS broadcasted to this componenet
    filter += " and (ether dst " + _params[Params::mac_src];
    // Accept ITS broadcasted messages
    it = _params.find(Params::mac_bc);
    if ((it != _params.end()) && !it->second.empty()) {
      filter += " or ether dst " + it->second + ")";
    } else {
      filter += " or ether dst ffffffffffff) ";
    }
    // Add user defined filter
    it = _params.find(std::string("filter"));
    if ((it != _params.end()) && !it->second.empty()) {
      filter += _params["filter"];
    } // else nothing to do
    ***/
  }
  // Log final PCAP filter
  loggers::get_instance().user("RawSocketLayer::RawSocketLayer: Filter: %s", filter.c_str());
  // Pass the device file handler to the polling procedure
  Handler_Add_Fd_Read(_socket); // Live capture
} // End of ctor

RawSocketLayer::~RawSocketLayer() {
  loggers::get_instance().log(">>> RawSocketLayer::~RawSocketLayer");
  
  if (_socket != -1) {
    close(_socket);
  }
} // End of dtor

void RawSocketLayer::sendData(OCTETSTRING& data, Params& params) {
  loggers::get_instance().log_msg(">>> RawSocketLayer::sendData: ", data);
  /***
  if (_pcap_h != -1) { // Check if offline mode is used
    if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) {
      loggers::get_instance().error("RawSocketLayer::sendData: Failed to send packet: %s", pcap_geterr(_device));
    }
  } else if (_sent_file != NULL) {
    struct pcap_pkthdr  hdr;
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    hdr.ts.tv_sec = ms.count() / 1000;
    hdr.ts.tv_usec = (ms.count() % 1000) * 1000;
    hdr.caplen = data.lengthof();
    hdr.len = hdr.caplen;
    pcap_dump((u_char *)_sent_file, &hdr, static_cast<const unsigned char *>(data));
  } else {
    loggers::get_instance().log("RawSocketLayer::sendData: Offline mode, operation was skipped");
  }
  ***/
}

void RawSocketLayer::receiveData(OCTETSTRING& data, Params& params) {
  loggers::get_instance().log(">>> RawSocketLayer::receiveData: Received %d bytes", data.lengthof());
  loggers::get_instance().log_to_hexa("Packet dump", data);
  
  // Pass the packet to the upper layers
  receiveToAllLayers(data, params);
}

void RawSocketLayer::Handle_Fd_Event_Readable(int fd) {
  //loggers::get_instance().log(">>> RawSocketLayer::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::get_instance().log("RawSocketLayer::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
      OCTETSTRING os(pkt_header->caplen, pkt_data);
      //loggers::get_instance().log_to_hexa("RawSocketLayer::Handle_Fd_Event_Readable: ", os);
      // TODO Case of caplen != len !!!
      float duration;
      loggers::get_instance().set_start_time(_time_key);
      this->receiveData(os, params); // TODO Check execution time for decoding operation
      loggers::get_instance().set_stop_time(_time_key, duration);      
    }
  } // else, skip the packet
  ***/
}

class RawSocketFactory: public LayerFactory {
  static RawSocketFactory _f;
public:
  RawSocketFactory();
  virtual Layer * createLayer(const std::string & type,
                              const std::string & param);
};

RawSocketFactory::RawSocketFactory() {
  // register factory
  loggers::get_instance().log(">>> RawSocketFactory::RawSocketFactory");
  LayerStackBuilder::RegisterLayerFactory("RAW", this);
}

Layer * RawSocketFactory::createLayer(const std::string & type, const std::string & param) {
  return new RawSocketLayer(type, param);
}

RawSocketFactory RawSocketFactory::_f;
+35 −0
Original line number Diff line number Diff line
#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ether.h> // Used for raw sockets
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <net/if.h> // Used for raw sockets
#include <net/ethernet.h> // Used for raw sockets

#include <linux/if_packet.h> // Used for raw sockets

#include "Layer.hh"
#include "Params.hh"

class PORT;

class RawSocketLayer : public Layer, public PORT {
  Params _params;
  int _socket;
  std::string _time_key;
  struct ifreq _if_interface;
  struct ifreq _if_mac_addr;

public:
  RawSocketLayer(const std::string& p_type, const std::string& param);
  virtual ~RawSocketLayer();

  virtual void sendData(OCTETSTRING& data, Params& params);
  virtual void receiveData(OCTETSTRING& data, Params& info);
  
  void Handle_Fd_Event_Readable(int fd);
};