diff --git a/src/TinsNetworkInterfaceCard.cpp b/src/TinsNetworkInterfaceCard.cpp index c184e4f..f72b624 100644 --- a/src/TinsNetworkInterfaceCard.cpp +++ b/src/TinsNetworkInterfaceCard.cpp @@ -32,40 +32,67 @@ TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::IPv6Address & ipv } -TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface) +TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface) : sniffNetworkInterfaceName(networkInterface.name()) { snifferConfig = std::make_unique(); snifferConfig->set_promisc_mode(true); snifferConfig->set_immediate_mode(true); - sniffer = std::make_unique(networkInterface.name()); packetSender = std::make_unique(networkInterface); sendPduHashList = std::make_unique(); hashListMutex = std::make_unique(); + isSnifferRunning = false; } TinsNetworkInterfaceCard::~TinsNetworkInterfaceCard() { + stopListen(); } bool TinsNetworkInterfaceCard::handle(const Tins::PDU &pdu, IPacketHandler *callBackHandler) { - return false; + if (!isSnifferRunning) + { + return false; + } + + Tins::PDU * clonePdu = pdu.clone(); + if (clonePdu == nullptr) + { + return true; + } + + //was the pdu sent by me? + Tins::PDU * phyLayerLessPdu = getPhyLessPduPtr(*clonePdu); + const ByteVector byteVector = phyLayerLessPdu->serialize(); + delete clonePdu; + const std::size_t byteVectorHashValue = byteVectorHash(byteVector); + if(searchAndRemoveHashListItem(byteVectorHashValue)) + { + return true; + } + + for (SPtrIPacketHandler handler: handlerList) + { + handler->handle(pdu, nullptr); + } + + return true; } void TinsNetworkInterfaceCard::sendPacket(const Tins::PDU &pdu) { Tins::PDU * clonePdu = pdu.clone(); - if (clonePdu == nullptr){ + if (clonePdu == nullptr) + { return; } Tins::PDU & clonePduRef = *clonePdu; Tins::PDU * phyLayerLessPdu = getPhyLessPduPtr(clonePduRef); - // layer3 only if (phyLayerLessPdu != nullptr) { - + addPduToHashList(*phyLayerLessPdu); packetSender->send(clonePduRef); } @@ -74,9 +101,14 @@ void TinsNetworkInterfaceCard::sendPacket(const Tins::PDU &pdu) void TinsNetworkInterfaceCard::addPduToHashList(IN Tins::PDU &pdu) { - std::lock_guard lockGuard(*hashListMutex); + if (!isSnifferRunning) + { + return; + } + const ByteVector byteVector = pdu.serialize(); const std::size_t byteVectorHashValue = byteVectorHash(byteVector); + std::lock_guard lockGuard(*hashListMutex); sendPduHashList->push_back(byteVectorHashValue); } @@ -97,12 +129,28 @@ bool TinsNetworkInterfaceCard::searchAndRemoveHashListItem(IN const std::size_t void TinsNetworkInterfaceCard::startListen() { + if (isSnifferRunning) + { + return; + } + UPtrSniffer sniffer = std::make_unique(sniffNetworkInterfaceName, *snifferConfig); + isSnifferRunning = true; + sniffer->sniff_loop(make_sniffer_handler(this, &TinsNetworkInterfaceCard::tinsSnifferCallback)); } void TinsNetworkInterfaceCard::stopListen() { + if (!isSnifferRunning) + { + return; + } + isSnifferRunning = false; + Tins::EthernetII pkt = Tins::EthernetII(); + packetSender->send(pkt); + std::lock_guard lockGuard(*hashListMutex); + sendPduHashList->clear(); } Tins::PDU * TinsNetworkInterfaceCard::getPhyLessPduPtr(IN Tins::PDU & pdu) const @@ -115,3 +163,23 @@ Tins::PDU * TinsNetworkInterfaceCard::getPhyLessPduPtr(IN Tins::PDU & pdu) const return getPhyLessPduPtr(*(ethPdu->inner_pdu())); } + +Tins::SnifferConfiguration & TinsNetworkInterfaceCard::getSnifferConfig() const +{ + return *snifferConfig; +} + +bool TinsNetworkInterfaceCard::tinsSnifferCallback(Tins::PDU &some_pdu) +{ + return handle(some_pdu, nullptr); +} + +SPtrIPacketHandlerList & TinsNetworkInterfaceCard::getHandlerList() +{ + return handlerList; +} + +bool TinsNetworkInterfaceCard::isSniffRunning() const +{ + return isSnifferRunning; +} diff --git a/src/TinsNetworkInterfaceCard.h b/src/TinsNetworkInterfaceCard.h index 11bd0db..b9b0d50 100644 --- a/src/TinsNetworkInterfaceCard.h +++ b/src/TinsNetworkInterfaceCard.h @@ -1,6 +1,7 @@ #ifndef TINSNETWORKINTERFACECARD_H #define TINSNETWORKINTERFACECARD_H +#include #include "TinsNetworkInterfaceCard_t.h" #include "INetworkInterfaceCard_t.h" #include "INetworkInterfaceCard.h" @@ -24,17 +25,24 @@ public: virtual void startListen() override; virtual void stopListen() override; + Tins::SnifferConfiguration & getSnifferConfig() const; + SPtrIPacketHandlerList & getHandlerList(); + bool isSniffRunning() const; + private: - Tins::PDU * getPhyLessPduPtr(IN Tins::PDU & pdu) const; + bool tinsSnifferCallback(IN Tins::PDU & some_pdu); + Tins::PDU * getPhyLessPduPtr(IN 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; + std::atomic isSnifferRunning; + SPtrIPacketHandlerList handlerList; + std::string sniffNetworkInterfaceName; }; #endif diff --git a/src/TinsNetworkInterfaceCard_t.h b/src/TinsNetworkInterfaceCard_t.h index 6e9e7ff..688ac35 100644 --- a/src/TinsNetworkInterfaceCard_t.h +++ b/src/TinsNetworkInterfaceCard_t.h @@ -55,4 +55,8 @@ typedef std::unique_ptr UPtrMutex; typedef std::vector HashList; typedef std::shared_ptr SPtrrHashList; typedef std::unique_ptr UPtrHashList; + +class TinsNetworkInterfaceCard; + +typedef std::shared_ptr SPtrTinsNetworkInterfaceCard; #endif diff --git a/test/src/TestTinsNetworkCard.cpp b/test/src/TestTinsNetworkCard.cpp new file mode 100644 index 0000000..4956e65 --- /dev/null +++ b/test/src/TestTinsNetworkCard.cpp @@ -0,0 +1,90 @@ +#include "fakeit.hpp" +#include +#include +#include "tins/ethernetII.h" +#include +#include +#include +#include +#include +#include +#include "TinsNetworkInterfaceCard.h" + +using namespace fakeit; + + +namespace TestTinsNetworkInterfaceCard +{ + Tins::PDU * currentInputPdu = nullptr; + int foundPduCount; + + struct MockPacketHandler : IPacketHandler + { + virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override + { + const Tins::IP * ip1 = pdu.find_pdu(); + const Tins::IP * ip2 = currentInputPdu->find_pdu(); + if(ip1 != nullptr && (ip1->dst_addr() == ip2->dst_addr())) + { + foundPduCount++; + } + + return true; + } + }; +} + +TEST_CASE( "test send and receive Packet", "[TinsNetworkInterfaceCard_SendRec]" ) +{ + + SPtrTinsNetworkInterfaceCard ptrPacketSender = std::make_shared(); + SPtrTinsNetworkInterfaceCard ptrPacketSniffer = std::make_shared(); + SPtrIPacketHandler sptrMockHandler = std::make_shared(); + Mock mockHandler(*sptrMockHandler); + TestTinsNetworkInterfaceCard::foundPduCount = 0; + ptrPacketSniffer->getHandlerList().push_back(sptrMockHandler); + Tins::EthernetII pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IP("1.2.3.4", "4.3.2.1") / Tins::TCP(); + TestTinsNetworkInterfaceCard::currentInputPdu = &pkt; + std::thread sniffThread(&TinsNetworkInterfaceCard::startListen, ptrPacketSniffer.get()); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSender->sendPacket(pkt); + ptrPacketSender->sendPacket(pkt); + ptrPacketSender->sendPacket(pkt); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSniffer->stopListen(); + ptrPacketSender->sendPacket(pkt); + ptrPacketSender->sendPacket(pkt); + ptrPacketSender->sendPacket(pkt); + sniffThread.join(); + REQUIRE(TestTinsNetworkInterfaceCard::foundPduCount == 3); + + std::thread sniffThread2(&TinsNetworkInterfaceCard::startListen, ptrPacketSniffer.get()); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSniffer->sendPacket(pkt); + ptrPacketSniffer->sendPacket(pkt); + ptrPacketSniffer->sendPacket(pkt); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSniffer->stopListen(); + ptrPacketSniffer->sendPacket(pkt); + ptrPacketSniffer->sendPacket(pkt); + ptrPacketSniffer->sendPacket(pkt); + sniffThread2.join(); + REQUIRE(TestTinsNetworkInterfaceCard::foundPduCount == 3); + + std::thread sniffThread3(&TinsNetworkInterfaceCard::startListen, ptrPacketSniffer.get()); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSniffer->sendPacket(pkt); + ptrPacketSender->sendPacket(pkt); + ptrPacketSniffer->sendPacket(pkt); + std::this_thread::sleep_for(std::chrono::seconds(2)); + ptrPacketSniffer->stopListen(); + sniffThread3.join(); + REQUIRE(TestTinsNetworkInterfaceCard::foundPduCount == 4); + /*REQUIRE(handler.handle(pkt, nullptr) == false); + REQUIRE(handler.handle(pkt, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).Once(); + + pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IP("1.2.3.4", "4.3.2.1") / Tins::TCP(); + REQUIRE(handler.handle(pkt, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).Twice();*/ +}