diff --git a/include/tcp.h b/include/tcp.h index d023ce4..149ab70 100644 --- a/include/tcp.h +++ b/include/tcp.h @@ -24,6 +24,7 @@ #include +#include #include #ifndef WIN32 #include @@ -95,8 +96,10 @@ namespace Tins { * \param olength The option's data length. * \param odata The option's data(if any). */ - TCPOption(uint8_t opt = 0, uint8_t olength = 0, uint8_t *ovalue = 0) : - option(opt), length(olength), value(ovalue) { } + TCPOption(uint8_t opt = 0, uint8_t length = 0, const uint8_t *value = 0) + : option(opt), value(value, (value) ? (value + length) : 0) { + + } /** * \brief Writes the option into a buffer. @@ -105,8 +108,8 @@ namespace Tins { */ uint8_t *write(uint8_t *buffer); - uint8_t option, length; - uint8_t *value; + uint8_t option; + std::vector value; }; /** @@ -120,30 +123,14 @@ namespace Tins { TCP(uint16_t dport = 0, uint16_t sport = 0); /** - * \brief Constructor which creates an TCP object from a buffer and adds all identifiable - * PDUs found in the buffer as children of this one. + * \brief Constructor which creates an TCP object from a buffer + * and adds all identifiable PDUs found in the buffer as children + * of this one. * \param buffer The buffer from which this PDU will be constructed. * \param total_sz The total size of the buffer. */ TCP(const uint8_t *buffer, uint32_t total_sz); - /** - * \brief Copy constructor. - */ - TCP(const TCP &other); - - /** - * \brief Copy assignment operator. - */ - TCP &operator= (const TCP &other); - - /** - * \brief TCP destructor. - * - * Destructs the TCP instance. Does not free the payload. - * */ - ~TCP(); - /** * \brief Getter for the destination port field. * @@ -459,14 +446,12 @@ namespace Tins { template bool generic_search(Option opt, T *value) { const TCPOption *option = search_option(opt); - if(option && option->length == sizeof(T)) { - *value = *(T*)option->value; + if(option && option->value.size() == sizeof(T)) { + *value = *(const T*)(&option->value[0]); return true; } return false; } - - void cleanup(); /** \brief Serialices this TCP PDU. * \param buffer The buffer in which the PDU will be serialized. * \param total_sz The size available in the buffer. diff --git a/src/tcp.cpp b/src/tcp.cpp index cc2019d..ea7212e 100644 --- a/src/tcp.cpp +++ b/src/tcp.cpp @@ -20,7 +20,6 @@ */ #include -#include //borrame #include #include #include "tcp.h" @@ -40,84 +39,50 @@ Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(Constants::IP::PROTO_TCP), window(DEFAULT_WINDOW); } -Tins::TCP::TCP(const TCP &other) : PDU(other) { - copy_fields(&other); -} - -Tins::TCP &Tins::TCP::operator= (const TCP &other) { - PDU::operator=(other); - copy_fields(&other); - return *this; -} - Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(Constants::IP::PROTO_TCP) { if(total_sz < sizeof(tcphdr)) throw std::runtime_error("Not enough size for an TCP header in the buffer."); std::memcpy(&_tcp, buffer, sizeof(tcphdr)); - try { - buffer += sizeof(tcphdr); - total_sz -= sizeof(tcphdr); - - _total_options_size = 0; - _options_size = 0; - - uint32_t index = 0, header_end = (data_offset() * sizeof(uint32_t)) - sizeof(tcphdr); - if(total_sz >= header_end) { - uint8_t args[2] = {0}; - while(index < header_end) { - for(unsigned i(0); i < 2; ++i) { - if(index == header_end) - throw std::runtime_error("Not enough size for a TCP header in the buffer."); - args[i] = buffer[index++]; - // NOP and EOL contain no length field - if(args[0] == NOP || args[0] == EOL) - break; - } - // We don't want to store NOPs and EOLs - if(args[0] != NOP && args[0] != EOL) { - // Not enough size for this option - args[1] -= (sizeof(uint8_t) << 1); - if(header_end - index < args[1]) - throw std::runtime_error("Not enough size for a TCP header in the buffer."); - if(args[1]) - add_option((Option)args[0], args[1], buffer + index); - else - add_option((Option)args[0], args[1], 0); - index += args[1]; - } - else - add_option((Option)args[0], 0, 0); - /*else if(args[0] == EOL) - //index = header_end; - add_option(EOL, 0, 0); - else { - add_option((Option)args[0], 0, 0); - // Skip the NOP - args[0] = 0; - }*/ + buffer += sizeof(tcphdr); + total_sz -= sizeof(tcphdr); + + _total_options_size = 0; + _options_size = 0; + + uint32_t index = 0, header_end = (data_offset() * sizeof(uint32_t)) - sizeof(tcphdr); + if(total_sz >= header_end) { + uint8_t args[2] = {0}; + while(index < header_end) { + for(unsigned i(0); i < 2; ++i) { + if(index == header_end) + throw std::runtime_error("Not enough size for a TCP header in the buffer."); + args[i] = buffer[index++]; + // NOP and EOL contain no length field + if(args[0] == NOP || args[0] == EOL) + break; } - buffer += index; - total_sz -= index; + // We don't want to store NOPs and EOLs + if(args[0] != NOP && args[0] != EOL) { + // Not enough size for this option + args[1] -= (sizeof(uint8_t) << 1); + if(header_end - index < args[1]) + throw std::runtime_error("Not enough size for a TCP header in the buffer."); + if(args[1]) + add_option((Option)args[0], args[1], buffer + index); + else + add_option((Option)args[0], args[1], 0); + index += args[1]; + } + else + add_option((Option)args[0], 0, 0); } - } - catch(std::runtime_error &err) { - cleanup(); - throw; + buffer += index; + total_sz -= index; } if(total_sz) inner_pdu(new RawPDU(buffer, total_sz)); } -Tins::TCP::~TCP() { - cleanup(); -} - -void Tins::TCP::cleanup() { - for(std::list::iterator it = _options.begin(); it != _options.end(); ++it) - delete[] it->value; - _options.clear(); -} - void Tins::TCP::dport(uint16_t new_dport) { _tcp.dport = Utils::net_to_host_s(new_dport); } @@ -196,10 +161,10 @@ void Tins::TCP::add_sack_option(const std::list &edges) { bool Tins::TCP::search_sack_option(std::list *edges) { const TCPOption *option = search_option(SACK); - if(!option || (option->length % sizeof(uint32_t)) != 0) + if(!option || (option->value.size() % 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)); + const uint32_t *ptr = (const uint32_t*)&option->value[0]; + const uint32_t *end = ptr + (option->value.size() / sizeof(uint32_t)); while(ptr < end) edges->push_back(Utils::net_to_host_l(*(ptr++))); return true; @@ -212,9 +177,9 @@ void Tins::TCP::add_timestamp_option(uint32_t value, uint32_t reply) { 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)) + if(!option || option->value.size() != (sizeof(uint32_t) << 1)) return false; - const uint32_t *ptr = (const uint32_t*)option->value; + const uint32_t *ptr = (const uint32_t*)&option->value[0]; *value = Utils::net_to_host_l(*(ptr++)); *reply = Utils::net_to_host_l(*(ptr)); return true; @@ -290,12 +255,8 @@ void Tins::TCP::set_flag(Flags tcp_flag, uint8_t value) { } void Tins::TCP::add_option(Option tcp_option, uint8_t length, const uint8_t *data) { - uint8_t *new_data = 0, padding; - if(data && length) { - new_data = new uint8_t[length]; - memcpy(new_data, data, length); - } - _options.push_back(TCPOption(tcp_option, length, new_data)); + uint8_t padding; + _options.push_back(TCPOption(tcp_option, length, data)); _options_size += sizeof(uint8_t); // SACK_OK contains length but not data.... @@ -358,23 +319,16 @@ uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) { } else { buffer[0] = option; - buffer[1] = length + (sizeof(uint8_t) << 1); - if(value) - memcpy(buffer + 2, value, length); + buffer[1] = value.size() + (sizeof(uint8_t) << 1); + if(!value.empty()) + std::copy(value.begin(), value.end(), buffer + 2); return buffer + buffer[1]; } } void Tins::TCP::copy_fields(const TCP *other) { std::memcpy(&_tcp, &other->_tcp, sizeof(_tcp)); - for(std::list::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) { - TCPOption opt(it->option, it->length); - if(it->value) { - opt.value = new uint8_t[it->length]; - std::memcpy(opt.value, it->value, it->length); - } - _options.push_back(opt); - } + _options = other->_options; _options_size = other->_options_size; _total_options_size = other->_total_options_size; } diff --git a/tests/src/tcp.cpp b/tests/src/tcp.cpp index af4a6c8..07cae51 100644 --- a/tests/src/tcp.cpp +++ b/tests/src/tcp.cpp @@ -36,6 +36,12 @@ TEST_F(TCPTest, CopyConstructor) { test_equals(tcp1, tcp2); } +TEST_F(TCPTest, CopyAssignmentOperator) { + TCP tcp1(0x6d1f, 0x78f2); + TCP tcp2 = tcp1; + test_equals(tcp1, tcp2); +} + TEST_F(TCPTest, CompleteConstructor) { TCP tcp(0x6d1f, 0x78f2); EXPECT_EQ(tcp.dport(), 0x6d1f);