1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Added PDU::rfind_pdu.

This commit is contained in:
Matias Fontanini
2013-04-19 22:27:48 -03:00
parent 91bdcca577
commit 2ea952d6ab
8 changed files with 83 additions and 22 deletions

View File

@@ -30,12 +30,27 @@
#ifndef TINS_CXXSTD_H
#define TINS_CXXSTD_H
#include <memory>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINS_CXXSTD_GCC_FIX 1
#else
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
namespace Tins{
namespace Internals {
template<typename T>
struct smart_ptr {
#if TINS_IS_CXX11
typedef std::unique_ptr<T> type;
#else
typedef std::auto_ptr<T> type;
#endif
};
}
}
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
#endif // TINS_CXXSTD_H

View File

@@ -48,7 +48,7 @@ public:
};
/**
* \brief Exception thrown when an option is not found.
* \brief Exception thrown when a malformed packet is parsed.
*/
class malformed_packet : public std::runtime_error {
public:
@@ -56,7 +56,20 @@ public:
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "Option not found";
return "Malformed packet";
}
};
/**
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
*/
class pdu_not_found : public std::runtime_error {
public:
pdu_not_found()
: std::runtime_error(std::string()) { }
const char* what() const throw() {
return "PDU not found";
}
};
}

View File

@@ -35,6 +35,7 @@
#include <vector>
#include "macros.h"
#include "cxxstd.h"
#include "exceptions.h"
/** \brief The Tins namespace.
*/
@@ -220,14 +221,14 @@ namespace Tins {
serialization_type serialize();
/**
* \brief Find and returns the first PDU that matches the given flag.
* \brief Finds and returns the first PDU that matches the given flag.
*
* This method searches for the first PDU which has the same type flag as
* the given one. If the first PDU matches that flag, it is returned.
* If no PDU matches, 0 is returned.
* \param flag The flag which being searched.
*/
template<class T>
template<typename T>
T *find_pdu(PDUType type = T::pdu_flag) {
PDU *pdu = this;
while(pdu) {
@@ -239,15 +240,42 @@ namespace Tins {
}
/**
* \brief Find and returns the first PDU that matches the given flag.
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<class T>
template<typename T>
const T *find_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->find_pdu<T>();
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* If the PDU is not found, a pdu_not_found exception is thrown.
*
* \sa PDU::find_pdu
*
* \param flag The flag which being searched.
*/
template<typename T>
T &rfind_pdu(PDUType type = T::pdu_flag) {
T *ptr = find_pdu<T>(type);
if(!ptr)
throw pdu_not_found();
return *ptr;
}
/**
* \brief Finds and returns the first PDU that matches the given flag.
*
* \param flag The flag which being searched.
*/
template<typename T>
const T &rfind_pdu(PDUType type = T::pdu_flag) const {
return const_cast<PDU*>(this)->rfind_pdu<T>();
}
/**
* \brief Clones this packet.
*

View File

@@ -272,7 +272,7 @@ namespace Tins {
bool ret_val(false);
LoopData<Functor> *data = reinterpret_cast<LoopData<Functor>*>(args);
try {
std::auto_ptr<PDU> pdu;
Internals::smart_ptr<PDU>::type pdu;
if(data->iface_type == DLT_EN10MB)
ret_val = call_functor<Tins::EthernetII>(data, packet, header);
else if(data->iface_type == DLT_IEEE802_11_RADIO)

View File

@@ -54,7 +54,7 @@ DNSResourceRecord::DNSResourceRecord(DNSRRImpl *impl,
DNSResourceRecord::DNSResourceRecord(const uint8_t *buffer, uint32_t size)
{
const uint8_t *buffer_end = buffer + size;
std::auto_ptr<DNSRRImpl> tmp_impl;
Internals::smart_ptr<DNSRRImpl>::type tmp_impl;
if((*buffer & 0xc0)) {
uint16_t offset(*reinterpret_cast<const uint16_t*>(buffer));
offset = Endian::be_to_host(offset) & 0x3fff;

View File

@@ -117,11 +117,7 @@ bool resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip,
IPv4Address my_ip;
NetworkInterface::Info info(iface.addresses());
EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr);
#if TINS_IS_CXX11
std::unique_ptr<PDU> response(sender.send_recv(packet));
#else
std::auto_ptr<PDU> response(sender.send_recv(packet));
#endif
Internals::smart_ptr<PDU>::type response(sender.send_recv(packet));
if(response.get()) {
ARP *arp_resp = response->find_pdu<ARP>();
if(arp_resp)
@@ -137,12 +133,7 @@ HWAddress<6> resolve_hwaddr(const NetworkInterface &iface, IPv4Address ip, Packe
IPv4Address my_ip;
NetworkInterface::Info info(iface.addresses());
EthernetII packet = ARP::make_arp_request(iface, ip, info.ip_addr, info.hw_addr);
#if TINS_IS_CXX11
std::unique_ptr<PDU>
#else
std::auto_ptr<PDU>
#endif
response(sender.send_recv(packet));
Internals::smart_ptr<PDU>::type response(sender.send_recv(packet));
if(response.get()) {
const ARP *arp_resp = response->find_pdu<ARP>();
if(arp_resp)

View File

@@ -3,6 +3,7 @@
#include <memory>
#include <stdint.h>
#include "dot11.h"
#include "cxxstd.h"
#include "tests/dot11.h"
@@ -61,12 +62,12 @@ TEST_F(Dot11DataTest, SeqNum) {
TEST_F(Dot11DataTest, ClonePDU) {
Dot11Data dot1(expected_packet, sizeof(expected_packet));
std::auto_ptr<Dot11Data> dot2(dot1.clone());
Internals::smart_ptr<Dot11Data>::type dot2(dot1.clone());
test_equals(dot1, *dot2);
}
TEST_F(Dot11DataTest, FromBytes) {
std::auto_ptr<PDU> dot11(Dot11::from_bytes(expected_packet, sizeof(expected_packet)));
Internals::smart_ptr<PDU>::type dot11(Dot11::from_bytes(expected_packet, sizeof(expected_packet)));
ASSERT_TRUE(dot11.get());
const Dot11Data *inner = dot11->find_pdu<Dot11Data>();
ASSERT_TRUE(inner);
@@ -94,7 +95,7 @@ TEST_F(Dot11DataTest, PCAPLoad1) {
EXPECT_EQ(dot1.from_ds(), 1);
EXPECT_EQ(dot1.frag_num(), 0);
EXPECT_EQ(dot1.seq_num(), 1945);
std::auto_ptr<Dot11Data> dot2(dot1.clone());
Internals::smart_ptr<Dot11Data>::type dot2(dot1.clone());
test_equals(dot1, *dot2);
}

View File

@@ -4,6 +4,7 @@
#include <stdint.h>
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#include "rawpdu.h"
#include "pdu.h"
#include "packet.h"
@@ -15,6 +16,18 @@ class PDUTest : public testing::Test {
public:
};
TEST_F(PDUTest, FindPDU) {
IP ip = IP("192.168.0.1") / TCP(22, 52) / RawPDU("Test");
EXPECT_TRUE(ip.find_pdu<TCP>());
EXPECT_TRUE(ip.find_pdu<RawPDU>());
EXPECT_FALSE(ip.find_pdu<UDP>());
TCP &t1 = ip.rfind_pdu<TCP>();
const TCP &t2 = ip.rfind_pdu<TCP>();
(void)t1;
(void)t2;
EXPECT_THROW(ip.rfind_pdu<UDP>(), pdu_not_found);
}
TEST_F(PDUTest, OperatorConcat) {
std::string raw_payload = "Test";
IP ip = IP("192.168.0.1") / TCP(22, 52) / RawPDU(raw_payload);