mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Fixed memory leak on TCP's options.
This commit is contained in:
@@ -368,6 +368,8 @@ namespace Tins {
|
||||
static const uint16_t DEFAULT_WINDOW;
|
||||
|
||||
void copy_fields(const TCP *other);
|
||||
|
||||
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.
|
||||
|
||||
74
src/tcp.cpp
74
src/tcp.cpp
@@ -56,48 +56,58 @@ Tins::TCP::TCP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_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));
|
||||
|
||||
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 && args[0] != NOP; ++i) {
|
||||
args[i] = buffer[index++];
|
||||
if(index == header_end)
|
||||
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
|
||||
}
|
||||
// We don't want to store NOPs and EOLs
|
||||
if(args[0] != NOP && args[0] != EOL) {
|
||||
args[1] -= (sizeof(uint8_t) << 1);
|
||||
if(args[1]) {
|
||||
// Not enough size for this option
|
||||
if(header_end - index < args[1])
|
||||
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 && args[0] != NOP; ++i) {
|
||||
args[i] = buffer[index++];
|
||||
if(index == header_end)
|
||||
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
|
||||
add_option((Options)args[0], args[1], buffer + index);
|
||||
}
|
||||
index += args[1];
|
||||
// We don't want to store NOPs and EOLs
|
||||
if(args[0] != NOP && args[0] != EOL) {
|
||||
args[1] -= (sizeof(uint8_t) << 1);
|
||||
if(args[1]) {
|
||||
// Not enough size for this option
|
||||
if(header_end - index < args[1])
|
||||
throw std::runtime_error("Not enought size for a TCP header in the buffer.");
|
||||
add_option((Options)args[0], args[1], buffer + index);
|
||||
}
|
||||
index += args[1];
|
||||
}
|
||||
else if(args[0] == EOL)
|
||||
index = header_end;
|
||||
else // Skip the NOP
|
||||
args[0] = 0;
|
||||
}
|
||||
else if(args[0] == EOL)
|
||||
index = header_end;
|
||||
else // Skip the NOP
|
||||
args[0] = 0;
|
||||
buffer += index;
|
||||
total_sz -= index;
|
||||
}
|
||||
buffer += index;
|
||||
total_sz -= index;
|
||||
}
|
||||
catch(std::runtime_error &err) {
|
||||
cleanup();
|
||||
throw;
|
||||
}
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer, total_sz));
|
||||
}
|
||||
|
||||
Tins::TCP::~TCP() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void Tins::TCP::cleanup() {
|
||||
for(std::list<TCPOption>::iterator it = _options.begin(); it != _options.end(); ++it)
|
||||
delete[] it->data;
|
||||
_options.clear();
|
||||
}
|
||||
|
||||
void Tins::TCP::dport(uint16_t new_dport) {
|
||||
@@ -242,8 +252,8 @@ void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD
|
||||
const Tins::IP *ip_packet = dynamic_cast<const Tins::IP*>(parent);
|
||||
memcpy(tcp_start, &_tcp, sizeof(tcphdr));
|
||||
if(!_tcp.check && ip_packet) {
|
||||
uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_TCP) +
|
||||
PDU::do_checksum(tcp_start, tcp_start + total_sz);
|
||||
uint32_t checksum = Utils::pseudoheader_checksum(ip_packet->src_addr(), ip_packet->dst_addr(), size(), IPPROTO_TCP) +
|
||||
Utils::do_checksum(tcp_start, tcp_start + total_sz);
|
||||
while (checksum >> 16)
|
||||
checksum = (checksum & 0xffff) + (checksum >> 16);
|
||||
((tcphdr*)tcp_start)->check = Utils::net_to_host_s(~checksum);
|
||||
|
||||
Reference in New Issue
Block a user