mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added TCPTest. Fixed some TCP bugs, most of them related to options.
This commit is contained in:
121
include/tcp.h
121
include/tcp.h
@@ -66,10 +66,23 @@ namespace Tins {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum Options {
|
enum Options {
|
||||||
EOL = 0,
|
EOL = 0,
|
||||||
NOP = 1,
|
NOP = 1,
|
||||||
MSS = 2,
|
MSS = 2,
|
||||||
TSOPT = 8
|
WSCALE = 3,
|
||||||
|
SACK_OK = 4,
|
||||||
|
SACK = 5,
|
||||||
|
TSOPT = 8,
|
||||||
|
ALTCHK = 14
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Alternate checksum enum.
|
||||||
|
*/
|
||||||
|
enum AltChecksums {
|
||||||
|
CHK_TCP,
|
||||||
|
CHK_8FLETCHER,
|
||||||
|
CHK_16FLETCHER
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,8 +95,8 @@ namespace Tins {
|
|||||||
* \param olength The option's data length.
|
* \param olength The option's data length.
|
||||||
* \param odata The option's data(if any).
|
* \param odata The option's data(if any).
|
||||||
*/
|
*/
|
||||||
TCPOption(uint8_t okind = 0, uint8_t olength = 0, uint8_t *odata = 0) :
|
TCPOption(uint8_t opt = 0, uint8_t olength = 0, uint8_t *ovalue = 0) :
|
||||||
kind(okind), length(olength), data(odata) { }
|
option(opt), length(olength), value(ovalue) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Writes the option into a buffer.
|
* \brief Writes the option into a buffer.
|
||||||
@@ -92,8 +105,8 @@ namespace Tins {
|
|||||||
*/
|
*/
|
||||||
uint8_t *write(uint8_t *buffer);
|
uint8_t *write(uint8_t *buffer);
|
||||||
|
|
||||||
uint8_t kind, length;
|
uint8_t option, length;
|
||||||
uint8_t *data;
|
uint8_t *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,19 +288,87 @@ namespace Tins {
|
|||||||
void payload(uint8_t *new_payload, uint32_t new_payload_size);
|
void payload(uint8_t *new_payload, uint32_t new_payload_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the maximum segment size.
|
* \brief Add a maximum segment size option.
|
||||||
*
|
*
|
||||||
* \param value The new maximum segment size.
|
* \param value The new maximum segment size.
|
||||||
*/
|
*/
|
||||||
void set_mss(uint16_t value);
|
void add_mss_option(uint16_t value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the timestamp.
|
* \brief Searchs for a maximum segment size option.
|
||||||
|
* \param value A pointer in which the option's value will be stored.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_mss_option(uint16_t *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a window scale option.
|
||||||
|
*
|
||||||
|
* \param value The new window scale.
|
||||||
|
*/
|
||||||
|
void add_winscale_option(uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for a window scale option.
|
||||||
|
* \param value A pointer in which the option's value will be stored.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_winscale_option(uint8_t *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a sack permitted option.
|
||||||
|
*/
|
||||||
|
void add_sack_permitted_option();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for a sack permitted option.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_sack_permitted_option();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a sack option.
|
||||||
|
*
|
||||||
|
* \param value The new window scale.
|
||||||
|
*/
|
||||||
|
void add_sack_option(const std::list<uint32_t> &edges);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for a sack option.
|
||||||
|
* \param value A pointer in which the option's value will be stored.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_sack_option(std::list<uint32_t> *edges);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a timestamp option.
|
||||||
*
|
*
|
||||||
* \param value The current value of the timestamp clock.
|
* \param value The current value of the timestamp clock.
|
||||||
* \param reply The echo reply field.
|
* \param reply The echo reply field.
|
||||||
*/
|
*/
|
||||||
void set_timestamp(uint32_t value, uint32_t reply);
|
void add_timestamp_option(uint32_t value, uint32_t reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for a timestamp option.
|
||||||
|
* \param value A pointer in which the option's value will be stored.
|
||||||
|
* \param reply A pointer in which the option's reply value will be stored.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_timestamp_option(uint32_t *value, uint32_t *reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add a alternate checksum option.
|
||||||
|
*
|
||||||
|
* \param value The new alternate checksum scale.
|
||||||
|
*/
|
||||||
|
void add_altchecksum_option(AltChecksums value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for a alternate checksum option.
|
||||||
|
* \param value A pointer in which the option's value will be stored.
|
||||||
|
* \return True if the option was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_altchecksum_option(uint8_t *value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set a TCP flag value.
|
* \brief Set a TCP flag value.
|
||||||
@@ -323,6 +404,13 @@ namespace Tins {
|
|||||||
*/
|
*/
|
||||||
PDUType pdu_type() const { return PDU::TCP; }
|
PDUType pdu_type() const { return PDU::TCP; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searchs for an option that matchs the given flag.
|
||||||
|
* \param opt_flag The flag to be searched.
|
||||||
|
* \return A pointer to the option, or 0 if it was not found.
|
||||||
|
*/
|
||||||
|
const TCPOption *search_option(Options opt) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Clones this PDU.
|
* \brief Clones this PDU.
|
||||||
*
|
*
|
||||||
@@ -369,6 +457,15 @@ namespace Tins {
|
|||||||
|
|
||||||
void copy_fields(const TCP *other);
|
void copy_fields(const TCP *other);
|
||||||
|
|
||||||
|
template<class T> bool generic_search(Options opt, T *value) {
|
||||||
|
const TCPOption *option = search_option(opt);
|
||||||
|
if(option && option->length == sizeof(T)) {
|
||||||
|
*value = *(T*)option->value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
/** \brief Serialices this TCP PDU.
|
/** \brief Serialices this TCP PDU.
|
||||||
* \param buffer The buffer in which the PDU will be serialized.
|
* \param buffer The buffer in which the PDU will be serialized.
|
||||||
|
|||||||
114
src/tcp.cpp
114
src/tcp.cpp
@@ -65,19 +65,17 @@ Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(Constants::IP::PR
|
|||||||
uint8_t args[2] = {0};
|
uint8_t args[2] = {0};
|
||||||
while(index < header_end) {
|
while(index < header_end) {
|
||||||
for(unsigned i(0); i < 2 && args[0] != NOP; ++i) {
|
for(unsigned i(0); i < 2 && args[0] != NOP; ++i) {
|
||||||
args[i] = buffer[index++];
|
|
||||||
if(index == header_end)
|
if(index == header_end)
|
||||||
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
|
throw std::runtime_error("Not enough size for a TCP header in the buffer.");
|
||||||
|
args[i] = buffer[index++];
|
||||||
}
|
}
|
||||||
// We don't want to store NOPs and EOLs
|
// We don't want to store NOPs and EOLs
|
||||||
if(args[0] != NOP && args[0] != EOL) {
|
if(args[0] != NOP && args[0] != EOL) {
|
||||||
args[1] -= (sizeof(uint8_t) << 1);
|
args[1] -= (sizeof(uint8_t) << 1);
|
||||||
if(args[1]) {
|
// Not enough size for this option
|
||||||
// Not enough size for this option
|
if(header_end - index < args[1])
|
||||||
if(header_end - index < args[1])
|
throw std::runtime_error("Not enough size for a TCP header in the buffer.");
|
||||||
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
|
add_option((Options)args[0], args[1], buffer + index);
|
||||||
add_option((Options)args[0], args[1], buffer + index);
|
|
||||||
}
|
|
||||||
index += args[1];
|
index += args[1];
|
||||||
}
|
}
|
||||||
else if(args[0] == EOL)
|
else if(args[0] == EOL)
|
||||||
@@ -103,7 +101,7 @@ Tins::TCP::~TCP() {
|
|||||||
|
|
||||||
void Tins::TCP::cleanup() {
|
void Tins::TCP::cleanup() {
|
||||||
for(std::list<TCPOption>::iterator it = _options.begin(); it != _options.end(); ++it)
|
for(std::list<TCPOption>::iterator it = _options.begin(); it != _options.end(); ++it)
|
||||||
delete[] it->data;
|
delete[] it->value;
|
||||||
_options.clear();
|
_options.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,16 +141,80 @@ void Tins::TCP::data_offset(uint8_t new_doff) {
|
|||||||
this->_tcp.doff = new_doff;
|
this->_tcp.doff = new_doff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tins::TCP::set_mss(uint16_t value) {
|
void Tins::TCP::add_mss_option(uint16_t value) {
|
||||||
value = Utils::net_to_host_s(value);
|
value = Utils::net_to_host_s(value);
|
||||||
add_option(MSS, 2, (uint8_t*)&value);
|
add_option(MSS, 2, (uint8_t*)&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tins::TCP::set_timestamp(uint32_t value, uint32_t reply) {
|
bool Tins::TCP::search_mss_option(uint16_t *value) {
|
||||||
|
if(!generic_search(MSS, value))
|
||||||
|
return false;
|
||||||
|
*value = Utils::net_to_host_s(*value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tins::TCP::add_winscale_option(uint8_t value) {
|
||||||
|
add_option(WSCALE, 1, &value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tins::TCP::search_winscale_option(uint8_t *value) {
|
||||||
|
return generic_search(WSCALE, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tins::TCP::add_sack_permitted_option() {
|
||||||
|
add_option(SACK_OK, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tins::TCP::search_sack_permitted_option() {
|
||||||
|
return search_option(SACK_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tins::TCP::add_sack_option(const std::list<uint32_t> &edges) {
|
||||||
|
uint32_t *value = 0;
|
||||||
|
if(edges.size()) {
|
||||||
|
value = new uint32_t[edges.size()];
|
||||||
|
uint32_t *ptr = value;
|
||||||
|
for(std::list<uint32_t>::const_iterator it = edges.begin(); it != edges.end(); ++it)
|
||||||
|
*(ptr++) = Utils::net_to_host_l(*it);
|
||||||
|
}
|
||||||
|
add_option(SACK, (uint8_t)(sizeof(uint32_t) * edges.size()), (const uint8_t*)value);
|
||||||
|
delete[] value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tins::TCP::search_sack_option(std::list<uint32_t> *edges) {
|
||||||
|
const TCPOption *option = search_option(SACK);
|
||||||
|
if(!option || (option->length % sizeof(uint32_t)) != 0)
|
||||||
|
return false;
|
||||||
|
const uint32_t *ptr = (const uint32_t*)option->value;
|
||||||
|
const uint32_t *end = ptr + (option->length / sizeof(uint32_t));
|
||||||
|
while(ptr < end)
|
||||||
|
edges->push_back(Utils::net_to_host_l(*(ptr++)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tins::TCP::add_timestamp_option(uint32_t value, uint32_t reply) {
|
||||||
uint64_t buffer = ((uint64_t)Utils::net_to_host_l(reply) << 32) | Utils::net_to_host_l(value);
|
uint64_t buffer = ((uint64_t)Utils::net_to_host_l(reply) << 32) | Utils::net_to_host_l(value);
|
||||||
add_option(TSOPT, 8, (uint8_t*)&buffer);
|
add_option(TSOPT, 8, (uint8_t*)&buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tins::TCP::search_timestamp_option(uint32_t *value, uint32_t *reply) {
|
||||||
|
const TCPOption *option = search_option(TSOPT);
|
||||||
|
if(!option || option->length != (sizeof(uint32_t) << 1))
|
||||||
|
return false;
|
||||||
|
const uint32_t *ptr = (const uint32_t*)option->value;
|
||||||
|
*value = Utils::net_to_host_l(*(ptr++));
|
||||||
|
*reply = Utils::net_to_host_l(*(ptr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tins::TCP::add_altchecksum_option(AltChecksums value) {
|
||||||
|
add_option(ALTCHK, 1, (const uint8_t*)&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tins::TCP::search_altchecksum_option(uint8_t *value) {
|
||||||
|
return generic_search(ALTCHK, value);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Tins::TCP::get_flag(Flags tcp_flag) {
|
uint8_t Tins::TCP::get_flag(Flags tcp_flag) {
|
||||||
switch(tcp_flag) {
|
switch(tcp_flag) {
|
||||||
case FIN:
|
case FIN:
|
||||||
@@ -239,8 +301,8 @@ void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
|
|||||||
buffer = it->write(buffer);
|
buffer = it->write(buffer);
|
||||||
|
|
||||||
if(_options_size < _total_options_size) {
|
if(_options_size < _total_options_size) {
|
||||||
uint8_t padding = _total_options_size;
|
uint8_t padding = _options_size;
|
||||||
while(padding < _options_size) {
|
while(padding < _total_options_size) {
|
||||||
*(buffer++) = 1;
|
*(buffer++) = 1;
|
||||||
padding++;
|
padding++;
|
||||||
}
|
}
|
||||||
@@ -258,19 +320,27 @@ void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
|
|||||||
_tcp.check = 0;
|
_tcp.check = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Tins::TCP::TCPOption *Tins::TCP::search_option(Options opt) const {
|
||||||
|
for(std::list<TCPOption>::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||||
|
if(it->option == opt)
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TCPOptions */
|
/* TCPOptions */
|
||||||
|
|
||||||
uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) {
|
uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) {
|
||||||
if(kind == 1) {
|
if(option == 1) {
|
||||||
*buffer = kind;
|
*buffer = option;
|
||||||
return buffer + 1;
|
return buffer + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buffer[0] = kind;
|
buffer[0] = option;
|
||||||
buffer[1] = length + (sizeof(uint8_t) << 1);
|
buffer[1] = length + (sizeof(uint8_t) << 1);
|
||||||
if(data)
|
if(value)
|
||||||
memcpy(buffer + 2, data, length);
|
memcpy(buffer + 2, value, length);
|
||||||
return buffer + buffer[1];
|
return buffer + buffer[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,10 +348,10 @@ uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) {
|
|||||||
void Tins::TCP::copy_fields(const TCP *other) {
|
void Tins::TCP::copy_fields(const TCP *other) {
|
||||||
std::memcpy(&_tcp, &other->_tcp, sizeof(_tcp));
|
std::memcpy(&_tcp, &other->_tcp, sizeof(_tcp));
|
||||||
for(std::list<TCPOption>::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) {
|
for(std::list<TCPOption>::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) {
|
||||||
TCPOption opt(it->kind, it->length);
|
TCPOption opt(it->option, it->length);
|
||||||
if(it->data) {
|
if(it->value) {
|
||||||
opt.data = new uint8_t[it->length];
|
opt.value = new uint8_t[it->length];
|
||||||
std::memcpy(opt.data, it->data, it->length);
|
std::memcpy(opt.value, it->value, it->length);
|
||||||
}
|
}
|
||||||
_options.push_back(opt);
|
_options.push_back(opt);
|
||||||
}
|
}
|
||||||
|
|||||||
213
tests/src/tcp.cpp
Normal file
213
tests/src/tcp.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "tcp.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Tins;
|
||||||
|
|
||||||
|
class TCPTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
static const uint8_t expected_packet[];
|
||||||
|
|
||||||
|
void test_equals(const TCP &tcp1, const TCP &tcp2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t TCPTest::expected_packet[] = {'\x7f', 'M', 'O', '\x1d', '\xf1', '\xda', '\xe5',
|
||||||
|
'F', '_', '\xae', '\xd1', '#', '\xd0', '\x02', 'q', '\xda', '\x00', '\x00', '\x1f', '\xae',
|
||||||
|
'\x02', '\x04', '\x98', '\xfa', '\x08', '\n', 'O', '\xd2', ':', '\xcb', '\x89', '\xfe',
|
||||||
|
'\x12', '4', '\x03', '\x03', 'z', '\x04', '\x02', '\x05', '\n', '\x00', '\x01', '\x02',
|
||||||
|
'\x03', '\x04', '\x05', '\x06', '\x07', '\x00', '\x00', '\x00'};
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TCPTest, DefaultConstructor) {
|
||||||
|
TCP tcp;
|
||||||
|
EXPECT_EQ(tcp.dport(), 0);
|
||||||
|
EXPECT_EQ(tcp.sport(), 0);
|
||||||
|
EXPECT_EQ(tcp.pdu_type(), PDU::TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, CopyConstructor) {
|
||||||
|
TCP tcp1(0x6d1f, 0x78f2);
|
||||||
|
TCP tcp2(tcp1);
|
||||||
|
test_equals(tcp1, tcp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, CompleteConstructor) {
|
||||||
|
TCP tcp(0x6d1f, 0x78f2);
|
||||||
|
EXPECT_EQ(tcp.dport(), 0x6d1f);
|
||||||
|
EXPECT_EQ(tcp.sport(), 0x78f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, DPort) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.dport(0x5fad);
|
||||||
|
EXPECT_EQ(tcp.dport(), 0x5fad);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, SPort) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.sport(0x5fad);
|
||||||
|
EXPECT_EQ(tcp.sport(), 0x5fad);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, Seq) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.seq(0x5fad65fb);
|
||||||
|
EXPECT_EQ(tcp.seq(), 0x5fad65fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, AckSeq) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.ack_seq(0x5fad65fb);
|
||||||
|
EXPECT_EQ(tcp.ack_seq(), 0x5fad65fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, Window) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.window(0x5fad);
|
||||||
|
EXPECT_EQ(tcp.window(), 0x5fad);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, Check) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.check(0x5fad);
|
||||||
|
EXPECT_EQ(tcp.check(), 0x5fad);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, UrgPtr) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.urg_ptr(0x5fad);
|
||||||
|
EXPECT_EQ(tcp.urg_ptr(), 0x5fad);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, DataOffset) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.data_offset(0xe);
|
||||||
|
EXPECT_EQ(tcp.data_offset(), 0xe);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, SetFlag) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.set_flag(TCP::SYN, 1);
|
||||||
|
tcp.set_flag(TCP::FIN, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::SYN), 1);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::FIN), 1);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::RST), 0);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::PSH), 0);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::ACK), 0);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::URG), 0);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::ECE), 0);
|
||||||
|
EXPECT_EQ(tcp.get_flag(TCP::CWR), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, MSS) {
|
||||||
|
TCP tcp;
|
||||||
|
uint16_t mss = 0x456f, found_mss;
|
||||||
|
tcp.add_mss_option(mss);
|
||||||
|
ASSERT_TRUE(tcp.search_mss_option(&found_mss));
|
||||||
|
EXPECT_EQ(mss, found_mss);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, WindowScale) {
|
||||||
|
TCP tcp;
|
||||||
|
uint8_t scale = 0x4f, found_scale;
|
||||||
|
tcp.add_winscale_option(scale);
|
||||||
|
ASSERT_TRUE(tcp.search_winscale_option(&found_scale));
|
||||||
|
EXPECT_EQ(scale, found_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, SackPermitted) {
|
||||||
|
TCP tcp;
|
||||||
|
tcp.add_sack_permitted_option();
|
||||||
|
ASSERT_TRUE(tcp.search_sack_permitted_option());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, Sack) {
|
||||||
|
TCP tcp;
|
||||||
|
list<uint32_t> edges, edges_found;
|
||||||
|
edges.push_back(0x13);
|
||||||
|
edges.push_back(0x63fa1d7a);
|
||||||
|
edges.push_back(0xff1c);
|
||||||
|
tcp.add_sack_option(edges);
|
||||||
|
ASSERT_TRUE(tcp.search_sack_option(&edges_found));
|
||||||
|
ASSERT_EQ(edges.size(), edges_found.size());
|
||||||
|
while(edges.size()) {
|
||||||
|
EXPECT_EQ(edges.front(), edges_found.front());
|
||||||
|
edges.pop_front();
|
||||||
|
edges_found.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, AlternateChecksum) {
|
||||||
|
TCP tcp;
|
||||||
|
uint8_t found;
|
||||||
|
tcp.add_altchecksum_option(TCP::CHK_16FLETCHER);
|
||||||
|
ASSERT_TRUE(tcp.search_altchecksum_option(&found));
|
||||||
|
EXPECT_EQ(found, (uint8_t)TCP::CHK_16FLETCHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, Timestamp) {
|
||||||
|
TCP tcp;
|
||||||
|
uint32_t value = 0x456fa23d, found_value;
|
||||||
|
uint32_t reply = 0xfa12d345, found_reply;
|
||||||
|
tcp.add_timestamp_option(value, reply);
|
||||||
|
ASSERT_TRUE(tcp.search_timestamp_option(&found_value, &found_reply));
|
||||||
|
EXPECT_EQ(value, found_value);
|
||||||
|
EXPECT_EQ(reply, found_reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCPTest::test_equals(const TCP &tcp1, const TCP &tcp2) {
|
||||||
|
EXPECT_EQ(tcp1.dport(), tcp2.dport());
|
||||||
|
EXPECT_EQ(tcp2.sport(), tcp2.sport());
|
||||||
|
EXPECT_EQ(tcp1.seq(), tcp2.seq());
|
||||||
|
EXPECT_EQ(tcp1.ack_seq(), tcp2.ack_seq());
|
||||||
|
EXPECT_EQ(tcp1.window(), tcp2.window());
|
||||||
|
EXPECT_EQ(tcp1.check(), tcp2.check());
|
||||||
|
EXPECT_EQ(tcp1.urg_ptr(), tcp2.urg_ptr());
|
||||||
|
EXPECT_EQ(tcp1.data_offset(), tcp2.data_offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, ConstructorFromBuffer) {
|
||||||
|
TCP tcp1(expected_packet, sizeof(expected_packet));
|
||||||
|
uint32_t value32, ovalue32;
|
||||||
|
uint16_t value16;
|
||||||
|
uint8_t value8;
|
||||||
|
|
||||||
|
EXPECT_EQ(tcp1.dport(), 0x4f1d);
|
||||||
|
EXPECT_EQ(tcp1.sport(), 0x7f4d);
|
||||||
|
EXPECT_EQ(tcp1.seq(), 0xf1dae546);
|
||||||
|
EXPECT_EQ(tcp1.ack_seq(), 0x5faed123);
|
||||||
|
EXPECT_EQ(tcp1.window(), 0x71da);
|
||||||
|
EXPECT_EQ(tcp1.urg_ptr(), 0x1fae);
|
||||||
|
EXPECT_EQ(tcp1.data_offset(), 0xd);
|
||||||
|
|
||||||
|
ASSERT_TRUE(tcp1.search_timestamp_option(&value32, &ovalue32));
|
||||||
|
EXPECT_EQ(value32, 0x4fd23acb);
|
||||||
|
EXPECT_EQ(ovalue32, 0x89fe1234);
|
||||||
|
|
||||||
|
EXPECT_TRUE(tcp1.search_sack_permitted_option());
|
||||||
|
|
||||||
|
ASSERT_TRUE(tcp1.search_winscale_option(&value8));
|
||||||
|
EXPECT_EQ(value8, 0x7a);
|
||||||
|
|
||||||
|
ASSERT_TRUE(tcp1.search_mss_option(&value16));
|
||||||
|
EXPECT_EQ(value16, 0x98fa);
|
||||||
|
|
||||||
|
list<uint32_t> edges;
|
||||||
|
ASSERT_TRUE(tcp1.search_sack_option(&edges));
|
||||||
|
ASSERT_EQ(edges.size(), 2);
|
||||||
|
EXPECT_EQ(edges.front(), 0x00010203); edges.pop_front();
|
||||||
|
EXPECT_EQ(edges.front(), 0x04050607);
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t *buffer = tcp1.serialize(size);
|
||||||
|
|
||||||
|
TCP tcp2(buffer, size);
|
||||||
|
test_equals(tcp1, tcp2);
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user