mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added some serialization tests to every PDU.
This commit is contained in:
@@ -205,6 +205,17 @@ namespace Tins {
|
||||
*/
|
||||
bool add_type_option(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option the the option list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*
|
||||
* \return True if the option was added successfully. \sa DHCP::add_option
|
||||
*/
|
||||
bool add_end_option();
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
* \param value A pointer in which the option's value will be stored.
|
||||
|
||||
@@ -42,7 +42,6 @@ namespace Tins {
|
||||
IPv4Address &operator=(const std::string &ip);
|
||||
|
||||
operator uint32_t() const;
|
||||
operator std::string() const;
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
@@ -55,7 +54,7 @@ namespace Tins {
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr) {
|
||||
return output << (std::string)addr;
|
||||
return output << addr.to_string();
|
||||
}
|
||||
private:
|
||||
uint32_t ip_to_int(const std::string &ip);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "packetsender.h"
|
||||
|
||||
/** \brief The Tins namespace.
|
||||
@@ -43,6 +44,10 @@ namespace Tins {
|
||||
*/
|
||||
class PDU {
|
||||
public:
|
||||
/**
|
||||
* The type that will be returned when serializing PDUs.
|
||||
*/
|
||||
typedef std::vector<uint8_t> serialization_type;
|
||||
|
||||
/**
|
||||
* \brief Enum which identifies each type of PDU.
|
||||
@@ -148,13 +153,16 @@ namespace Tins {
|
||||
void inner_pdu(PDU *next_pdu);
|
||||
|
||||
|
||||
/** \brief Serializes the whole chain of PDU's, including this one.
|
||||
/**
|
||||
* \brief Serializes the whole chain of PDU's, including this one.
|
||||
*
|
||||
* \param sz The size of the buffer must be returned through this parameter.
|
||||
* The buffer returned must be deleted by the user using
|
||||
* operator delete[].
|
||||
* This allocates a std::vector of size size(), and fills it
|
||||
* with the serialization this PDU, and all of the inner ones'.
|
||||
*
|
||||
* \return serialization_type containing the serialization
|
||||
* of the whole stack of PDUs.
|
||||
*/
|
||||
uint8_t *serialize(uint32_t &sz);
|
||||
serialization_type serialize();
|
||||
|
||||
/**
|
||||
* \brief Find and returns the first PDU that matches the given flag.
|
||||
|
||||
21
src/dhcp.cpp
21
src/dhcp.cpp
@@ -35,14 +35,14 @@ const uint32_t DHCP::MAX_DHCP_SIZE = 312;
|
||||
|
||||
/* Magic cookie: uint32_t.
|
||||
* end of options: 1 byte. */
|
||||
DHCP::DHCP() : _size(sizeof(uint32_t) + 1) {
|
||||
DHCP::DHCP() : _size(sizeof(uint32_t)) {
|
||||
opcode(BOOTREQUEST);
|
||||
htype(1); //ethernet
|
||||
hlen(EthernetII::ADDR_SIZE);
|
||||
}
|
||||
|
||||
DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
|
||||
: BootP(buffer, total_sz, 0), _size(sizeof(uint32_t) + 1)
|
||||
: BootP(buffer, total_sz, 0), _size(sizeof(uint32_t))
|
||||
{
|
||||
buffer += BootP::header_size() - vend_size();
|
||||
total_sz -= BootP::header_size() - vend_size();
|
||||
@@ -55,24 +55,19 @@ DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
|
||||
for(unsigned i(0); i < 2; ++i) {
|
||||
args[i] = *(buffer++);
|
||||
total_sz--;
|
||||
if(args[0] == END || args[0] == PAD)
|
||||
if(args[0] == END || args[0] == PAD) {
|
||||
args[1] = 0;
|
||||
i = 2;
|
||||
}
|
||||
else if(!total_sz)
|
||||
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
|
||||
}
|
||||
// If the END-OF-OPTIONS was not found...
|
||||
if(args[0] != END && args[0] != PAD) {
|
||||
// Not enough size for this option
|
||||
if(total_sz < args[1])
|
||||
throw std::runtime_error("Not enough size for a DHCP header in the buffer.");
|
||||
add_option((Options)args[0], args[1], buffer);
|
||||
buffer += args[1];
|
||||
total_sz -= args[1];
|
||||
}
|
||||
// Otherwise, break the loop.
|
||||
else
|
||||
total_sz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DHCP::DHCPOption::DHCPOption(uint8_t opt, uint8_t len, const uint8_t *val)
|
||||
@@ -102,6 +97,10 @@ bool DHCP::add_type_option(Flags type) {
|
||||
return add_option(DHCP_MESSAGE_TYPE, sizeof(uint8_t), &int_type);
|
||||
}
|
||||
|
||||
bool DHCP::add_end_option() {
|
||||
return add_option(DHCP_MESSAGE_TYPE, 0, 0);
|
||||
}
|
||||
|
||||
bool DHCP::search_type_option(uint8_t *value) {
|
||||
return generic_search(DHCP_MESSAGE_TYPE, value);
|
||||
}
|
||||
@@ -239,7 +238,7 @@ void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa
|
||||
ptr += it->value.size();
|
||||
}
|
||||
// End of options
|
||||
result[_size-1] = END;
|
||||
//result[_size-1] = END;
|
||||
vend(result, _size);
|
||||
}
|
||||
BootP::write_serialization(buffer, total_sz, parent);
|
||||
|
||||
11
src/dns.cpp
11
src/dns.cpp
@@ -41,6 +41,7 @@ DNS::DNS(const uint8_t *buffer, uint32_t total_sz) : PDU(255), extra_size(0) {
|
||||
const uint8_t *end(buffer + total_sz);
|
||||
uint16_t nquestions(questions());
|
||||
buffer += sizeof(dnshdr);
|
||||
total_sz -= sizeof(dnshdr);
|
||||
for(uint16_t i(0); i < nquestions; ++i) {
|
||||
const uint8_t *ptr(buffer);
|
||||
while(ptr < end && *ptr)
|
||||
@@ -105,10 +106,10 @@ const uint8_t *DNS::build_resource_list(list<ResourceRecord*> &lst, const uint8_
|
||||
ptr += sizeof(uint16_t);
|
||||
}
|
||||
else {
|
||||
const uint8_t *str_end(ptr), *end(ptr + sz);
|
||||
while(str_end < end && *str_end)
|
||||
const uint8_t *str_end(ptr);
|
||||
while(str_end < ptr_end && *str_end)
|
||||
str_end++;
|
||||
if(str_end == end)
|
||||
if(str_end == ptr_end)
|
||||
throw std::runtime_error("Not enough size for a resource domain name.");
|
||||
//str_end++;
|
||||
res.reset(new NamedResourceRecord(string(ptr, str_end)));
|
||||
@@ -123,7 +124,7 @@ const uint8_t *DNS::build_resource_list(list<ResourceRecord*> &lst, const uint8_
|
||||
|
||||
// Store the option size.
|
||||
res->data.resize(
|
||||
Utils::host_to_be(*reinterpret_cast<const uint16_t*>(ptr))
|
||||
Utils::be_to_host(*reinterpret_cast<const uint16_t*>(ptr))
|
||||
);
|
||||
ptr += sizeof(uint16_t);
|
||||
if(ptr + res->data.size() > ptr_end)
|
||||
@@ -131,7 +132,7 @@ const uint8_t *DNS::build_resource_list(list<ResourceRecord*> &lst, const uint8_
|
||||
if(contains_dname(res->info.type))
|
||||
std::copy(ptr, ptr + res->data.size(), res->data.begin());
|
||||
else if(res->data.size() == sizeof(uint32_t))
|
||||
*(uint32_t*)&res->data[0] = Utils::host_to_be(*(uint32_t*)ptr);
|
||||
*(uint32_t*)&res->data[0] = Utils::be_to_host(*(uint32_t*)ptr);
|
||||
else
|
||||
throw std::runtime_error("Not enough size for resource data");
|
||||
|
||||
|
||||
@@ -47,10 +47,6 @@ Tins::IP::IP(IPv4Address ip_dst, IPv4Address ip_src, PDU *child) :
|
||||
this->src_addr(ip_src);
|
||||
}
|
||||
|
||||
Tins::IP::IP() : PDU(IPPROTO_IP) {
|
||||
init_ip_fields();
|
||||
}
|
||||
|
||||
Tins::IP::IP(const uint8_t *buffer, uint32_t total_sz)
|
||||
: PDU(Constants::IP::PROTO_IP)
|
||||
{
|
||||
|
||||
@@ -49,10 +49,6 @@ IPv4Address::operator uint32_t() const {
|
||||
return Utils::host_to_be(ip_addr);
|
||||
}
|
||||
|
||||
IPv4Address::operator std::string() const {
|
||||
return Utils::ip_to_string(ip_addr);
|
||||
}
|
||||
|
||||
std::string IPv4Address::to_string() const {
|
||||
return Utils::ip_to_string(ip_addr);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <cassert>
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include "packetsender.h"
|
||||
|
||||
@@ -102,11 +103,11 @@ bool Tins::PacketSender::send_l2(PDU *pdu, struct sockaddr* link_addr, uint32_t
|
||||
if(!open_l2_socket())
|
||||
return false;
|
||||
|
||||
uint32_t sz;
|
||||
int sock = _sockets[ETHER_SOCKET];
|
||||
uint8_t *buffer = pdu->serialize(sz);
|
||||
bool ret_val = (sendto(sock, buffer, sz, 0, link_addr, len_addr) != -1);
|
||||
delete[] buffer;
|
||||
PDU::serialization_type buffer = pdu->serialize();
|
||||
if(buffer.size() == 0)
|
||||
return false;
|
||||
bool ret_val = (sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
@@ -128,11 +129,9 @@ bool Tins::PacketSender::send_l3(PDU *pdu, struct sockaddr* link_addr, uint32_t
|
||||
if(!open_l3_socket(type))
|
||||
ret_val = false;
|
||||
if (ret_val) {
|
||||
uint32_t sz;
|
||||
int sock = _sockets[type];
|
||||
uint8_t *buffer = pdu->serialize(sz);
|
||||
ret_val = (sendto(sock, buffer, sz, 0, link_addr, len_addr) != -1);
|
||||
delete[] buffer;
|
||||
PDU::serialization_type buffer = pdu->serialize();
|
||||
ret_val = (sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) != -1);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
33
src/pdu.cpp
33
src/pdu.cpp
@@ -25,32 +25,33 @@
|
||||
#include "pdu.h"
|
||||
#include "rawpdu.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
Tins::PDU::PDU(uint32_t flag, PDU *next_pdu) : _flag(flag), _inner_pdu(next_pdu) {
|
||||
PDU::PDU(uint32_t flag, PDU *next_pdu) : _flag(flag), _inner_pdu(next_pdu) {
|
||||
|
||||
}
|
||||
|
||||
Tins::PDU::PDU(const PDU &other) : _inner_pdu(0) {
|
||||
PDU::PDU(const PDU &other) : _inner_pdu(0) {
|
||||
_flag = other.flag();
|
||||
copy_inner_pdu(other);
|
||||
}
|
||||
|
||||
Tins::PDU &Tins::PDU::operator=(const PDU &other) {
|
||||
PDU &PDU::operator=(const PDU &other) {
|
||||
_flag = other.flag();
|
||||
copy_inner_pdu(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Tins::PDU::~PDU() {
|
||||
PDU::~PDU() {
|
||||
delete _inner_pdu;
|
||||
}
|
||||
|
||||
void Tins::PDU::copy_inner_pdu(const PDU &pdu) {
|
||||
void 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 PDU::size() const {
|
||||
uint32_t sz = header_size() + trailer_size();
|
||||
const PDU *ptr(_inner_pdu);
|
||||
while(ptr) {
|
||||
@@ -60,23 +61,24 @@ uint32_t Tins::PDU::size() const {
|
||||
return sz;
|
||||
}
|
||||
|
||||
void Tins::PDU::flag(uint32_t new_flag) {
|
||||
void PDU::flag(uint32_t new_flag) {
|
||||
_flag = new_flag;
|
||||
}
|
||||
|
||||
void Tins::PDU::inner_pdu(PDU *next_pdu) {
|
||||
void PDU::inner_pdu(PDU *next_pdu) {
|
||||
delete _inner_pdu;
|
||||
_inner_pdu = next_pdu;
|
||||
}
|
||||
|
||||
uint8_t *Tins::PDU::serialize(uint32_t &sz) {
|
||||
sz = size();
|
||||
uint8_t *buffer = new uint8_t[sz];
|
||||
serialize(buffer, sz, 0);
|
||||
PDU::serialization_type PDU::serialize() {
|
||||
std::vector<uint8_t> buffer(size());
|
||||
serialize(&buffer[0], buffer.size(), 0);
|
||||
|
||||
// Copy elision, do your magic
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void Tins::PDU::serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
void PDU::serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
uint32_t sz = header_size() + trailer_size();
|
||||
/* Must not happen... */
|
||||
assert(total_sz >= sz);
|
||||
@@ -85,7 +87,7 @@ void Tins::PDU::serialize(uint8_t *buffer, uint32_t total_sz, const PDU *parent)
|
||||
write_serialization(buffer, total_sz, parent);
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::PDU::clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz) {
|
||||
PDU *PDU::clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz) {
|
||||
PDU *child = 0;
|
||||
if(inner_pdu()) {
|
||||
child = inner_pdu()->clone_packet(ptr, total_sz);
|
||||
@@ -97,7 +99,7 @@ Tins::PDU *Tins::PDU::clone_inner_pdu(const uint8_t *ptr, uint32_t total_sz) {
|
||||
return child;
|
||||
}
|
||||
|
||||
Tins::PDU *Tins::PDU::clone_packet() const {
|
||||
PDU *PDU::clone_packet() const {
|
||||
PDU *ret = clone_pdu();
|
||||
if(ret) {
|
||||
PDU *ptr = 0, *last = ret;
|
||||
@@ -109,3 +111,4 @@ Tins::PDU *Tins::PDU::clone_packet() const {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
181
tests/depends.d
181
tests/depends.d
@@ -264,6 +264,28 @@ src/utils_test.o: src/utils_test.cpp ../include/utils.h \
|
||||
../include/network_interface.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
src/dot11/ack.o: src/dot11/ack.cpp ../include/dot11.h ../include/pdu.h \
|
||||
../include/packetsender.h ../include/utils.h ../include/ipaddress.h \
|
||||
../include/hwaddress.h ../include/network_interface.h \
|
||||
include/tests/dot11.h include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/assoc_request.o: src/dot11/assoc_request.cpp ../include/dot11.h \
|
||||
../include/pdu.h ../include/packetsender.h ../include/utils.h \
|
||||
../include/ipaddress.h ../include/hwaddress.h \
|
||||
@@ -355,6 +377,97 @@ src/dot11/beacon.o: src/dot11/beacon.cpp ../include/dot11.h \
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/block_ack_request.o: src/dot11/block_ack_request.cpp \
|
||||
../include/dot11.h ../include/pdu.h ../include/packetsender.h \
|
||||
../include/utils.h ../include/ipaddress.h ../include/hwaddress.h \
|
||||
../include/network_interface.h include/tests/dot11.h \
|
||||
include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/cfendack.o: src/dot11/cfendack.cpp ../include/dot11.h \
|
||||
../include/pdu.h ../include/packetsender.h ../include/utils.h \
|
||||
../include/ipaddress.h ../include/hwaddress.h \
|
||||
../include/network_interface.h include/tests/dot11.h \
|
||||
include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/cfend.o: src/dot11/cfend.cpp ../include/dot11.h \
|
||||
../include/pdu.h ../include/packetsender.h ../include/utils.h \
|
||||
../include/ipaddress.h ../include/hwaddress.h \
|
||||
../include/network_interface.h include/tests/dot11.h \
|
||||
include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/data.o: src/dot11/data.cpp ../include/dot11.h ../include/pdu.h \
|
||||
../include/packetsender.h ../include/utils.h ../include/ipaddress.h \
|
||||
../include/hwaddress.h ../include/network_interface.h \
|
||||
include/tests/dot11.h include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/deauthentication.o: src/dot11/deauthentication.cpp \
|
||||
../include/dot11.h ../include/pdu.h ../include/packetsender.h \
|
||||
@@ -449,6 +562,52 @@ src/dot11/probe_request.o: src/dot11/probe_request.cpp ../include/dot11.h \
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/probe_response.o: src/dot11/probe_response.cpp \
|
||||
../include/dot11.h ../include/pdu.h ../include/packetsender.h \
|
||||
../include/utils.h ../include/ipaddress.h ../include/hwaddress.h \
|
||||
../include/network_interface.h include/tests/dot11.h \
|
||||
include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/pspoll.o: src/dot11/pspoll.cpp ../include/dot11.h \
|
||||
../include/pdu.h ../include/packetsender.h ../include/utils.h \
|
||||
../include/ipaddress.h ../include/hwaddress.h \
|
||||
../include/network_interface.h include/tests/dot11.h \
|
||||
include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/reassoc_request.o: src/dot11/reassoc_request.cpp \
|
||||
../include/dot11.h ../include/pdu.h ../include/packetsender.h \
|
||||
@@ -495,6 +654,28 @@ src/dot11/reassoc_response.o: src/dot11/reassoc_response.cpp \
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
src/dot11/rts.o: src/dot11/rts.cpp ../include/dot11.h ../include/pdu.h \
|
||||
../include/packetsender.h ../include/utils.h ../include/ipaddress.h \
|
||||
../include/hwaddress.h ../include/network_interface.h \
|
||||
include/tests/dot11.h include/tests/dot11.h
|
||||
|
||||
../include/dot11.h:
|
||||
|
||||
../include/pdu.h:
|
||||
|
||||
../include/packetsender.h:
|
||||
|
||||
../include/utils.h:
|
||||
|
||||
../include/ipaddress.h:
|
||||
|
||||
../include/hwaddress.h:
|
||||
|
||||
../include/network_interface.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
|
||||
include/tests/dot11.h:
|
||||
../src/arp.o: ../src/arp.cpp ../include/arp.h ../include/pdu.h \
|
||||
../include/packetsender.h ../include/ipaddress.h ../include/utils.h \
|
||||
|
||||
@@ -143,25 +143,18 @@ TEST_F(ARPTest, Opcode) {
|
||||
TEST_F(ARPTest, Serialize) {
|
||||
ARP arp1(0x1234, 0xa3f1, hw_addr1, hw_addr2);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = arp1.serialize(size);
|
||||
ASSERT_TRUE(buffer);
|
||||
PDU::serialization_type buffer = arp1.serialize();
|
||||
|
||||
ARP arp2(arp1);
|
||||
uint32_t size2;
|
||||
uint8_t *buffer2 = arp2.serialize(size2);
|
||||
ASSERT_EQ(size, size2);
|
||||
EXPECT_TRUE(memcmp(buffer, buffer2, size) == 0);
|
||||
delete[] buffer;
|
||||
delete[] buffer2;
|
||||
PDU::serialization_type buffer2 = arp2.serialize();
|
||||
EXPECT_EQ(buffer, buffer2);
|
||||
}
|
||||
|
||||
TEST_F(ARPTest, ConstructorFromBuffer) {
|
||||
ARP arp1(expected_packet, sizeof(expected_packet));
|
||||
uint32_t size;
|
||||
uint8_t *buffer = arp1.serialize(size);
|
||||
PDU::serialization_type buffer = arp1.serialize();
|
||||
|
||||
ARP arp2(buffer, size);
|
||||
ARP arp2(&buffer[0], buffer.size());
|
||||
EXPECT_EQ(arp1.opcode(), arp2.opcode());
|
||||
ASSERT_EQ(arp1.hw_addr_length(), arp2.hw_addr_length());
|
||||
EXPECT_EQ(arp1.hw_addr_format(), arp2.hw_addr_format());
|
||||
@@ -171,6 +164,4 @@ TEST_F(ARPTest, ConstructorFromBuffer) {
|
||||
EXPECT_EQ(arp1.target_ip_addr(), arp2.target_ip_addr());
|
||||
EXPECT_EQ(arp1.sender_hw_addr(), arp2.sender_hw_addr());
|
||||
EXPECT_EQ(arp1.target_hw_addr(), arp2.target_hw_addr());
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
@@ -39,28 +39,39 @@ const uint8_t DHCPTest::file[] = "\x16\xab\x54\x12\xfa\xca\x56\x7f\x1b\x65\x11\x
|
||||
"\x16\xab\x54\x12\xfa\xca\x56\x7f\x1b\x65\x11\xfa\xda\xfb\x19\x18";
|
||||
const IPv4Address DHCPTest::addr("192.168.8.1");
|
||||
|
||||
/*const uint8_t DHCPTest::expected_packet[] = {'\x01', '\x01', '\x06', '\x1f', '?', '\xab', '#', '\xde',
|
||||
'\x9f', '\x1a', '\x00', '\x00', '\xc0', '\xa8', '\x00', 'f', '\xf3', '\x16', '"', 'b', '\xa7', ' ',
|
||||
'\x0b', '\x9a', '{', '+', '7', '\xfe', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', 'c', '\x82', 'S', 'c', '6', '\x04', '\xc0', '\xa8', '\x04', '\x02',
|
||||
'\x01', '\x04', '\xff', '\xff', ' ', '\x0b', '5', '\x01', '\x04'};*/
|
||||
|
||||
const uint8_t DHCPTest::expected_packet[] = {'\x01', '\x01', '\x06', '\x1f', '?', '\xab', '#', '\xde', '\x9f', '\x1a', '\x00', '\x00', '\xc0', '\xa8', '\x00', 'f', '\xf3', '\x16', '"', 'b', '\xa7', ' ', '\x0b', '\x9a', '{', '+', '7', '\xfe', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'c', '\x82', 'S', 'c', '6', '\x04', '\xc0', '\xa8', '\x04', '\x02', '\x01', '\x04', '\xff', '\xff', ' ', '\x0b', '5', '\x01', '\x04', '\x03', '\x08', '\xc0', '\xa8', '\x00', '\x01', '\x7f', '\x00', '\x00', '\x01', '\x06', '\x08', '\xc0', '\xa8', '\x00', '\x02', '\x7f', '\x00', '\x00', '\x01'};
|
||||
const uint8_t DHCPTest::expected_packet[] = {
|
||||
'\x01', '\x01', '\x06', '\x1f', '?', '\xab', '#', '\xde', '\x9f',
|
||||
'\x1a', '\x00', '\x00', '\xc0', '\xa8', '\x00', 'f', '\xf3', '\x16',
|
||||
'"', 'b', '\xa7', ' ', '\x0b', '\x9a', '{', '+', '7', '\xfe', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
|
||||
'c', '\x82', 'S', 'c', '6', '\x04', '\xc0', '\xa8', '\x04', '\x02',
|
||||
'\x01', '\x04', '\xff', '\xff', ' ', '\x0b', '5', '\x01', '\x04', '\x03',
|
||||
'\x08', '\xc0', '\xa8', '\x00', '\x01', '\x7f', '\x00', '\x00', '\x01',
|
||||
'\x06', '\x08', '\xc0', '\xa8', '\x00', '\x02', '\x7f', '\x00', '\x00',
|
||||
'\x01'
|
||||
};
|
||||
|
||||
TEST_F(DHCPTest, DefaultConstructor) {
|
||||
DHCP dhcp;
|
||||
@@ -316,14 +327,17 @@ TEST_F(DHCPTest, ConstructorFromBuffer) {
|
||||
ASSERT_EQ(routers.size(), sizeof(expected_routers) / sizeof(IPv4Address));
|
||||
|
||||
ASSERT_TRUE(std::equal(routers.begin(), routers.end(), expected_routers));
|
||||
}
|
||||
|
||||
TEST_F(DHCPTest, Serialize) {
|
||||
DHCP dhcp1(expected_packet, sizeof(expected_packet));
|
||||
PDU::serialization_type buffer = dhcp1.serialize();
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = dhcp1.serialize(size);
|
||||
ASSERT_EQ(buffer.size(), sizeof(expected_packet));
|
||||
EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet));
|
||||
|
||||
DHCP dhcp2(buffer, size);
|
||||
DHCP dhcp2(&buffer[0], buffer.size());
|
||||
test_equals(dhcp1, dhcp2);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -113,12 +113,9 @@ TEST_F(EthernetIITest, CompleteConstructor) {
|
||||
TEST_F(EthernetIITest, Serialize) {
|
||||
EthernetII eth(iface, d_addr, s_addr);
|
||||
eth.payload_type(p_type);
|
||||
uint32_t sz;
|
||||
uint8_t *serialized = eth.serialize(sz);
|
||||
EXPECT_EQ(eth.size(), sz);
|
||||
EXPECT_TRUE(serialized);
|
||||
EXPECT_TRUE(memcmp(serialized, expected_packet, sz) == 0);
|
||||
delete[] serialized;
|
||||
PDU::serialization_type serialized = eth.serialize();
|
||||
ASSERT_EQ(serialized.size(), sizeof(expected_packet));
|
||||
EXPECT_TRUE(std::equal(serialized.begin(), serialized.end(), expected_packet));
|
||||
}
|
||||
|
||||
TEST_F(EthernetIITest, ConstructorFromBuffer) {
|
||||
|
||||
@@ -196,24 +196,17 @@ TEST_F(ICMPTest, Serialize) {
|
||||
ICMP icmp1;
|
||||
icmp1.set_echo_request(0x34ab, 0x12f7);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = icmp1.serialize(size);
|
||||
ASSERT_TRUE(buffer);
|
||||
PDU::serialization_type buffer = icmp1.serialize();
|
||||
|
||||
ICMP icmp2(icmp1);
|
||||
uint32_t size2;
|
||||
uint8_t *buffer2 = icmp2.serialize(size2);
|
||||
ASSERT_EQ(size, size2);
|
||||
EXPECT_TRUE(memcmp(buffer, buffer2, size) == 0);
|
||||
delete[] buffer;
|
||||
delete[] buffer2;
|
||||
PDU::serialization_type buffer2 = icmp2.serialize();
|
||||
EXPECT_EQ(buffer, buffer2);
|
||||
}
|
||||
|
||||
TEST_F(ICMPTest, ConstructorFromBuffer) {
|
||||
for(unsigned i(0); i < expected_packet_count; ++i) {
|
||||
ICMP icmp1(expected_packets[i], sizeof(expected_packets[i]));
|
||||
uint32_t size;
|
||||
uint8_t *buffer = icmp1.serialize(size);
|
||||
PDU::serialization_type buffer = icmp1.serialize();
|
||||
|
||||
switch(i) {
|
||||
case 0:
|
||||
@@ -229,9 +222,7 @@ TEST_F(ICMPTest, ConstructorFromBuffer) {
|
||||
break;
|
||||
}
|
||||
|
||||
ICMP icmp2(buffer, size);
|
||||
ICMP icmp2(&buffer[0], buffer.size());
|
||||
test_equals(icmp1, icmp2);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,12 +187,12 @@ TEST_F(IPTest, ConstructorFromBuffer) {
|
||||
EXPECT_EQ(option->type.number, IP::SEC);
|
||||
EXPECT_EQ(option->type.op_class, IP::CONTROL);
|
||||
ASSERT_EQ(option->data_size(), sizeof(opt_sec));
|
||||
EXPECT_TRUE(memcmp(option->data_ptr(), opt_sec, sizeof(opt_sec)) == 0);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = ip1.serialize(size);
|
||||
ASSERT_TRUE(buffer);
|
||||
|
||||
IP ip2(buffer, size);
|
||||
delete[] buffer;
|
||||
EXPECT_TRUE(std::equal(option->data_ptr(), option->data_ptr() + option->data_size(), opt_sec));
|
||||
}
|
||||
|
||||
TEST_F(IPTest, Serialize) {
|
||||
IP ip1(expected_packet, sizeof(expected_packet));
|
||||
PDU::serialization_type buffer = ip1.serialize();
|
||||
ASSERT_EQ(buffer.size(), sizeof(expected_packet));
|
||||
EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ TEST(IPAddressTest, Constructor) {
|
||||
IPv4Address addr1(ip_string);
|
||||
IPv4Address addr2(Utils::ip_to_int(ip_string));
|
||||
EXPECT_EQ(addr2, addr1);
|
||||
EXPECT_EQ((std::string)addr1, ip_string);
|
||||
EXPECT_EQ((std::string)addr2, ip_string);
|
||||
EXPECT_EQ(addr1.to_string(), ip_string);
|
||||
EXPECT_EQ(addr2.to_string(), ip_string);
|
||||
}
|
||||
|
||||
@@ -79,17 +79,11 @@ TEST_F(SNAPTest, Serialize) {
|
||||
snap1.poll(0x1);
|
||||
snap1.id(0x1);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = snap1.serialize(size);
|
||||
ASSERT_TRUE(buffer);
|
||||
PDU::serialization_type buffer = snap1.serialize();
|
||||
|
||||
SNAP snap2(snap1);
|
||||
uint32_t size2;
|
||||
uint8_t *buffer2 = snap2.serialize(size2);
|
||||
ASSERT_EQ(size, size2);
|
||||
EXPECT_TRUE(memcmp(buffer, buffer2, size) == 0);
|
||||
delete[] buffer;
|
||||
delete[] buffer2;
|
||||
PDU::serialization_type buffer2 = snap2.serialize();
|
||||
EXPECT_EQ(buffer, buffer2);
|
||||
}
|
||||
|
||||
TEST_F(SNAPTest, ClonePDU) {
|
||||
@@ -107,17 +101,15 @@ TEST_F(SNAPTest, ClonePDU) {
|
||||
|
||||
TEST_F(SNAPTest, ConstructorFromBuffer) {
|
||||
SNAP snap1(expected_packet, sizeof(expected_packet));
|
||||
uint32_t size;
|
||||
uint8_t *buffer = snap1.serialize(size);
|
||||
PDU::serialization_type buffer = snap1.serialize();
|
||||
|
||||
EXPECT_EQ(snap1.id(), 3);
|
||||
EXPECT_EQ(snap1.dsap(), 0xaa);
|
||||
EXPECT_EQ(snap1.ssap(), 0xaa);
|
||||
EXPECT_EQ(snap1.eth_type(), 0x7ab1);
|
||||
|
||||
SNAP snap2(buffer, size);
|
||||
SNAP snap2(&buffer[0], buffer.size());
|
||||
test_equals(snap1, snap2);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void SNAPTest::test_equals(const SNAP &snap1, const SNAP &snap2) {
|
||||
|
||||
@@ -220,19 +220,15 @@ TEST_F(TCPTest, ConstructorFromBuffer) {
|
||||
EXPECT_EQ(edges.front(), 0x00010203); edges.pop_front();
|
||||
EXPECT_EQ(edges.front(), 0x04050607);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = tcp1.serialize(size);
|
||||
PDU::serialization_type buffer = tcp1.serialize();
|
||||
|
||||
TCP tcp2(buffer, size);
|
||||
TCP tcp2(&buffer[0], buffer.size());
|
||||
test_equals(tcp1, tcp2);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
TEST_F(TCPTest, Serialize) {
|
||||
TCP tcp1(expected_packet, sizeof(expected_packet));
|
||||
uint32_t size;
|
||||
uint8_t *buffer = tcp1.serialize(size);
|
||||
ASSERT_EQ(size, sizeof(expected_packet));
|
||||
ASSERT_TRUE(std::equal(buffer, buffer + size, expected_packet));
|
||||
delete[] buffer;
|
||||
PDU::serialization_type buffer = tcp1.serialize();
|
||||
ASSERT_EQ(buffer.size(), sizeof(expected_packet));
|
||||
EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet));
|
||||
}
|
||||
|
||||
@@ -105,35 +105,26 @@ TEST_F(UDPTest, Serialize) {
|
||||
udp1.sport(sport);
|
||||
udp1.length(length);
|
||||
|
||||
uint32_t size;
|
||||
uint8_t *buffer = udp1.serialize(size);
|
||||
ASSERT_TRUE(buffer);
|
||||
PDU::serialization_type buffer = udp1.serialize();
|
||||
|
||||
UDP udp2(udp1);
|
||||
uint32_t size2;
|
||||
uint8_t *buffer2 = udp2.serialize(size2);
|
||||
ASSERT_EQ(size, size2);
|
||||
EXPECT_TRUE(memcmp(buffer, buffer2, size) == 0);
|
||||
delete[] buffer;
|
||||
delete[] buffer2;
|
||||
PDU::serialization_type buffer2 = udp2.serialize();
|
||||
EXPECT_EQ(buffer, buffer2);
|
||||
}
|
||||
|
||||
TEST_F(UDPTest, ConstructorFromBuffer) {
|
||||
UDP udp1(expected_packet, sizeof(expected_packet));
|
||||
uint32_t size;
|
||||
uint8_t *buffer = udp1.serialize(size);
|
||||
PDU::serialization_type buffer = udp1.serialize();
|
||||
|
||||
EXPECT_EQ(size, sizeof(expected_packet));
|
||||
EXPECT_EQ(buffer.size(), sizeof(expected_packet));
|
||||
EXPECT_EQ(udp1.dport(), 0x47f1);
|
||||
EXPECT_EQ(udp1.sport(), 0xf51a);
|
||||
EXPECT_EQ(udp1.length(), 0x453);
|
||||
|
||||
UDP udp2(buffer, size);
|
||||
UDP udp2(&buffer[0], buffer.size());
|
||||
EXPECT_EQ(udp1.dport(), udp2.dport());
|
||||
EXPECT_EQ(udp1.sport(), udp2.sport());
|
||||
EXPECT_EQ(udp1.length(), udp2.length());
|
||||
EXPECT_EQ(udp1.size(), udp2.size());
|
||||
EXPECT_EQ(udp1.header_size(), udp2.header_size());
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user