add IpFragmentation
This commit is contained in:
98
src/IpPacketFragmentation.cpp
Normal file
98
src/IpPacketFragmentation.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "IpPacketFragmentation.h"
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/rawpdu.h>
|
||||
|
||||
IpPacketFragmentation::IpPacketFragmentation(const size_t newMtu) : mtu(newMtu), idCounter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IpPacketFragmentation::~IpPacketFragmentation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IpPacketFragmentation::addExtensionHeader(IN const uint8_t nextHeader, IN const uint8_t *startPtr, IN Tins::IPv6 & ipFragmentPdu)
|
||||
{
|
||||
Tins::IPv6::ext_header fragmentionHeader(nextHeader, fragmentionHeadersize , startPtr);
|
||||
ipFragmentPdu.add_ext_header(fragmentionHeader);
|
||||
}
|
||||
|
||||
void IpPacketFragmentation::initFragmentationHeader(FragmentionHeaderStruct* ptrFragmentionHeaderStruct)
|
||||
{
|
||||
ptrFragmentionHeaderStruct->NextHeader = Tins::IPv6::FRAGMENT;
|
||||
ptrFragmentionHeaderStruct->Reserved = 0;
|
||||
ptrFragmentionHeaderStruct->Res = 0;
|
||||
ptrFragmentionHeaderStruct->MFlag = 1;
|
||||
ptrFragmentionHeaderStruct->Identification = ++idCounter;
|
||||
}
|
||||
|
||||
bool IpPacketFragmentation::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
if (callBackHandler == nullptr || callBackHandler == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t originPduSize = pdu.size();
|
||||
const size_t fragmentationCount = originPduSize + 1;
|
||||
if (fragmentationCount < 2)
|
||||
{
|
||||
return callBackHandler->handle(pdu, this);
|
||||
}
|
||||
|
||||
const Tins::IPv6 * ipPdu = pdu.find_pdu<Tins::IPv6>();
|
||||
if (ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::PDU * ipDataPdu = ipPdu->inner_pdu();
|
||||
if (ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteVector ipPayload = ipDataPdu->serialize();
|
||||
const long ipPayloadSize = static_cast<const long>(ipPayload.size());
|
||||
const long fragmentationSize = static_cast<const long>(ipPayload.size() / fragmentationCount);
|
||||
const long payLoadEndIndicator = ipPayloadSize - fragmentationSize;
|
||||
ByteVector::iterator fragmentPosIt = ipPayload.begin();
|
||||
FragmentionHeaderUnion fragmentionHeaderUnion;
|
||||
FragmentionHeaderStruct * ptrFragmentionHeaderStruct = &fragmentionHeaderUnion.Structed;
|
||||
uint8_t * ptrStartFragmentionHeader = &fragmentionHeaderUnion.Bytes[1];
|
||||
initFragmentationHeader(ptrFragmentionHeaderStruct);
|
||||
for (ptrFragmentionHeaderStruct->FragmentOffset = 0; ptrFragmentionHeaderStruct->FragmentOffset < payLoadEndIndicator; ptrFragmentionHeaderStruct->FragmentOffset += fragmentationSize)
|
||||
{
|
||||
ByteVector::iterator fragmentStart = fragmentPosIt;
|
||||
fragmentPosIt = fragmentStart + fragmentationSize;
|
||||
if (!createAndForwardFragmend(pdu, fragmentStart, fragmentPosIt, ptrFragmentionHeaderStruct, ptrStartFragmentionHeader, callBackHandler))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ptrFragmentionHeaderStruct->MFlag = 0;
|
||||
return createAndForwardFragmend(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)
|
||||
{
|
||||
SPtrByteVector fragmentPayload = std::make_shared<ByteVector>(fragmentStart, fragmentPosIt);
|
||||
Tins::PDU * fragmentPdu = pdu.clone();
|
||||
if (fragmentPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::IPv6 * ipFragmentPdu = fragmentPdu->find_pdu<Tins::IPv6>();
|
||||
if (ipFragmentPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
addExtensionHeader(ptrFragmentionHeaderStruct->NextHeader, ptrStartFragmentionHeader, *ipFragmentPdu);
|
||||
SPtrRawPDU rawFragmentPdu = std::make_shared<Tins::RawPDU>(fragmentPayload->data(), static_cast<uint32_t>(fragmentPayload->size()));
|
||||
ipFragmentPdu->inner_pdu(rawFragmentPdu.get());
|
||||
return callBackHandler->handle(pdu, this);
|
||||
}
|
||||
27
src/IpPacketFragmentation.h
Normal file
27
src/IpPacketFragmentation.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef IPPACKETFRAGMENTATION_H
|
||||
#define IPPACKETFRAGMENTATION_H
|
||||
|
||||
#include "IpPacketFragmentation_t.h"
|
||||
#include "Ip6Packet_t.h"
|
||||
#include "AbstractPacketHandler.h"
|
||||
|
||||
class IpPacketFragmentation : public AbstractPacketHandler
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
IpPacketFragmentation(const size_t newMtu);
|
||||
virtual ~IpPacketFragmentation();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
private:
|
||||
const size_t mtu;
|
||||
uint32_t idCounter;
|
||||
static const size_t fragmentionHeadersize = sizeof (FragmentionHeaderUnion) - 1;
|
||||
static void addExtensionHeader(IN const uint8_t NextHeader, IN const uint8_t *startPtr, IN Tins::IPv6 & ipFragmentPdu);
|
||||
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);
|
||||
|
||||
void initFragmentationHeader(FragmentionHeaderStruct* ptrFragmentionHeaderStruct);
|
||||
};
|
||||
|
||||
#endif // IPPACKETFRAGMENTATION_H
|
||||
40
src/IpPacketFragmentation_t.h
Normal file
40
src/IpPacketFragmentation_t.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef IPPACKETFRAGMENTATION_T_H
|
||||
#define IPPACKETFRAGMENTATION_T_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
class IpPacketFragmentation;
|
||||
typedef IpPacketFragmentation * PtrIpPacketFragmentation;
|
||||
typedef std::shared_ptr<IpPacketFragmentation> * SPtrIpPacketFragmentation;
|
||||
typedef std::unique_ptr<IpPacketFragmentation> * UPtrIpPacketFragmentation;
|
||||
typedef std::weak_ptr<IpPacketFragmentation> * WPtrIpPacketFragmentation;
|
||||
|
||||
namespace Tins
|
||||
{
|
||||
class RawPDU;
|
||||
}
|
||||
|
||||
typedef std::unique_ptr<Tins::RawPDU> UPtrRawPDU;
|
||||
typedef std::weak_ptr<Tins::RawPDU> WPtrRawPDU;
|
||||
typedef std::shared_ptr<Tins::RawPDU> SPtrRawPDU;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct FragmentionHeaderStruct
|
||||
{
|
||||
uint8_t NextHeader;
|
||||
uint8_t Reserved;
|
||||
uint16_t MFlag:1;
|
||||
uint16_t Res:2;
|
||||
uint16_t FragmentOffset:13;
|
||||
uint32_t Identification;
|
||||
};
|
||||
|
||||
struct FragmentionHeaderUnion
|
||||
{
|
||||
FragmentionHeaderStruct Structed;
|
||||
uint8_t Bytes[8];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // IPPACKETFRAGMENTATION_T_H
|
||||
@@ -29,4 +29,12 @@ namespace std
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::vector<uint8_t> ByteVector;
|
||||
typedef std::shared_ptr<ByteVector> SPtrByteVector;
|
||||
|
||||
typedef std::vector<SPtrByteVector> ByteVectorList;
|
||||
typedef std::shared_ptr<ByteVectorList> SPtrByteVectorList;
|
||||
typedef std::unique_ptr<ByteVectorList> UPtrByteVectorList;
|
||||
typedef std::weak_ptr<ByteVectorList> WPtrByteVectorList;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
#define TINSNETWORKINTERFACECARD_T_H
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include "Main_t.h"
|
||||
|
||||
typedef std::vector<uint8_t> ByteVector;
|
||||
|
||||
|
||||
namespace Tins
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user