Skip to content
ip_offline_layer.cc 5.71 KiB
Newer Older
#include <netdb.h>
#include <arpa/inet.h>

#include "ip_offline_layer_factory.hh"

#include "loggers.hh"

ip_offline_layer::ip_offline_layer(const std::string&  p_type, const std::string&  p_param) : layer(p_type), _params() {
  loggers::get_instance().log(">>> ip_offline_layer::ip_offline_layer: '%s', %s", to_string().c_str(), p_param.c_str());
  // Setup parameters
  params::convert(_params, p_param);
}

void ip_offline_layer::send_data(OCTETSTRING& p_data, params& p_params) {
  loggers::get_instance().log_msg(">>> ip_offline_layer::send_data: ", p_data);
  p_params.log();

  // FIXME FSCOM: To be done
  loggers::get_instance().warning("ip_offline_layer::send_data: Not implemented. Only for offline mode");
  TTCN_Buffer ip;
  ip.put_c(0x45); // Protocol version
  ip.put_c(0x02); // Flags
  unsigned short l = p_data.lengthof();
  ip.put_c(l >> 8 & 0xFF); // Data length
  ip.put_c(l & 0xFF); // Data length
  ip.put_c(0x00); ip.put_c(0x00); // Identification
  ip.put_c(0x40); ip.put_c(0x00); // Flags (Don't fragment)
  ip.put_c(0x40); // TTL
  ip.put_c(132); // Protocol is SCTP
  OCTETSTRING checksum = int2oct(0, 2); // Checksum
  ip.put_s(checksum.lengthof(), static_cast<const unsigned char*>(checksum));

  int addr = htonl(get_host_id("localhost"/*_params["dst_ip"]*/));
  OCTETSTRING ip_addr = int2oct(addr, 4); // Source address
  ip.put_s(ip_addr.lengthof(), static_cast<const unsigned char*>(ip_addr));
  ip_addr = int2oct(addr, 4); // Destination address
  ip.put_s(ip_addr.lengthof(), static_cast<const unsigned char*>(ip_addr));

  OCTETSTRING ip_pdu(ip.get_read_len(), ip.get_data());
  ip_pdu += p_data;

  send_to_all_layers(ip_pdu, static_cast<params&>(p_params));
}

void ip_offline_layer::receive_data(OCTETSTRING& p_data, params& p_params) {
  loggers::get_instance().log_msg(">>> ip_offline_layer::receive_data: ", p_data);

  // Version
  uint8_t v = static_cast<const uint8_t>(*p_data);
  OCTETSTRING version = int2oct(1, v >> 4);
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: verion: ", version);
  // Length in bytes
  uint8_t length = (v & 0x0f) * 4;
  loggers::get_instance().log("ip_offline_layer::receive_data: length: %d", length);
  // DSF
  OCTETSTRING dsf = OCTETSTRING(1, 1 + static_cast<const uint8_t *>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: dsf: ", dsf);
  // Total Length
  OCTETSTRING total_length = OCTETSTRING(2, 2 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: total_length: ", total_length);
  // Identification
  OCTETSTRING id = OCTETSTRING(2, 4 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: id: ", id);
  // Flags 
  OCTETSTRING flags = OCTETSTRING(2, 6 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: id: ", flags);
  // TTL 
  OCTETSTRING ttl = OCTETSTRING(1, 8 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: ttl: ", ttl);
  // Protocol 
  OCTETSTRING protocol = OCTETSTRING(1, 9 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: protocol: ", protocol);
  // checksum 
  OCTETSTRING checksum = OCTETSTRING(2, 10 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: checksum: ", checksum);
  // src 
  OCTETSTRING src = OCTETSTRING(4, 12 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: src: ", src);
  // dst 
  OCTETSTRING dst = OCTETSTRING(4, 16 + static_cast<const uint8_t*>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: dst: ", dst);

  OCTETSTRING data = OCTETSTRING(p_data.lengthof() - length, length + static_cast<const uint8_t *>(p_data));
  loggers::get_instance().log_msg("ip_offline_layer::receive_data: payload for upper layer:", data);

  // Update params
  CHARSTRING s = oct2str(dst);
  p_params.insert(std::pair<std::string, std::string>(params::ip_dst, std::string(static_cast<const char *>(s))));
  s = oct2str(src);
  p_params.insert(std::pair<std::string, std::string>(params::ip_src, std::string(static_cast<const char *>(s))));
  s = oct2str(protocol);
  p_params.insert(std::pair<std::string, std::string>(params::ip_proto, std::string(static_cast<const char *>(s))));

  receive_to_all_layers(data, static_cast<params&>(p_params));
}

unsigned long ip_offline_layer::get_host_id(const std::string& p_host_name) {
  loggers::get_instance().log(">>> ip_offline_layer::get_host_id");

  if (p_host_name.empty()) {
    loggers::get_instance().warning("ip_offline_layer::get_host_id: Wrong parameter");
    return INADDR_ANY;
  }

  unsigned long ip_addr = 0;
  if (p_host_name.compare("255.255.255.255") == 0) {
    loggers::get_instance().warning("ip_offline_layer::get_host_id: Host ip is 255.255.255.255");
    ip_addr = 0xffffffff;
  } else {
    in_addr_t addr = ::inet_addr(p_host_name.c_str());
    if (addr != (in_addr_t)-1) { // host name in XX:XX:XX:XX form
      ip_addr = addr;
    } else { // host name in domain.com form
      struct hostent *hptr;
      if ((hptr = ::gethostbyname(p_host_name.c_str())) == 0) {
        loggers::get_instance().error("ip_offline_layer::get_host_id: Invalid host name: '%s'", p_host_name.c_str());
      }
      ip_addr = *((unsigned long *)hptr->h_addr_list[0]);
    }
  }

  loggers::get_instance().log("ip_offline_layer::get_host_id: Host name: '%s', Host address: %u", p_host_name.c_str(), ip_addr);

  return htonl(ip_addr);
}

ip_offline_layer_factory ip_offline_layer_factory::_f;