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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
}
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::receive_data: 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::receive_data: stream_id: ", stream_id);
p += 2;
// Stream sequence number
OCTETSTRING stream_num = OCTETSTRING(2, p);
loggers::get_instance().log_msg("sctp_offline_layer::receive_data: 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::receive_data: protocol: %d", protocol);
p += 4;
loggers::get_instance().log("sctp_offline_layer::receive_data: 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
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::send_data: 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;