add src/TinsNetworkInterfaceCard_t.h (send pdu and store their hash in a thread safe list)

This commit is contained in:
stubbfel
2017-03-02 00:14:53 +01:00
parent 1664136d14
commit 1f40e10d5c
6 changed files with 233 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
#include <memory>
#include <vector>
#ifndef MAIN_T_H
#define MAIN_T_H

View File

@@ -0,0 +1,110 @@
#include "TinsNetworkInterfaceCard.h"
#include <functional>
#include <mutex>
#include <tins/packet_sender.h>
#include <tins/network_interface.h>
#include <tins/sniffer.h>
ByteVectorHash TinsNetworkInterfaceCard::byteVectorHash;
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard() : TinsNetworkInterfaceCard(Tins::NetworkInterface::default_interface())
{
}
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const std::string& name) : TinsNetworkInterfaceCard(name.c_str())
{
}
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const char* name) : TinsNetworkInterfaceCard(Tins::NetworkInterface(name))
{
}
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::IPv4Address & ip) : TinsNetworkInterfaceCard(Tins::NetworkInterface(ip))
{
}
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::IPv6Address & ipv6) : TinsNetworkInterfaceCard(Tins::NetworkInterface(ipv6))
{
}
TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface)
{
snifferConfig = std::make_unique<Tins::SnifferConfiguration>();
snifferConfig->set_promisc_mode(true);
snifferConfig->set_immediate_mode(true);
sniffer = std::make_unique<Tins::Sniffer>(networkInterface.name());
packetSender = std::make_unique<Tins::PacketSender>(networkInterface);
sendPduHashList = std::make_unique<HashList>();
hashListMutex = std::make_unique<std::mutex>();
}
TinsNetworkInterfaceCard::~TinsNetworkInterfaceCard()
{
}
bool TinsNetworkInterfaceCard::handle(const Tins::PDU &pdu, IPacketHandler *callBackHandler)
{
return false;
}
void TinsNetworkInterfaceCard::sendPacket(const Tins::PDU &pdu)
{
Tins::PDU * clonePdu = pdu.clone();
if (clonePdu == nullptr){
return;
}
Tins::PDU & clonePduRef = *clonePdu;
Tins::PDU * phyLayerLessPdu = getPhyLessPduPtr(clonePduRef);
// layer3 only
if (phyLayerLessPdu != nullptr)
{
packetSender->send(clonePduRef);
}
delete clonePdu;
}
void TinsNetworkInterfaceCard::addPduToHashList(IN Tins::PDU &pdu)
{
std::lock_guard<std::mutex> lockGuard(*hashListMutex);
const ByteVector byteVector = pdu.serialize();
const std::size_t byteVectorHashValue = byteVectorHash(byteVector);
sendPduHashList->push_back(byteVectorHashValue);
}
bool TinsNetworkInterfaceCard::searchAndRemoveHashListItem(IN const std::size_t removedHash)
{
std::lock_guard<std::mutex> lockGuard(*hashListMutex);
const HashList::const_iterator start = sendPduHashList->cbegin();
const HashList::const_iterator end = sendPduHashList->cend();
const HashList::const_iterator findIt = std::find(start, end, removedHash);
if (findIt == end)
{
return false;
}
sendPduHashList->erase(findIt);
return true;
}
void TinsNetworkInterfaceCard::startListen()
{
}
void TinsNetworkInterfaceCard::stopListen()
{
}
Tins::PDU * TinsNetworkInterfaceCard::getPhyLessPduPtr(IN const Tins::PDU & pdu) const
{
return pdu.inner_pdu();
}

View File

@@ -0,0 +1,40 @@
#ifndef TINSNETWORKINTERFACECARD_H
#define TINSNETWORKINTERFACECARD_H
#include "TinsNetworkInterfaceCard_t.h"
#include "INetworkInterfaceCard_t.h"
#include "INetworkInterfaceCard.h"
#include "Ip4Packet_t.h"
#include "Ip6Packet_t.h"
class TinsNetworkInterfaceCard : public INetworkInterfaceCard
{
public:
TinsNetworkInterfaceCard();
TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface);
TinsNetworkInterfaceCard(const std::string& name);
TinsNetworkInterfaceCard(const char* name);
TinsNetworkInterfaceCard(const Tins::IPv4Address & ip);
TinsNetworkInterfaceCard(const Tins::IPv6Address & ipv6);
virtual ~TinsNetworkInterfaceCard();
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
virtual void sendPacket(IN const Tins::PDU & pdu) override;
virtual void startListen() override;
virtual void stopListen() override;
private:
Tins::PDU * getPhyLessPduPtr(IN const Tins::PDU & pdu) const;
void addPduToHashList(IN Tins::PDU &pdu);
bool searchAndRemoveHashListItem(IN const std::size_t removedHash);
UPtrSniffer sniffer;
UPtrSnifferConfiguration snifferConfig;
UPtrPacketSender packetSender;
static ByteVectorHash byteVectorHash;
UPtrHashList sendPduHashList;
UPtrMutex hashListMutex;
};
#endif

View File

@@ -0,0 +1,58 @@
#ifndef TINSNETWORKINTERFACECARD_T_H
#define TINSNETWORKINTERFACECARD_T_H
#include <functional>
#include <vector>
#include "Main_t.h"
typedef std::vector<uint8_t> ByteVector;
namespace Tins
{
class NetworkInterface;
class PacketSender;
class Sniffer;
class SnifferConfiguration;
}
typedef std::unique_ptr<Tins::Sniffer> UPtrSniffer;
typedef std::unique_ptr<Tins::SnifferConfiguration> UPtrSnifferConfiguration;
typedef std::unique_ptr<Tins::PacketSender> UPtrPacketSender;
namespace std
{
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
template<>
struct hash<ByteVector>
{
std::size_t operator()(ByteVector const& byte_vector) const
{
std::size_t resultHash = 0;
for (uint8_t byte : byte_vector)
{
hash_combine(resultHash, byte);
}
return resultHash;
}
};
class mutex;
}
typedef std::hash<ByteVector> ByteVectorHash;
typedef std::shared_ptr<std::mutex> SPtrMutex;
typedef std::unique_ptr<std::mutex> UPtrMutex;
typedef std::vector<size_t> HashList;
typedef std::shared_ptr<HashList> SPtrrHashList;
typedef std::unique_ptr<HashList> UPtrHashList;
#endif

View File

@@ -1,5 +1,5 @@
#include "fakeit.hpp"
#include "tins/ethernetII.h"
#include <fakeit.hpp>
#include <tins/ethernetII.h>
#include <tins/ip.h>
#include <tins/ipv6.h>
#include <tins/ip_address.h>
@@ -7,8 +7,11 @@
#include <tins/tcp.h>
#include "Ip6ToIp4PacketHandler.h"
#include "IpAddressTranslator.h"
#include "TinsNetworkInterfaceCard_t.h"
using namespace fakeit;
namespace TestIp6ToIp4PacketHandler
{
Tins::PDU * currentInputPdu = nullptr;
@@ -57,4 +60,22 @@ TEST_CASE( "test Ip6ToIp4PacketHandler", "[Ip6ToIp4PacketHandler]" ) {
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::1", "::2") / Tins::TCP();
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
Verify(Method(mockHandler, handle)).Twice();
// test pkt hashes
Tins::EthernetII * clonePkt = pkt.clone();
REQUIRE((long) clonePkt != (long) &pkt);
Tins::PDU::serialization_type ser_pkt = pkt.serialize();
Tins::PDU::serialization_type ser_clonepkt = clonePkt->serialize();
REQUIRE(ser_pkt == ser_clonepkt);
Tins::PDU & pdu = *((Tins::PDU *)&pkt);
std::hash<Tins::PDU::serialization_type>pdu_hash;
std::size_t h1 = pdu_hash(ser_pkt);
std::size_t h2 = pdu_hash(ser_clonepkt);
REQUIRE(h1 == h2);
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::2", "::1") / Tins::TCP();
ser_pkt = pkt.serialize();
h1 = pdu_hash(ser_pkt);
REQUIRE(h1 != h2);
}