diff --git a/include/arp.h b/include/arp.h index 9a27dfc..50d8d7d 100644 --- a/include/arp.h +++ b/include/arp.h @@ -59,7 +59,17 @@ namespace Tins { * \param total_sz The total size of the buffer. */ ARP(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Copy constructor. + */ + ARP(const ARP &other); + /** + * \brief Copy asignment operator. + */ + ARP &operator= (const ARP &other); + /* Getters */ /** * \brief Getter for the sender's hardware address. @@ -315,6 +325,12 @@ namespace Tins { */ PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz); + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct arphdr { uint16_t ar_hrd; /* format of hardware address */ @@ -335,6 +351,7 @@ namespace Tins { */ ARP(const arphdr *arp_ptr); + void copy_fields(const ARP *other); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); arphdr _arp; diff --git a/include/bootp.h b/include/bootp.h index 30cad84..6e84329 100644 --- a/include/bootp.h +++ b/include/bootp.h @@ -63,6 +63,16 @@ namespace Tins { */ BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64); + /** + * \brief Copy constructor. + */ + BootP(const BootP &other); + + /** + * \brief Copy assignment operator. + */ + BootP &operator= (const BootP &other); + /** \brief BootP destructor. * * This frees the memory allocated to hold the vend field. @@ -232,7 +242,21 @@ namespace Tins { * \param size The size of the new vend field. */ void vend(uint8_t *new_vend, uint32_t size); + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::BOOTP; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; protected: + void copy_bootp_fields(const BootP *other); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); private: /** @@ -255,7 +279,6 @@ namespace Tins { uint8_t file[128]; } __attribute__((__packed__)); - bootphdr _bootp; uint8_t *_vend; uint32_t _vend_size; diff --git a/include/dhcp.h b/include/dhcp.h index dfda95b..8e23ddf 100644 --- a/include/dhcp.h +++ b/include/dhcp.h @@ -172,7 +172,17 @@ namespace Tins { * Subclasses might use 0 to provide their own interpretation of this field. */ DHCP(const uint8_t *buffer, uint32_t total_sz); - + + /** + * \brief Copy constructor. + */ + DHCP(const DHCP &other); + + /** + * \brief Copy assignment operator. + */ + DHCP &operator= (const DHCP &other); + /** * \brief DHCP destructor * @@ -265,9 +275,17 @@ namespace Tins { * \sa PDU::header_size */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: static const uint32_t MAX_DHCP_SIZE; - + + void copy_fields(const DHCP *other); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); uint8_t *serialize_list(const std::list &int_list, uint32_t &sz); diff --git a/include/eapol.h b/include/eapol.h index 377674c..e7a32da 100644 --- a/include/eapol.h +++ b/include/eapol.h @@ -117,6 +117,11 @@ namespace Tins { */ EAPOL(uint8_t packet_type, EAPOLTYPE type); + /** + * \brief Copy constructor. + */ + EAPOL(const EAPOL &other); + /** * \brief Constructor which creates an EAPOL object from a buffer. * \param buffer The buffer from which this PDU will be constructed. @@ -124,6 +129,8 @@ namespace Tins { */ EAPOL(const uint8_t *buffer, uint32_t total_sz); + void copy_eapol_fields(const EAPOL *other); + struct eapolhdr { uint8_t version, packet_type; uint16_t length; @@ -169,6 +176,16 @@ namespace Tins { */ RC4EAPOL(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + RC4EAPOL(const RC4EAPOL &other); + + /** + * \brief Copy assignment operator. + */ + RC4EAPOL &operator= (const RC4EAPOL &other); + /** * \brief RC4EAPOL destructor * @@ -275,6 +292,13 @@ namespace Tins { * \sa PDU::header_size */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct rc4hdr { uint16_t key_length; @@ -285,6 +309,7 @@ namespace Tins { uint8_t key_sign[16]; } __attribute__((__packed__)); + void copy_fields(const RC4EAPOL *other); void write_body(uint8_t *buffer, uint32_t total_sz); @@ -311,6 +336,16 @@ namespace Tins { */ RSNEAPOL(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + RSNEAPOL(const RSNEAPOL &other); + + /** + * \brief Copy assignment operator. + */ + RSNEAPOL &operator= (const RSNEAPOL &other); + /** * \brief Destructor. * @@ -455,6 +490,13 @@ namespace Tins { * \sa RSNInformation. */ void rsn_information(const RSNInformation &rsn); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct rsnhdr { uint16_t key_mic:1, @@ -476,6 +518,8 @@ namespace Tins { uint16_t wpa_length; } __attribute__((__packed__)); + + void copy_fields(const RSNEAPOL *other); void write_body(uint8_t *buffer, uint32_t total_sz); diff --git a/include/icmp.h b/include/icmp.h index 28b30a8..5ee7d56 100644 --- a/include/icmp.h +++ b/include/icmp.h @@ -56,6 +56,16 @@ namespace Tins { * \param flag The type flag which will be set. */ ICMP(Flags flag = ECHO_REQUEST); + + /** + * \brief Copy constructor. + */ + ICMP(const ICMP &other); + + /** + * \brief Copy assignment operator. + */ + ICMP &operator= (const ICMP &other); /** * \brief Constructor which creates an ICMP object from a buffer and adds all identifiable @@ -282,6 +292,13 @@ namespace Tins { * \sa PDU::clone_packet */ PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: static uint16_t global_id, global_seq; @@ -308,6 +325,8 @@ namespace Tins { */ ICMP(const icmphdr *ptr); + void copy_fields(const ICMP *other); + /** \brief Serialices this ICMP PDU. * \param buffer The buffer in which the PDU will be serialized. * \param total_sz The size available in the buffer. diff --git a/include/ieee802-11.h b/include/ieee802-11.h index dcdd6de..a813af8 100644 --- a/include/ieee802-11.h +++ b/include/ieee802-11.h @@ -36,9 +36,7 @@ namespace Tins { * \brief Class representing an 802.11 frame. */ class IEEE802_11 : public PDU { - public: - /** * \brief Broadcast hardware address. */ @@ -217,6 +215,11 @@ namespace Tins { * \param total_sz The total size of the buffer. */ IEEE802_11(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Copy constructor. + */ + IEEE802_11(const IEEE802_11 &other); /** * \brief IEEE802_11 destructor. @@ -225,6 +228,11 @@ namespace Tins { */ ~IEEE802_11(); + /** + * \brief Copy assignment operator. + */ + IEEE802_11 &operator= (const IEEE802_11 &other); + /** * \brief Getter for the protocol version. * @@ -531,6 +539,7 @@ namespace Tins { protected: virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; } void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz); + void copy_80211_fields(const IEEE802_11 *other); protected: /** * Struct that represents the 802.11 header @@ -995,6 +1004,7 @@ namespace Tins { ManagementFrame(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0); ManagementFrame(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr) throw (std::runtime_error); ManagementFrame(const uint8_t *buffer, uint32_t total_sz); + ManagementFrame(const ManagementFrame &other); void ssid(const std::string &new_ssid); void rates(const std::list &new_rates); @@ -1050,6 +1060,16 @@ namespace Tins { */ IEEE802_11_Beacon(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + IEEE802_11_Beacon(const IEEE802_11_Beacon &other); + + /** + * \brief Copy assignment operator. + */ + IEEE802_11_Beacon &operator= (const IEEE802_11_Beacon &other); + /** * \brief Getter for the timestamp field. * @@ -1148,10 +1168,11 @@ namespace Tins { CapabilityInformation capability; } __attribute__((__packed__)); - BeaconBody _body; - + void copy_fields(const IEEE802_11_Beacon *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); - + + + BeaconBody _body; }; /** @@ -1180,6 +1201,16 @@ namespace Tins { */ IEEE802_11_Disassoc(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0) throw (std::runtime_error); + /** + * \brief Copy constructor. + */ + IEEE802_11_Disassoc(const IEEE802_11_Disassoc &other); + + /** + * \brief Copy assignment operator. + */ + IEEE802_11_Disassoc &operator= (const IEEE802_11_Disassoc &other); + /** * \brief Getter for the reason code. * @@ -1206,6 +1237,7 @@ namespace Tins { uint16_t reason_code; }; + void copy_fields(const IEEE802_11_Disassoc *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); @@ -1247,6 +1279,16 @@ namespace Tins { */ IEEE802_11_Assoc_Request(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + IEEE802_11_Assoc_Request(const IEEE802_11_Assoc_Request &other); + + /** + * \brief Copy assignment operator. + */ + IEEE802_11_Assoc_Request &operator= (const IEEE802_11_Assoc_Request &other); + /** * \brief Getter for the Capabilities Information. * @@ -1338,6 +1380,7 @@ namespace Tins { uint16_t listen_interval; }; + void copy_fields(const IEEE802_11_Assoc_Request *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); AssocReqBody _body; @@ -1378,6 +1421,16 @@ namespace Tins { */ IEEE802_11_Assoc_Response(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + IEEE802_11_Assoc_Response(const IEEE802_11_Assoc_Response &other); + + /** + * \brief Copy assignment operator + */ + IEEE802_11_Assoc_Response &operator= (const IEEE802_11_Assoc_Response &other); + /** * \brief Getter for the Capabilities Information. * @@ -1458,6 +1511,7 @@ namespace Tins { uint16_t aid; }; + void copy_fields(const IEEE802_11_Assoc_Response *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); AssocRespBody _body; @@ -1512,6 +1566,16 @@ namespace Tins { */ IEEE802_11_QoS_Data(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + IEEE802_11_QoS_Data(const IEEE802_11_QoS_Data &other); + + /** + * \brief Copy assignment operator. + */ + IEEE802_11_QoS_Data &operator= (const IEEE802_11_QoS_Data &other); + /** * \brief Getter for the qos_control field. * @@ -1533,13 +1597,12 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; - private: - - uint16_t _qos_control; - + void copy_fields(const IEEE802_11_QoS_Data *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); + + uint16_t _qos_control; }; } diff --git a/include/pdu.h b/include/pdu.h index 3ffccca..b594363 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -60,6 +60,7 @@ namespace Tins { TCP, UDP, ICMP, + BOOTP, DHCP, EAPOL }; @@ -214,6 +215,18 @@ namespace Tins { */ virtual PDU *clone_packet(const uint8_t *ptr, uint32_t total_sz) { return 0; } protected: + /** + * \brief Copy consstructor. + */ + PDU(const PDU &other); + + /** + * \brief Copy other PDU's inner PDU(if any). + * \param pdu The PDU from which to copy the inner PDU. + */ + void copy_inner_pdu(const PDU &pdu); + + /** \brief Serializes this PDU and propagates this action to child PDUs. * * \param buffer The buffer in which to store this PDU's serialization. diff --git a/include/snap.h b/include/snap.h index 7c394be..d58ca36 100644 --- a/include/snap.h +++ b/include/snap.h @@ -49,6 +49,16 @@ namespace Tins { */ SNAP(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Copy constructor. + */ + SNAP(const SNAP &other); + + /** + * \brief Copy assignment operator. + */ + SNAP &operator= (const SNAP &other); + /** * \brief Returns the SNAP frame's header length. * @@ -62,6 +72,13 @@ namespace Tins { * \sa PDU::pdu_type */ PDUType pdu_type() const { return PDU::SNAP; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct snaphdr { uint8_t dsap; @@ -74,6 +91,7 @@ namespace Tins { uint16_t eth_type; } __attribute__((__packed__)); + void copy_fields(const SNAP *other); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); snaphdr _snap; diff --git a/include/tcp.h b/include/tcp.h index 16e8f39..99cd572 100644 --- a/include/tcp.h +++ b/include/tcp.h @@ -82,7 +82,7 @@ namespace Tins { * \param olength The option's data length. * \param odata The option's data(if any). */ - TCPOption(uint8_t okind, uint8_t olength, uint8_t *odata) : + TCPOption(uint8_t okind = 0, uint8_t olength = 0, uint8_t *odata = 0) : kind(okind), length(olength), data(odata) { } /** @@ -114,6 +114,16 @@ namespace Tins { */ 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. * @@ -313,6 +323,12 @@ namespace Tins { */ PDUType pdu_type() const { return PDU::TCP; } + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct tcphdr { uint16_t sport; @@ -351,6 +367,7 @@ namespace Tins { static const uint16_t DEFAULT_WINDOW; + void copy_fields(const TCP *other); /** \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/include/udp.h b/include/udp.h index 82d2405..ae7fbc9 100644 --- a/include/udp.h +++ b/include/udp.h @@ -52,7 +52,17 @@ namespace Tins { * \param total_sz The total size of the buffer. */ UDP(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Copy constructor. + */ + UDP(const UDP &other); + /** + * \brief Copy assignment operator. + */ + UDP &operator= (const UDP& other); + /** * \brief Getter for the destination port. * \return The datagram's destination port. @@ -113,6 +123,13 @@ namespace Tins { * \sa PDU::pdu_type */ PDUType pdu_type() const { return PDU::UDP; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct udphdr { uint16_t sport; @@ -121,6 +138,7 @@ namespace Tins { uint16_t check; } __attribute__((packed)); + void copy_fields(const UDP *other); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); udphdr _udp; diff --git a/src/arp.cpp b/src/arp.cpp index 6e01902..0a71b13 100644 --- a/src/arp.cpp +++ b/src/arp.cpp @@ -55,6 +55,16 @@ Tins::ARP::ARP(const uint8_t *buffer, uint32_t total_sz) : PDU(0x0608) { inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz)); } +Tins::ARP::ARP(const ARP &other) : PDU(other) { + copy_fields(&other); +} + +Tins::ARP &Tins::ARP::operator= (const ARP &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::ARP::ARP(const arphdr *arp_ptr) : PDU(Utils::net_to_host_s(0x0806)) { memcpy(&_arp, arp_ptr, sizeof(arphdr)); } @@ -207,3 +217,13 @@ Tins::PDU* Tins::ARP::make_arp_reply(const string& iface, EthernetII* eth = new EthernetII(iface, hw_tgt, hw_snd, arp); return eth; } + +Tins::PDU *Tins::ARP::clone_pdu() const { + ARP *new_pdu = new ARP(); + new_pdu->copy_fields(this); + return new_pdu; +} + +void Tins::ARP::copy_fields(const ARP *other) { + std::memcpy(&_arp, &other->_arp, sizeof(_arp)); +} diff --git a/src/bootp.cpp b/src/bootp.cpp index 9b5105f..8574927 100644 --- a/src/bootp.cpp +++ b/src/bootp.cpp @@ -24,6 +24,16 @@ Tins::BootP::BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field // Maybe RawPDU on what is left on the buffer?... } +Tins::BootP::BootP(const BootP &other) : PDU(other) { + copy_bootp_fields(&other); +} + +Tins::BootP &Tins::BootP::operator= (const BootP &other) { + copy_bootp_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::BootP::~BootP() { delete[] _vend; } @@ -100,3 +110,18 @@ void Tins::BootP::write_serialization(uint8_t *buffer, uint32_t total_sz, const std::memcpy(buffer, &_bootp, sizeof(bootphdr)); std::memcpy(buffer + sizeof(bootphdr), _vend, _vend_size); } + +void Tins::BootP::copy_bootp_fields(const BootP *other) { + std::memcpy(&_bootp, &other->_bootp, sizeof(_bootp)); + _vend_size = other->_vend_size; + if(_vend_size) { + _vend = new uint8_t[_vend_size]; + std::memcpy(_vend, other->_vend, _vend_size); + } +} + +Tins::PDU *Tins::BootP::clone_pdu() const { + BootP *new_pdu = new BootP(); + new_pdu->copy_bootp_fields(this); + return new_pdu; +} diff --git a/src/dhcp.cpp b/src/dhcp.cpp index 47f2215..770fd31 100644 --- a/src/dhcp.cpp +++ b/src/dhcp.cpp @@ -63,6 +63,16 @@ Tins::DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz) : BootP(buffer, total } } +Tins::DHCP::DHCP(const DHCP &other) : BootP(other) { + copy_fields(&other); +} + +Tins::DHCP &Tins::DHCP::operator= (const DHCP &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::DHCP::~DHCP() { while(_options.size()) { delete[] _options.front().value; @@ -71,8 +81,12 @@ Tins::DHCP::~DHCP() { } Tins::DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, const uint8_t *val) : option(opt), length(len) { - value = new uint8_t[len]; - std::memcpy(value, val, len); + if(len) { + value = new uint8_t[len]; + std::memcpy(value, val, len); + } + else + value = 0; } bool Tins::DHCP::add_option(Options opt, uint8_t len, const uint8_t *val) { @@ -149,7 +163,8 @@ void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) { *(ptr++) = it->option; *(ptr++) = it->length; - std::memcpy(ptr, it->value, it->length); + if(it->length) + std::memcpy(ptr, it->value, it->length); ptr += it->length; } // End of options @@ -160,3 +175,15 @@ void Tins::DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P delete[] result; } +void Tins::DHCP::copy_fields(const DHCP *other) { + BootP::copy_bootp_fields(other); + _size = other->_size; + for(std::list::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) + _options.push_back(DHCPOption(it->option, it->length, it->value)); +} + +Tins::PDU *Tins::DHCP::clone_pdu() const { + DHCP *new_pdu = new DHCP(); + new_pdu->copy_fields(this); + return new_pdu; +} diff --git a/src/eapol.cpp b/src/eapol.cpp index 8ef9bab..6cc942d 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -39,6 +39,10 @@ Tins::EAPOL::EAPOL(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { std::memcpy(&_header, buffer, sizeof(_header)); } +Tins::EAPOL::EAPOL(const EAPOL &other) : PDU(other) { + copy_eapol_fields(&other); +} + Tins::EAPOL *Tins::EAPOL::from_bytes(const uint8_t *buffer, uint32_t total_sz) { if(total_sz < sizeof(eapolhdr)) throw std::runtime_error("Not enough size for an EAPOL header in the buffer."); @@ -80,6 +84,11 @@ void Tins::EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const write_body(buffer + sizeof(_header), total_sz - sizeof(_header)); } +void Tins::EAPOL::copy_eapol_fields(const EAPOL *other) { + std::memcpy(&_header, &other->_header, sizeof(_header)); + +} + /* RC4EAPOL */ Tins::RC4EAPOL::RC4EAPOL() : EAPOL(0x03, RC4), _key(0), _key_size(0) { @@ -103,6 +112,16 @@ Tins::RC4EAPOL::RC4EAPOL(const uint8_t *buffer, uint32_t total_sz) : EAPOL(buffe _key = 0; } +Tins::RC4EAPOL::RC4EAPOL(const RC4EAPOL &other) : EAPOL(other) { + copy_fields(&other); +} + +Tins::RC4EAPOL &Tins::RC4EAPOL::operator= (const RC4EAPOL &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::RC4EAPOL::~RC4EAPOL() { delete[] _key; } @@ -153,6 +172,23 @@ void Tins::RC4EAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { std::memcpy(buffer, _key, _key_size); } +Tins::PDU *Tins::RC4EAPOL::clone_pdu() const { + RC4EAPOL *new_pdu = new RC4EAPOL(); + new_pdu->copy_fields(this); + return new_pdu; +} + +void Tins::RC4EAPOL::copy_fields(const RC4EAPOL *other) { + copy_eapol_fields(other); + std::memcpy(&_header, &other->_header, sizeof(_header)); + _key_size = other->_key_size; + if(_key_size) { + _key = new uint8_t[_key_size]; + std::memcpy(_key, other->_key, _key_size); + } + else + _key = 0; +} /* RSNEAPOL */ @@ -178,6 +214,16 @@ Tins::RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz) : EAPOL(0x03, _key = 0; } +Tins::RSNEAPOL::RSNEAPOL(const RSNEAPOL &other) : EAPOL(other) { + copy_fields(&other); +} + +Tins::RSNEAPOL &Tins::RSNEAPOL::operator= (const RSNEAPOL &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::RSNEAPOL::~RSNEAPOL() { delete[] _key; } @@ -248,3 +294,20 @@ void Tins::RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { } } +void Tins::RSNEAPOL::copy_fields(const RSNEAPOL *other) { + copy_eapol_fields(other); + std::memcpy(&_header, &other->_header, sizeof(_header)); + _key_size = other->_key_size; + if(_key_size) { + _key = new uint8_t[_key_size]; + std::memcpy(_key, other->_key, _key_size); + } + else + _key = 0; +} + +Tins::PDU *Tins::RSNEAPOL::clone_pdu() const { + RSNEAPOL *new_pdu = new RSNEAPOL(); + new_pdu->copy_fields(this); + return new_pdu; +} diff --git a/src/ethernetII.cpp b/src/ethernetII.cpp index df11180..a909f6d 100644 --- a/src/ethernetII.cpp +++ b/src/ethernetII.cpp @@ -73,12 +73,13 @@ Tins::EthernetII::EthernetII(const uint8_t *buffer, uint32_t total_sz) : PDU(ETH inner_pdu(next); } -Tins::EthernetII::EthernetII(const EthernetII &other) : PDU(ETHERTYPE_IP) { - *this = other; +Tins::EthernetII::EthernetII(const EthernetII &other) : PDU(other) { + copy_fields(&other); } Tins::EthernetII &Tins::EthernetII::operator= (const EthernetII &other) { copy_fields(&other); + copy_inner_pdu(other); return *this; } diff --git a/src/icmp.cpp b/src/icmp.cpp index e7bc639..52254b1 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -48,6 +48,16 @@ Tins::ICMP::ICMP(Flags flag) : PDU(IPPROTO_ICMP) { }; } +Tins::ICMP::ICMP(const ICMP &other) : PDU(other) { + copy_fields(&other); +} + +Tins::ICMP &Tins::ICMP::operator= (const ICMP &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + Tins::ICMP::ICMP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_ICMP) { if(total_sz < sizeof(icmphdr)) throw std::runtime_error("Not enough size for an ICMP header in the buffer."); @@ -199,3 +209,13 @@ Tins::PDU *Tins::ICMP::clone_packet(const uint8_t *ptr, uint32_t total_sz) { cloned->inner_pdu(child); return cloned; } + +void Tins::ICMP::copy_fields(const ICMP *other) { + std::memcpy(&_icmp, &other->_icmp, sizeof(_icmp)); +} + +Tins::PDU *Tins::ICMP::clone_pdu() const { + ICMP *new_pdu = new ICMP(); + new_pdu->copy_fields(this); + return new_pdu; +} diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index 1f5ce29..d19bd27 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -84,6 +84,10 @@ Tins::IEEE802_11::IEEE802_11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETH } } +Tins::IEEE802_11::IEEE802_11(const IEEE802_11 &other) : PDU(other) { + copy_80211_fields(&other); +} + Tins::IEEE802_11::~IEEE802_11() { while(_options.size()) { delete[] _options.front().value; @@ -91,6 +95,12 @@ Tins::IEEE802_11::~IEEE802_11() { } } +Tins::IEEE802_11 &Tins::IEEE802_11::operator= (const IEEE802_11 &other) { + copy_80211_fields(&other); + copy_inner_pdu(other); + return *this; +} + void Tins::IEEE802_11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) { uint8_t opcode, length; while(total_sz >= 2) { @@ -261,6 +271,14 @@ Tins::PDU *Tins::IEEE802_11::from_bytes(const uint8_t *buffer, uint32_t total_sz return ret; } +void Tins::IEEE802_11::copy_80211_fields(const IEEE802_11 *other) { + std::memcpy(&_header, &other->_header, sizeof(_header)); + std::memcpy(_addr4, other->_addr4, sizeof(_header)); + _iface_index = other->_iface_index; + _options_size = other->_options_size; + for(std::list::const_iterator it = other->_options.begin(); it != other->_options.end(); ++it) + _options.push_back(IEEE802_11_Option(it->option, it->length, it->value)); +} /* * ManagementFrame @@ -280,6 +298,10 @@ Tins::ManagementFrame::ManagementFrame(const std::string &iface, this->type(IEEE802_11::MANAGEMENT); } +Tins::ManagementFrame::ManagementFrame(const ManagementFrame &other) : IEEE802_11(other) { + +} + void Tins::ManagementFrame::ssid(const std::string &new_ssid) { add_tagged_option(IEEE802_11::SSID, new_ssid.size(), (const uint8_t*)new_ssid.c_str()); } @@ -392,6 +414,21 @@ Tins::IEEE802_11_Beacon::IEEE802_11_Beacon(const uint8_t *buffer, uint32_t total parse_tagged_parameters(buffer, total_sz); } +Tins::IEEE802_11_Beacon::IEEE802_11_Beacon(const IEEE802_11_Beacon &other) : ManagementFrame(other) { + +} + +Tins::IEEE802_11_Beacon &Tins::IEEE802_11_Beacon::operator= (const IEEE802_11_Beacon &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + +void Tins::IEEE802_11_Beacon::copy_fields(const IEEE802_11_Beacon *other) { + copy_80211_fields(other); + std::memcpy(&_body, &other->_body, sizeof(_body)); +} + void Tins::IEEE802_11_Beacon::timestamp(uint64_t new_timestamp) { this->_body.timestamp = new_timestamp; } @@ -473,6 +510,8 @@ uint32_t Tins::IEEE802_11_Beacon::write_fixed_parameters(uint8_t *buffer, uint32 return sz; } +/* 802.11 diassoc */ + Tins::IEEE802_11_Disassoc::IEEE802_11_Disassoc() : ManagementFrame() { this->subtype(IEEE802_11::DISASSOC); memset(&_body, 0, sizeof(_body)); @@ -485,6 +524,21 @@ Tins::IEEE802_11_Disassoc::IEEE802_11_Disassoc(const std::string& iface, memset(&_body, 0, sizeof(_body)); } +Tins::IEEE802_11_Disassoc::IEEE802_11_Disassoc(const IEEE802_11_Disassoc &other) : ManagementFrame(other) { + copy_fields(&other); +} + +Tins::IEEE802_11_Disassoc &Tins::IEEE802_11_Disassoc::operator= (const IEEE802_11_Disassoc &other) { + copy_inner_pdu(other); + copy_fields(&other); + return *this; +} + +void Tins::IEEE802_11_Disassoc::copy_fields(const IEEE802_11_Disassoc *other) { + copy_80211_fields(other); + std::memcpy(&_body, &other->_body, sizeof(_body)); +} + void Tins::IEEE802_11_Disassoc::reason_code(uint16_t new_reason_code) { this->_body.reason_code = new_reason_code; } @@ -561,6 +615,8 @@ Tins::RSNInformation Tins::RSNInformation::wpa2_psk() { return info; } +/* Assoc request. */ + Tins::IEEE802_11_Assoc_Request::IEEE802_11_Assoc_Request() : ManagementFrame() { this->subtype(IEEE802_11::ASSOC_REQ); memset(&_body, 0, sizeof(_body)); @@ -584,6 +640,21 @@ Tins::IEEE802_11_Assoc_Request::IEEE802_11_Assoc_Request(const uint8_t *buffer, parse_tagged_parameters(buffer, total_sz); } +Tins::IEEE802_11_Assoc_Request::IEEE802_11_Assoc_Request(const IEEE802_11_Assoc_Request &other) : ManagementFrame(other) { + copy_fields(&other); +} + +Tins::IEEE802_11_Assoc_Request &Tins::IEEE802_11_Assoc_Request::operator= (const IEEE802_11_Assoc_Request &other) { + copy_inner_pdu(other); + copy_fields(&other); + return *this; +} + +void Tins::IEEE802_11_Assoc_Request::copy_fields(const IEEE802_11_Assoc_Request *other) { + copy_80211_fields(other); + std::memcpy(&_body, &other->_body, sizeof(_body)); +} + void Tins::IEEE802_11_Assoc_Request::listen_interval(uint16_t new_listen_interval) { this->_body.listen_interval = new_listen_interval; } @@ -627,6 +698,8 @@ uint32_t Tins::IEEE802_11_Assoc_Request::write_fixed_parameters(uint8_t *buffer, return sz; } +/* Assoc response. */ + Tins::IEEE802_11_Assoc_Response::IEEE802_11_Assoc_Response() : ManagementFrame() { this->subtype(IEEE802_11::ASSOC_RESP); memset(&_body, 0, sizeof(_body)); @@ -650,6 +723,21 @@ Tins::IEEE802_11_Assoc_Response::IEEE802_11_Assoc_Response(const uint8_t *buffer parse_tagged_parameters(buffer, total_sz); } +Tins::IEEE802_11_Assoc_Response::IEEE802_11_Assoc_Response(const IEEE802_11_Assoc_Response &other) : ManagementFrame(other) { + copy_fields(&other); +} + +Tins::IEEE802_11_Assoc_Response &Tins::IEEE802_11_Assoc_Response::operator= (const IEEE802_11_Assoc_Response &other) { + copy_inner_pdu(other); + copy_fields(&other); + return *this; +} + +void Tins::IEEE802_11_Assoc_Response::copy_fields(const IEEE802_11_Assoc_Response *other) { + copy_80211_fields(other); + std::memcpy(&_body, &other->_body, sizeof(_body)); +} + void Tins::IEEE802_11_Assoc_Response::status_code(uint16_t new_status_code) { this->_body.status_code = new_status_code; } @@ -681,6 +769,8 @@ uint32_t Tins::IEEE802_11_Assoc_Response::write_fixed_parameters(uint8_t *buffer return sz; } +/* QoS data. */ + Tins::IEEE802_11_QoS_Data::IEEE802_11_QoS_Data(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : IEEE802_11(dst_hw_addr, src_hw_addr, child) { this->type(IEEE802_11::DATA); this->subtype(IEEE802_11::QOS_DATA_DATA); @@ -710,6 +800,21 @@ Tins::IEEE802_11_QoS_Data::IEEE802_11_QoS_Data(const uint8_t *buffer, uint32_t t inner_pdu(new Tins::SNAP(buffer, total_sz)); } +Tins::IEEE802_11_QoS_Data::IEEE802_11_QoS_Data(const IEEE802_11_QoS_Data &other) : IEEE802_11(other) { + copy_fields(&other); +} + +Tins::IEEE802_11_QoS_Data &Tins::IEEE802_11_QoS_Data::operator= (const IEEE802_11_QoS_Data &other) { + copy_inner_pdu(other); + copy_fields(&other); + return *this; +} + +void Tins::IEEE802_11_QoS_Data::copy_fields(const IEEE802_11_QoS_Data *other) { + copy_80211_fields(other); + _qos_control = other->_qos_control; +} + void Tins::IEEE802_11_QoS_Data::qos_control(uint16_t new_qos_control) { this->_qos_control = new_qos_control; } diff --git a/src/ip.cpp b/src/ip.cpp index c85aa69..6ce362a 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -46,8 +46,8 @@ Tins::IP::IP(const string &ip_dst, const string &ip_src, PDU *child) : PDU(IPPRO } -Tins::IP::IP(const IP &other) : PDU(IPPROTO_IP) { - *this = other; +Tins::IP::IP(const IP &other) : PDU(other) { + copy_fields(&other); } Tins::IP::IP() : PDU(IPPROTO_IP) { @@ -56,8 +56,7 @@ Tins::IP::IP() : PDU(IPPROTO_IP) { Tins::IP &Tins::IP::operator= (const IP &other) { copy_fields(&other); - if(other.inner_pdu()) - inner_pdu(other.inner_pdu()->clone_packet()); + copy_inner_pdu(other); return *this; } @@ -354,9 +353,13 @@ void Tins::IP::copy_fields(const IP *other) { new_opt.optional_data = new uint8_t[it->optional_data_size]; memcpy(new_opt.optional_data, it->optional_data, it->optional_data_size); } + else + new_opt.optional_data = 0; new_opt.optional_data_size = it->optional_data_size; _ip_options.push_back(new_opt); } + _options_size = other->_options_size; + _padded_options_size = other->_padded_options_size; } Tins::PDU *Tins::IP::clone_pdu() const { diff --git a/src/pdu.cpp b/src/pdu.cpp index 090b33e..c5b8831 100644 --- a/src/pdu.cpp +++ b/src/pdu.cpp @@ -29,10 +29,20 @@ Tins::PDU::PDU(uint32_t flag, PDU *next_pdu) : _flag(flag), _inner_pdu(next_pdu) } +Tins::PDU::PDU(const PDU &other) : _inner_pdu(0) { + _flag = other.flag(); + copy_inner_pdu(other); +} + Tins::PDU::~PDU() { delete _inner_pdu; } +void Tins::PDU::copy_inner_pdu(const PDU &pdu) { + if(pdu.inner_pdu()) + inner_pdu(pdu.inner_pdu()->clone_pdu()); +} + uint32_t Tins::PDU::size() const { uint32_t sz = header_size() + trailer_size(); const PDU *ptr(_inner_pdu); diff --git a/src/snap.cpp b/src/snap.cpp index 28b8f9b..d956be2 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -57,6 +57,16 @@ Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { }; } +Tins::SNAP::SNAP(const SNAP &other) : PDU(other) { + copy_fields(&other); +} + +Tins::SNAP &Tins::SNAP::operator= (const SNAP &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + uint32_t Tins::SNAP::header_size() const { return sizeof(_snap); } @@ -83,3 +93,12 @@ void Tins::SNAP::write_serialization(uint8_t *buffer, uint32_t total_sz, const P std::memcpy(buffer, &_snap, sizeof(_snap)); } +void Tins::SNAP::copy_fields(const SNAP *other) { + std::memcpy(&_snap, &other->_snap, sizeof(_snap)); +} + +Tins::PDU *Tins::SNAP::clone_pdu() const { + SNAP *new_pdu = new SNAP(); + new_pdu->copy_fields(this); + return new_pdu; +} diff --git a/src/tcp.cpp b/src/tcp.cpp index 60560ad..c7fdbd0 100644 --- a/src/tcp.cpp +++ b/src/tcp.cpp @@ -42,6 +42,16 @@ Tins::TCP::TCP(uint16_t dport, uint16_t sport) : PDU(IPPROTO_TCP), _options_size this->check(0); } +Tins::TCP::TCP(const TCP &other) : PDU(other) { + copy_fields(&other); +} + +Tins::TCP &Tins::TCP::operator= (const TCP &other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + 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."); @@ -253,3 +263,24 @@ uint8_t *Tins::TCP::TCPOption::write(uint8_t *buffer) { return buffer + length + (sizeof(uint8_t) << 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->kind, it->length); + if(it->data) { + opt.data = new uint8_t[it->length]; + std::memcpy(opt.data, it->data, it->length); + } + _options.push_back(opt); + } + _options_size = other->_options_size; + _total_options_size = other->_total_options_size; +} + +Tins::PDU *Tins::TCP::clone_pdu() const { + TCP *new_pdu = new TCP(); + new_pdu->copy_fields(this); + return new_pdu; +} + diff --git a/src/udp.cpp b/src/udp.cpp index a274c91..7f0ede3 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -46,6 +46,16 @@ Tins::UDP::UDP(const uint8_t *buffer, uint32_t total_sz) : PDU(IPPROTO_UDP) { inner_pdu(new RawPDU(buffer + sizeof(udphdr), total_sz)); } +Tins::UDP::UDP(const UDP &other) : PDU(other) { + copy_fields(&other); +} + +Tins::UDP &Tins::UDP::operator= (const UDP& other) { + copy_fields(&other); + copy_inner_pdu(other); + return *this; +} + void Tins::UDP::payload(uint8_t *new_payload, uint32_t new_payload_size) { inner_pdu(new RawPDU(new_payload, new_payload_size)); } @@ -82,3 +92,12 @@ void Tins::UDP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PD _udp.check = 0; } +void Tins::UDP::copy_fields(const UDP *other) { + std::memcpy(&_udp, &other->_udp, sizeof(_udp)); +} + +Tins::PDU *Tins::UDP::clone_pdu() const { + UDP *new_pdu = new UDP(); + new_pdu->copy_fields(this); + return new_pdu; +}