diff --git a/include/rawpdu.h b/include/rawpdu.h new file mode 100644 index 0000000..e1897fa --- /dev/null +++ b/include/rawpdu.h @@ -0,0 +1,54 @@ +/* + * libtins is a net packet wrapper library for crafting and + * interpreting sniffed packets. + * + * Copyright (C) 2011 Nasel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __RAWPDU_H +#define __RAWPDU_H + + +#include "pdu.h" + + +namespace Tins { + + /** \brief Represents a PDU which holds raw data. + * + * In order to send payloads over TCP, UDP, or other transport layer or + * higher level protocols, RawPDU can be used as a wrapper for raw byte arrays. + */ + class RawPDU : public PDU { + public: + RawPDU(uint8_t *payload, uint32_t size); + + /** \brief Returns the header size. + * + * This metod overrides PDU::header_size. \sa PDU::header_size + */ + uint32_t header_size() const; + private: + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); + + uint8_t *_payload; + uint32_t _payload_size; + }; +}; + + +#endif diff --git a/include/tcp.h b/include/tcp.h index 37607c1..b8e6f36 100644 --- a/include/tcp.h +++ b/include/tcp.h @@ -111,10 +111,6 @@ namespace Tins { */ inline uint16_t urg_ptr() const { return _tcp.urg_ptr; } - /** \brief Returns the payload. - */ - inline const uint8_t *payload() const { return _payload; } - /** \brief Set the destination port. * \param new_dport New destination port. */ @@ -153,7 +149,10 @@ namespace Tins { /** \brief Set the payload. * * Payload is NOT copied. Therefore, pointers provided as - * payloads must be freed manually by the user. + * payloads must be freed manually by the user. This actually + * creates a RawPDU that holds the payload, and sets it as the + * inner_pdu. Therefore, if an inner_pdu was set previously, + * a call to TCP::payload will delete it. * \param new_payload New payload. * \param new_payload_size New payload's size */ @@ -247,8 +246,7 @@ namespace Tins { tcphdr _tcp; std::vector _options; - uint8_t *_payload; - uint32_t _payload_size, _options_size, _total_options_size; + uint32_t _options_size, _total_options_size; }; }; diff --git a/include/udp.h b/include/udp.h index ba74263..03ef6f0 100644 --- a/include/udp.h +++ b/include/udp.h @@ -1,3 +1,24 @@ +/* + * libtins is a net packet wrapper library for crafting and + * interpreting sniffed packets. + * + * Copyright (C) 2011 Nasel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef __UDP_H #define __UDP_H @@ -22,11 +43,7 @@ namespace Tins { * */ UDP(uint16_t sport = 0, uint16_t dport = 0); - - /** \brief Returns the payload. - */ - inline const uint8_t *payload() const { return _payload; } - + /** \brief Returns the destination port */ inline uint16_t dport() const { return _udp.dport; } @@ -50,7 +67,10 @@ namespace Tins { /** \brief Set the payload. * * Payload is NOT copied. Therefore, pointers provided as - * payloads must be freed manually by the user. + * payloads must be freed manually by the user. This actually + * creates a RawPDU that holds the payload, and sets it as the + * inner_pdu. Therefore, if an inner_pdu was set previously, + * a call to UDP::payload will delete it. * \param new_payload New payload. * \param new_payload_size New payload's size */ @@ -74,8 +94,6 @@ namespace Tins { void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); udphdr _udp; - uint8_t *_payload; - uint32_t _payload_size; }; }; diff --git a/src/rawpdu.cpp b/src/rawpdu.cpp new file mode 100644 index 0000000..151094a --- /dev/null +++ b/src/rawpdu.cpp @@ -0,0 +1,40 @@ +/* + * libtins is a net packet wrapper library for crafting and + * interpreting sniffed packets. + * + * Copyright (C) 2011 Nasel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "rawpdu.h" +#include + + +Tins::RawPDU::RawPDU(uint8_t *payload, uint32_t size) : PDU(255), _payload(payload), _payload_size(size) { + +} + +uint32_t Tins::RawPDU::header_size() const { + return _payload_size; +} + +void Tins::RawPDU::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { + assert(total_sz >= _payload_size); + std::memcpy(buffer, _payload, _payload_size); +} + diff --git a/src/tcp.cpp b/src/tcp.cpp index 9555944..d806128 100644 --- a/src/tcp.cpp +++ b/src/tcp.cpp @@ -21,19 +21,18 @@ #include #include -#include //borrame #ifndef WIN32 #include #endif #include "tcp.h" #include "ip.h" +#include "rawpdu.h" #include "utils.h" const uint16_t Tins::TCP::DEFAULT_WINDOW = 32678; -Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP), _payload(0), _payload_size(0), - _options_size(0), _total_options_size(0) { +Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP), _options_size(0), _total_options_size(0) { std::memset(&_tcp, 0, sizeof(tcphdr)); _tcp.dport = Utils::net_to_host_s(dport); _tcp.sport = Utils::net_to_host_s(sport); @@ -76,8 +75,7 @@ void Tins::TCP::urg_ptr(uint16_t new_urg_ptr) { } void Tins::TCP::payload(uint8_t *new_payload, uint32_t new_payload_size) { - _payload = new_payload; - _payload_size = new_payload_size; + inner_pdu(new RawPDU(new_payload, new_payload_size)); } void Tins::TCP::set_mss(uint16_t value) { @@ -129,7 +127,7 @@ void Tins::TCP::add_option(Options tcp_option, uint8_t length, uint8_t *data) { } uint32_t Tins::TCP::header_size() const { - return sizeof(tcphdr) + _payload_size + _total_options_size; + return sizeof(tcphdr) + _total_options_size; } void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { @@ -148,14 +146,12 @@ void Tins::TCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD } } - memcpy(buffer, _payload, _payload_size); - buffer += _payload_size; const IP *ip_packet = dynamic_cast(parent); if(!_tcp.check && ip_packet) { - uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), header_size(), IPPROTO_TCP) + - PDU::do_checksum(tcp_start + sizeof(tcphdr), buffer) + PDU::do_checksum((uint8_t*)&_tcp, ((uint8_t*)&_tcp) + sizeof(tcphdr)); + uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), size(), IPPROTO_TCP) + + PDU::do_checksum(tcp_start + sizeof(tcphdr), tcp_start + total_sz) + PDU::do_checksum((uint8_t*)&_tcp, ((uint8_t*)&_tcp) + sizeof(tcphdr)); while (checksum >> 16) - checksum = (checksum & 0xffff)+(checksum >> 16); + checksum = (checksum & 0xffff) + (checksum >> 16); _tcp.check = Utils::net_to_host_s(~checksum); } memcpy(tcp_start, &_tcp, sizeof(tcphdr)); diff --git a/src/udp.cpp b/src/udp.cpp index 40535d0..0beb845 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -1,3 +1,24 @@ +/* + * libtins is a net packet wrapper library for crafting and + * interpreting sniffed packets. + * + * Copyright (C) 2011 Nasel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef WIN32 #include #endif @@ -6,8 +27,9 @@ #include "utils.h" #include "udp.h" #include "ip.h" +#include "rawpdu.h" -Tins::UDP::UDP(uint16_t sport, uint16_t dport) : PDU(IPPROTO_UDP), _payload(0), _payload_size(0) { +Tins::UDP::UDP(uint16_t sport, uint16_t dport) : PDU(IPPROTO_UDP) { _udp.sport = sport; _udp.dport = dport; _udp.check = 0; @@ -15,9 +37,8 @@ Tins::UDP::UDP(uint16_t sport, uint16_t dport) : PDU(IPPROTO_UDP), _payload(0), } void Tins::UDP::payload(uint8_t *new_payload, uint32_t new_payload_size) { - _payload = new_payload; - _payload_size = new_payload_size; - _udp.len = Utils::net_to_host_s(sizeof(udphdr) + _payload_size); + inner_pdu(new RawPDU(new_payload, new_payload_size)); + _udp.len = Utils::net_to_host_s(sizeof(udphdr) + new_payload_size); } void Tins::UDP::dport(uint16_t new_dport) { @@ -29,21 +50,19 @@ void Tins::UDP::sport(uint16_t new_sport) { } uint32_t Tins::UDP::header_size() const { - /* Round? */ - return sizeof(udphdr) + _payload_size; + return sizeof(udphdr); } void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { - assert(total_sz >= sizeof(udphdr) + _payload_size); + assert(total_sz >= sizeof(udphdr)); const IP *ip_packet = dynamic_cast(parent); if(!_udp.check && ip_packet) { - uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), header_size(), IPPROTO_UDP) + - PDU::do_checksum(_payload, _payload + _payload_size) + PDU::do_checksum((uint8_t*)&_udp, ((uint8_t*)&_udp) + sizeof(udphdr)); + uint32_t checksum = PDU::pseudoheader_checksum(ip_packet->source_address(), ip_packet->dest_address(), size(), IPPROTO_UDP) + + PDU::do_checksum(buffer + sizeof(udphdr), buffer + total_sz) + PDU::do_checksum((uint8_t*)&_udp, ((uint8_t*)&_udp) + sizeof(udphdr)); while (checksum >> 16) checksum = (checksum & 0xffff)+(checksum >> 16); _udp.check = Utils::net_to_host_s(~checksum); } std::memcpy(buffer, &_udp, sizeof(udphdr)); - std::memcpy(buffer + sizeof(udphdr), _payload, _payload_size); }