diff --git a/lib/libtins b/lib/libtins index f06a508..0600181 160000 --- a/lib/libtins +++ b/lib/libtins @@ -1 +1 @@ -Subproject commit f06a508b2c61d530d4e3e576058b05b80b655bf9 +Subproject commit 06001815aeba98e7a5a8c67e345d468336caec9a diff --git a/src/INetworkInterfaceCard.h b/src/INetworkInterfaceCard.h index a3a629a..343b884 100644 --- a/src/INetworkInterfaceCard.h +++ b/src/INetworkInterfaceCard.h @@ -1,6 +1,7 @@ #ifndef INETWORKINTERFACECARD_H #define INETWORKINTERFACECARD_H +#include "INetworkInterfaceCard_t.h" #include "IPacketHandler.h" interface INetworkInterfaceCard : IPacketHandler @@ -8,5 +9,6 @@ interface INetworkInterfaceCard : IPacketHandler virtual void sendPacket(IN const Tins::PDU & pdu) = 0; virtual void startListen() = 0; virtual void stopListen() = 0; + virtual size_t getMtu() const = 0; }; #endif diff --git a/src/INetworkInterfaceCard_t.h b/src/INetworkInterfaceCard_t.h index ce99f3c..311b956 100644 --- a/src/INetworkInterfaceCard_t.h +++ b/src/INetworkInterfaceCard_t.h @@ -5,6 +5,10 @@ #include #include "Main_t.h" +#ifndef DEFAULT_MTU_VAULE +#define DEFAULT_MTU_VAULE 1500 +#endif + interface IPacketHandler; diff --git a/src/IpPacketFragmentation.cpp b/src/IpPacketFragmentation.cpp index f6524f0..95c7af5 100644 --- a/src/IpPacketFragmentation.cpp +++ b/src/IpPacketFragmentation.cpp @@ -1,6 +1,8 @@ #include "IpPacketFragmentation.h" +#include #include #include +#include const size_t IpPacketFragmentation::fragmentionHeadersize = sizeof (FragmentionHeaderUnion) - 1; @@ -16,13 +18,13 @@ IpPacketFragmentation::~IpPacketFragmentation() void IpPacketFragmentation::addExtensionHeader(IN const uint8_t nextHeader, IN const uint8_t *startPtr, IN Tins::IPv6 & ipFragmentPdu, const size_t headersize) { - Tins::IPv6::ext_header extensionHeader(nextHeader, headersize , startPtr); + Tins::IPv6::ext_header extensionHeader(nextHeader, 6 , startPtr); ipFragmentPdu.add_ext_header(extensionHeader); } void IpPacketFragmentation::initFragmentationHeader(FragmentionHeaderStruct* ptrFragmentionHeaderStruct) { - ptrFragmentionHeaderStruct->NextHeader = Tins::IPv6::FRAGMENT; + ptrFragmentionHeaderStruct->NextHeader = Tins::Constants::IP::PROTO_TCP; ptrFragmentionHeaderStruct->Reserved = 0; ptrFragmentionHeaderStruct->Res = 0; ptrFragmentionHeaderStruct->MFlag = 1; @@ -43,7 +45,7 @@ bool IpPacketFragmentation::handle(IN const Tins::PDU & pdu, IN IPacketHandler * return callBackHandler->handle(pdu, this); } - const Tins::IPv6 * ipPdu = pdu.find_pdu(); + Tins::IPv6 * ipPdu = pdu.clone()->find_pdu(); if (ipPdu == nullptr) { return false; @@ -55,30 +57,41 @@ bool IpPacketFragmentation::handle(IN const Tins::PDU & pdu, IN IPacketHandler * return false; } - ByteVector ipPayload = ipDataPdu->serialize(); + ByteVector ipPayload2 = ipPdu->serialize(); + ByteVector ipPayload(ipPayload2.begin() + ipPdu->header_size(), ipPayload2.end()); + uint8_t originNextHeader = ipPdu->next_header(); const long ipPayloadSize = static_cast(ipPayload.size()); - const long fragmentationSize = static_cast(ipPayload.size() / fragmentationCount); + const long fragmentationSize64B = (ipPayloadSize/ static_cast(fragmentationCount)) / 64; + const long fragmentationSize = fragmentationSize64B * 64; const long payLoadEndIndicator = ipPayloadSize - fragmentationSize; ByteVector::iterator fragmentPosIt = ipPayload.begin(); FragmentionHeaderUnion fragmentionHeaderUnion; FragmentionHeaderStruct * ptrFragmentionHeaderStruct = &fragmentionHeaderUnion.Structed; - uint8_t * ptrStartFragmentionHeader = &fragmentionHeaderUnion.Bytes[1]; + uint8_t * ptrStartFragmentionHeader = &fragmentionHeaderUnion.Bytes[2]; initFragmentationHeader(ptrFragmentionHeaderStruct); - for (ptrFragmentionHeaderStruct->FragmentOffset = 0; ptrFragmentionHeaderStruct->FragmentOffset < payLoadEndIndicator; ptrFragmentionHeaderStruct->FragmentOffset += fragmentationSize) + + long frameOffset; + for (frameOffset = 0; frameOffset < payLoadEndIndicator; frameOffset += fragmentationSize) { ByteVector::iterator fragmentStart = fragmentPosIt; fragmentPosIt = fragmentStart + fragmentationSize; - if (!createAndForwardFragmend(pdu, fragmentStart, fragmentPosIt, ptrFragmentionHeaderStruct, ptrStartFragmentionHeader, callBackHandler)) + ptrFragmentionHeaderStruct->FragmentOffset = static_cast(frameOffset) / 8; + std::swap(fragmentionHeaderUnion.Bytes[2],fragmentionHeaderUnion.Bytes[3]); + if (!createAndForwardFragmend(originNextHeader,pdu, fragmentStart, fragmentPosIt, ptrFragmentionHeaderStruct, ptrStartFragmentionHeader, callBackHandler)) { return false; } + + std::swap(fragmentionHeaderUnion.Bytes[2],fragmentionHeaderUnion.Bytes[3]); } ptrFragmentionHeaderStruct->MFlag = 0; - return createAndForwardFragmend(pdu, fragmentPosIt, ipPayload.end(), ptrFragmentionHeaderStruct, ptrStartFragmentionHeader, callBackHandler); + ptrFragmentionHeaderStruct->FragmentOffset = static_cast(frameOffset) / 8; + std::swap(fragmentionHeaderUnion.Bytes[2],fragmentionHeaderUnion.Bytes[3]); + return createAndForwardFragmend(originNextHeader, pdu, fragmentPosIt, ipPayload.end(), ptrFragmentionHeaderStruct, ptrStartFragmentionHeader, callBackHandler); } -bool IpPacketFragmentation::createAndForwardFragmend(IN const Tins::PDU & pdu, IN const ByteVector::iterator & fragmentStart, IN const ByteVector::iterator & fragmentPosIt, IN FragmentionHeaderStruct * ptrFragmentionHeaderStruct, IN uint8_t * ptrStartFragmentionHeader, IN IPacketHandler * callBackHandler) +bool IpPacketFragmentation::createAndForwardFragmend(IN const uint8_t originNextHeader, IN const Tins::PDU & pdu, IN const ByteVector::iterator & fragmentStart, IN const ByteVector::iterator & fragmentPosIt, IN FragmentionHeaderStruct * ptrFragmentionHeaderStruct, IN uint8_t * ptrStartFragmentionHeader, IN IPacketHandler * callBackHandler) { SPtrByteVector fragmentPayload = std::make_shared(fragmentStart, fragmentPosIt); Tins::PDU * fragmentPdu = pdu.clone(); @@ -93,11 +106,9 @@ bool IpPacketFragmentation::createAndForwardFragmend(IN const Tins::PDU & pdu, I return false; } - // Tins::IPv6::ext_header fragmentionHeader(ptrFragmentionHeaderStruct->NextHeader, IpPacketFragmentation::fragmentionHeadersize , ptrStartFragmentionHeader); - // ipFragmentPdu->add_ext_header(fragmentionHeader); - addExtensionHeader(ptrFragmentionHeaderStruct->NextHeader, ptrStartFragmentionHeader, *ipFragmentPdu, IpPacketFragmentation::fragmentionHeadersize); - addExtensionHeader(Tins::IPv6::NO_NEXT_HEADER, nullptr, *ipFragmentPdu, 0); + addExtensionHeader(originNextHeader, ptrStartFragmentionHeader, *ipFragmentPdu, IpPacketFragmentation::fragmentionHeadersize); SPtrRawPDU rawFragmentPdu = std::make_shared(fragmentPayload->data(), static_cast(fragmentPayload->size())); ipFragmentPdu->inner_pdu(rawFragmentPdu.get()); + ipFragmentPdu->next_header(Tins::IPv6::FRAGMENT); return callBackHandler->handle(*fragmentPdu, this); } diff --git a/src/IpPacketFragmentation.h b/src/IpPacketFragmentation.h index 8c348d1..5bde812 100644 --- a/src/IpPacketFragmentation.h +++ b/src/IpPacketFragmentation.h @@ -19,7 +19,7 @@ private: uint32_t idCounter; static const size_t fragmentionHeadersize; static void addExtensionHeader(IN const uint8_t NextHeader, IN const uint8_t *startPtr, IN Tins::IPv6 & ipFragmentPdu, IN const size_t headersize); - bool createAndForwardFragmend(IN const Tins::PDU & pdu, IN const ByteVector::iterator & fragmentStart, IN const ByteVector::iterator & fragmentPosIt, IN FragmentionHeaderStruct * ptrFragmentionHeaderStruct, IN uint8_t * ptrStartFragmentionHeader, IN IPacketHandler * callBackHandler); + bool createAndForwardFragmend(IN const uint8_t originNextHeader, IN const Tins::PDU & pdu, IN const ByteVector::iterator & fragmentStart, IN const ByteVector::iterator & fragmentPosIt, IN FragmentionHeaderStruct * ptrFragmentionHeaderStruct, IN uint8_t * ptrStartFragmentionHeader, IN IPacketHandler * callBackHandler); void initFragmentationHeader(FragmentionHeaderStruct* ptrFragmentionHeaderStruct); }; diff --git a/src/IpPacketFragmentation_t.h b/src/IpPacketFragmentation_t.h index a0e9070..378393b 100644 --- a/src/IpPacketFragmentation_t.h +++ b/src/IpPacketFragmentation_t.h @@ -5,9 +5,9 @@ class IpPacketFragmentation; typedef IpPacketFragmentation * PtrIpPacketFragmentation; -typedef std::shared_ptr * SPtrIpPacketFragmentation; -typedef std::unique_ptr * UPtrIpPacketFragmentation; -typedef std::weak_ptr * WPtrIpPacketFragmentation; +typedef std::shared_ptr SPtrIpPacketFragmentation; +typedef std::unique_ptr UPtrIpPacketFragmentation; +typedef std::weak_ptr WPtrIpPacketFragmentation; namespace Tins { @@ -36,5 +36,20 @@ union FragmentionHeaderUnion uint8_t Bytes[8]; }; + +struct tcp_header_s { + uint16_t sport; + uint16_t dport; + uint32_t seq; + uint32_t ack_seq; + uint8_t doff:4, + res1:4; + union { + uint8_t flags_8; + }; + uint16_t window; + uint16_t check; + uint16_t urg_ptr; + }; #pragma pack(pop) #endif // IPPACKETFRAGMENTATION_T_H diff --git a/src/IpVersionRouter.cpp b/src/IpVersionRouter.cpp index d4fa038..27e83b7 100644 --- a/src/IpVersionRouter.cpp +++ b/src/IpVersionRouter.cpp @@ -3,11 +3,13 @@ #include #include #include "INetworkInterfaceCard.h" +#include "IpPacketFragmentation.h" IpVersionRouter::IpVersionRouter(SPtrINetworkInterfaceCard netv4Card, SPtrINetworkInterfaceCard netv6Card) { ipv4Card = netv4Card; ipv6Card = netv6Card; + ipv6Fragmentation = std::make_unique(ipv6Card->getMtu()); } IpVersionRouter::~IpVersionRouter() @@ -19,8 +21,13 @@ bool IpVersionRouter::handle(IN const Tins::PDU & pdu, IN IPacketHandler * /* ca const Tins::IPv6 * ipv6Pdu = pdu.find_pdu(); if(ipv6Pdu != nullptr) { - ipv6Card->sendPacket(pdu); - return true; + if (pdu.size() < ipv6Card->getMtu()) + { + ipv6Card->sendPacket(pdu); + return true; + } + + return ipv6Fragmentation->handle(pdu, this); } const Tins::IP * ipv4Pdu = pdu.find_pdu(); diff --git a/src/IpVersionRouter.h b/src/IpVersionRouter.h index d3ed00a..518c183 100644 --- a/src/IpVersionRouter.h +++ b/src/IpVersionRouter.h @@ -4,6 +4,7 @@ #include "AbstractRouter.h" #include "INetworkInterfaceCard_t.h" + class IpVersionRouter: public AbstractRouter { public: @@ -19,6 +20,7 @@ private: SPtrINetworkInterfaceCard ipv6Card; SPtrINetworkInterfaceCard ipv4Card; + UPtrIPacketHandler ipv6Fragmentation; }; #endif // ABSTRACTROUTER_H diff --git a/src/Main.cpp b/src/Main.cpp index 7c7419c..1e23928 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -39,6 +39,10 @@ int main(int argc, char** argv) const int itemtype = natPairItem["type"].asInt(); const std::string netcardName = natPairItem["nic-name"].asString(); SPtrTinsNetworkInterfaceCard netcard = std::make_shared(netcardName); + if(natPairItem.isMember("mtu")) + { + netcard->setMtu(static_cast(natPairItem["mtu"].asInt())); + } switch (itemtype) { case 4: diff --git a/src/TinsNetworkInterfaceCard.cpp b/src/TinsNetworkInterfaceCard.cpp index bd71da6..322e2fc 100644 --- a/src/TinsNetworkInterfaceCard.cpp +++ b/src/TinsNetworkInterfaceCard.cpp @@ -33,7 +33,7 @@ TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::IPv6Address & ipv } -TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface) : sniffNetworkInterfaceName(networkInterface.name()) +TinsNetworkInterfaceCard::TinsNetworkInterfaceCard(const Tins::NetworkInterface & networkInterface) : mtu(DEFAULT_MTU_VAULE), sniffNetworkInterfaceName(networkInterface.name()) { snifferConfig = std::make_unique(); snifferConfig->set_promisc_mode(true); @@ -111,11 +111,7 @@ void TinsNetworkInterfaceCard::sendPacket(const Tins::PDU &pdu) if (phyLayerLessPdu != nullptr) { addPduToHashList(*phyLayerLessPdu); - printf("len: %u, type: %s \n", clonePduRef.size(), typeid(clonePduRef).name()); - if (clonePduRef.size() < 1500) - { - packetSender->send(clonePduRef); - } + packetSender->send(clonePduRef); } delete clonePdu; @@ -171,7 +167,12 @@ void TinsNetworkInterfaceCard::stopListen() Tins::EthernetII pkt = Tins::EthernetII(); packetSender->send(pkt); std::lock_guard lockGuard(*hashListMutex); - sendPduHashList->clear(); + sendPduHashList->clear(); +} + +size_t TinsNetworkInterfaceCard::getMtu() const +{ + return DEFAULT_MTU_VAULE; } Tins::PDU * TinsNetworkInterfaceCard::getPhyLessPduPtr(IN Tins::PDU & pdu) const @@ -204,3 +205,8 @@ bool TinsNetworkInterfaceCard::isSniffRunning() const { return isSnifferRunning; } + +void TinsNetworkInterfaceCard::setMtu(const size_t &value) +{ + mtu = value; +} diff --git a/src/TinsNetworkInterfaceCard.h b/src/TinsNetworkInterfaceCard.h index 28fe0ae..29dfb2a 100644 --- a/src/TinsNetworkInterfaceCard.h +++ b/src/TinsNetworkInterfaceCard.h @@ -3,7 +3,6 @@ #include #include "TinsNetworkInterfaceCard_t.h" -#include "INetworkInterfaceCard_t.h" #include "INetworkInterfaceCard.h" #include "Ip4Packet_t.h" #include "Ip6Packet_t.h" @@ -24,14 +23,17 @@ public: virtual void sendPacket(IN const Tins::PDU & pdu) override; virtual void startListen() override; virtual void stopListen() override; + virtual size_t getMtu() const override; Tins::SnifferConfiguration & getSnifferConfig() const; SPtrIPacketHandlerList & getHandlerList(); bool isSniffRunning() const; -private: + void setMtu(const size_t &value); - bool tinsSnifferCallback(IN Tins::PDU & some_pdu); +private: + size_t mtu; + 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); diff --git a/test/src/TestIp6Fragmentation.cpp b/test/src/TestIp6Fragmentation.cpp index 2ae4e48..e4c5936 100644 --- a/test/src/TestIp6Fragmentation.cpp +++ b/test/src/TestIp6Fragmentation.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -42,14 +43,15 @@ namespace TestIp6PacketFragmentation FragmentionHeaderUnion fragmentionHeaderUnion; FragmentionHeaderStruct * ptrFragmentionHeaderStruct = &fragmentionHeaderUnion.Structed; - std::memcpy(&fragmentionHeaderUnion.Bytes[1], fragmentHeader->data_ptr(), fragmentHeader->data_size()); + std::memcpy(&fragmentionHeaderUnion.Bytes[2], fragmentHeader->data_ptr(), fragmentHeader->data_size()); + std::swap(fragmentionHeaderUnion.Bytes[2],fragmentionHeaderUnion.Bytes[3]); uint16_t mFlag = fragmentationCount > 1 ? 1 : 0; if (firstFragment) { firstFragment = false; id = ptrFragmentionHeaderStruct->Identification; } - REQUIRE(fragmentHeader->option() == Tins::IPv6::FRAGMENT); + REQUIRE(fragmentHeader->option() == Tins::Constants::IP::PROTO_TCP); REQUIRE(ptrFragmentionHeaderStruct->Reserved == 0); REQUIRE(ptrFragmentionHeaderStruct->Res == 0); REQUIRE(ptrFragmentionHeaderStruct->MFlag == mFlag); @@ -81,7 +83,7 @@ TEST_CASE( "test Ip6PacketFragmentation", "[Ip6PacketFragmentation]" ) { Tins::EthernetII pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / mtuPayload; TestIp6PacketFragmentation::currentInputPdu = &pkt; - TestIp6PacketFragmentation::fragmentationCount = 2; + TestIp6PacketFragmentation::fragmentationCount = 3; TestIp6PacketFragmentation::maxfragmentationSize = mtu/2; REQUIRE(handler.handle(pkt, nullptr) == false); @@ -93,7 +95,7 @@ TEST_CASE( "test Ip6PacketFragmentation", "[Ip6PacketFragmentation]" ) { REQUIRE(handler.handle(pkt, &mockHandler.get()) == false); - pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::1", "::2") / mtuPayload; + pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::1", "::2") / Tins::TCP(1,1) /mtuPayload; REQUIRE(handler.handle(pkt, &mockHandler.get()) == true); - Verify(Method(mockHandler, handle)).Twice(); + Verify(Method(mockHandler, handle)).Exactly(3); } diff --git a/test/src/TestMain.cpp b/test/src/TestMain.cpp index af8daa1..a927a67 100644 --- a/test/src/TestMain.cpp +++ b/test/src/TestMain.cpp @@ -26,6 +26,7 @@ TEST_CASE( "test main setup", "[test_main]" ) SPtrIPacketHandlerList routerList; std::vector threadPool; + int mtuCount = 0; for (Json::Value natpair : natpairs) { const std::string pairname = natpair["name"].asString(); @@ -48,6 +49,11 @@ TEST_CASE( "test main setup", "[test_main]" ) const std::string netcardName = natPairItem["nic-name"].asString(); SPtrTinsNetworkInterfaceCard netcard = std::make_shared(netcardName); + if(natPairItem.isMember("mtu")) + { + mtuCount++; + REQUIRE(natPairItem["mtu"].asInt() == 1000); + } switch (itemtype) { case 4: @@ -62,6 +68,7 @@ TEST_CASE( "test main setup", "[test_main]" ) } } + REQUIRE(mtuCount ==1); SPtrIPacketHandler ip4ToIp6Handler = std::make_shared(prefix); SPtrIPacketHandler ip6ToIp4Handler = std::make_shared(); SPtrIPacketHandler icmp4ToIcmp6Handler = std::make_shared(prefix); diff --git a/test/src/test_config.json b/test/src/test_config.json index 2a87f56..31608e0 100644 --- a/test/src/test_config.json +++ b/test/src/test_config.json @@ -10,6 +10,7 @@ { "nic-name": "lo", "type": 6, + "mtu": 1000, "prefix": "42::" } ]