Newer
Older
#include <chrono>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#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, std::string>(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);
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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<const unsigned char*>(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<const unsigned char*>(protocol));
chunk.put_s(p_data.lengthof(), static_cast<const unsigned char*>(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<const unsigned char*>(vt));
OCTETSTRING checksum = int2oct(0, 4); // Checksum
sctp.put_s(checksum.lengthof(), static_cast<const unsigned char*>(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<params&>(p_params));
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
}
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<const uint8_t *>(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<const uint8_t *>(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<const uint8_t *>(p_data));
loggers::get_instance().log_msg("sctp_offline_layer::receive_data: vtag: ", vtag);
// checksum
OCTETSTRING checksum = OCTETSTRING(4, 8 + static_cast<const uint8_t*>(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<const uint8_t*>(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<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))));
// 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<const uint8_t*>(p_chunk); // Chunk type
switch (static_cast<const uint8_t>(*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);
loggers::get_instance().log("sctp_offline_layer::process_chunk: pointer offset: %d", (uint32_t)(p - static_cast<const uint8_t*>(p_chunk)));
p_payload = OCTETSTRING(p_chunk.lengthof() - (uint32_t)(p - static_cast<const uint8_t*>(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<const uint8_t>(*(p)));
const uint8_t f = static_cast<const uint8_t>(*(p + 1));
loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): flags: %04x", f);
const uint16_t l = static_cast<const uint16_t>((*(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;