#include #include #include #include #include #include "sctp_offline_layer_factory.hh" #include "loggers.hh" sctp_offline_layer::sctp_offline_layer(const std::string& p_type, const std::string& param) : layer(p_type), _params(), _time_key("sctp_offline_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> sctp_offline_layer::sctp_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); _o_params.insert(std::pair(std::string("timestamp"), std::string())); } // End of ctor sctp_offline_layer::~sctp_offline_layer() { loggers::get_instance().log(">>> sctp_offline_layer::~sctp_offline_layer"); } // End of dtor void sctp_offline_layer::send_data(OCTETSTRING &p_data, params &p_params) { loggers::get_instance().log_msg(">>> sctp_offline_layer::send_data: ", p_data); p_params.log(); // FIXME FSCOM: To be done loggers::get_instance().warning("sctp_offline_layer::send_data: Not implemented. Only for offline mode"); TTCN_Buffer chunk; chunk.put_c(0x00); // DATA chunk chunk.put_c(0x03); // Flags unsigned short l = p_data.lengthof(); chunk.put_c(l >> 8 & 0xFF); // Data length chunk.put_c(l & 0xFF); // Data length OCTETSTRING tsn = int2oct(0, 4); // Transmission sequence number chunk.put_s(tsn.lengthof(), static_cast(tsn)); l = 7; // Stream sequence identifier chunk.put_c(l >> 8 & 0xFF); // Stream sequence identifier chunk.put_c(l & 0xFF); // Stream sequence identifier chunk.put_c(0x00); // Stream sequence number chunk.put_c(0x00); // Stream sequence number OCTETSTRING protocol = int2oct(60, 4); // Protocol is NGAP chunk.put_s(protocol.lengthof(), static_cast(protocol)); chunk.put_s(p_data.lengthof(), static_cast(p_data)); // FIXME FSCOM: Add padding TTCN_Buffer sctp; l = 12345; // SCTP Source port sctp.put_c(l >> 8 & 0xFF); // Stream sequence identifier sctp.put_c(l & 0xFF); // Stream sequence identifier l = 12345; // SCTP Destination port sctp.put_c(l >> 8 & 0xFF); // Stream sequence identifier sctp.put_c(l & 0xFF); // Stream sequence identifier OCTETSTRING vt = int2oct(0, 4); // Verification tag sctp.put_s(vt.lengthof(), static_cast(vt)); OCTETSTRING checksum = int2oct(0, 4); // Checksum sctp.put_s(checksum.lengthof(), static_cast(checksum)); OCTETSTRING sctp_pdu(sctp.get_read_len(), sctp.get_data()); sctp_pdu += OCTETSTRING(chunk.get_read_len(), chunk.get_data()); send_to_all_layers(sctp_pdu, static_cast(p_params)); } void sctp_offline_layer::receive_data(OCTETSTRING &p_data, params &p_params) { loggers::get_instance().log(">>> sctp_offline_layer::receive_data: Received %d bytes", p_data.lengthof()); loggers::get_instance().log_to_hexa("Packet dump", p_data); // Source port OCTETSTRING src_port = OCTETSTRING(2, static_cast(p_data)); loggers::get_instance().log_msg("sctp_offline_layer::receive_data: src_port: ", src_port); // Dst port OCTETSTRING dst_port = OCTETSTRING(2, 2 + static_cast(p_data)); loggers::get_instance().log_msg("sctp_offline_layer::receive_data: dst_port: ", dst_port); // Verification tag OCTETSTRING vtag = OCTETSTRING(4, 4 + static_cast(p_data)); loggers::get_instance().log_msg("sctp_offline_layer::receive_data: vtag: ", vtag); // checksum OCTETSTRING checksum = OCTETSTRING(4, 8 + static_cast(p_data)); loggers::get_instance().log_msg("sctp_offline_layer::receive_data: checksum: ", checksum); // Chunk OCTETSTRING chunk = OCTETSTRING(p_data.lengthof() - 12, 12 + static_cast(p_data)); loggers::get_instance().log_msg("sctp_offline_layer::receive_data: chunk: ", chunk); OCTETSTRING payload(0, nullptr); process_chunk(chunk, p_params, payload); if (payload.lengthof() == 0) { loggers::get_instance().log("sctp_offline_layer::receive_data: SCTP chunk, skip it"); return; } // Update params // CHARSTRING s = oct2str(dst); // p_params.insert(std::pair(params::ip_dst, std::string(static_cast(s)))); // s = oct2str(src); // p_params.insert(std::pair(params::ip_src, std::string(static_cast(s)))); // s = oct2str(protocol); // p_params.insert(std::pair(params::ip_proto, std::string(static_cast(s)))); // Pass the packet to the upper layers receive_to_all_layers(payload, p_params); } void sctp_offline_layer::process_chunk(const OCTETSTRING& p_chunk, params &p_params, OCTETSTRING& p_payload) { loggers::get_instance().log_msg(">>> sctp_offline_layer::process_chunk: ", p_chunk); const uint8_t* p = static_cast(p_chunk); // Chunk type switch (static_cast(*p)) { case 0x00: { // DATA chunk p += 2; // Skip Chunk type + Chunk flag // Chunk length uint16_t l = (*p << 8 | *(p + 1)) & 0xffff; loggers::get_instance().log("sctp_offline_layer::process_chunk: l: %d", l); p += 2; p += 4; // Skip Transmission sequence number // Stream identifier OCTETSTRING stream_id = OCTETSTRING(2, p); loggers::get_instance().log_msg("sctp_offline_layer::process_chunk: stream_id: ", stream_id); p += 2; // Stream sequence number OCTETSTRING stream_num = OCTETSTRING(2, p); loggers::get_instance().log_msg("sctp_offline_layer::process_chunk: stream_num: ", stream_num); p += 2; // Protocol uint32_t protocol = (*p << 24 | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3)) & 0xffffffff; loggers::get_instance().log("sctp_offline_layer::process_chunk: protocol: %d", protocol); p += 4; loggers::get_instance().log("sctp_offline_layer::process_chunk: pointer offset: %d", (uint32_t)(p - static_cast(p_chunk))); p_payload = OCTETSTRING(p_chunk.lengthof() - (uint32_t)(p - static_cast(p_chunk)), p); } break; case 0x01: // INIT chunk break; case 0x02: // INIT_ACK chunk break; case 0x03: { // SACK loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): position: %02x", static_cast(*(p))); const uint8_t f = static_cast(*(p + 1)); loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): flags: %04x", f); const uint16_t l = static_cast((*(p + 2) << 8 | *(p + 3)) & 0xffff); loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): length: %d", l); loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): p_chunk.lengthof(): %d", p_chunk.lengthof()); if (p_chunk.lengthof() > l) { // Extract and process the next chunk OCTETSTRING chunk(p_chunk.lengthof() - l, p + l); process_chunk(chunk, p_params, p_payload); } } break; case 0x04: // HEARTBEAT break; case 0x05: // HEARTBEAT_ACK break; case 0x0a: // COOKIE_ECHO chunk break; case 0x0b: // COOKIE_ACK chunk break; default: // loggers::get_instance().warning("sctp_offline_layer::process_chunk: Unprocessed chunk: 0x%02x", *p); } loggers::get_instance().log_msg("<<< sctp_offline_layer::process_chunk: p_payload: ", p_payload); } sctp_offline_layer_factory sctp_offline_layer_factory::_f;