Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7b58a2e62 | ||
|
|
225fd3870f | ||
|
|
5185c025d8 | ||
|
|
1345a8013c | ||
|
|
c0b8a1b5e0 | ||
|
|
d202fdc778 | ||
|
|
008f67e1f1 | ||
|
|
131d57e808 | ||
|
|
0facb2f57b | ||
|
|
76e86f556a | ||
|
|
1f40e10d5c | ||
|
|
1664136d14 | ||
|
|
45b738c8e2 | ||
|
|
6cecaacb23 | ||
|
|
471bd9459c | ||
|
|
86ff923e8a | ||
|
|
9b65fca64a | ||
|
|
7e7e66f0b7 | ||
|
|
7a781d6d46 | ||
|
|
6979ae8bb2 | ||
|
|
79d7336689 | ||
|
|
41f8c9243f |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,8 +1,9 @@
|
||||
|
||||
# Created by https://www.gitignore.io/api/c++,linux,codeblocks
|
||||
# project
|
||||
test
|
||||
test/vm
|
||||
projectfiles
|
||||
CMakeLists.txt.user
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "lib/libtins"]
|
||||
path = lib/libtins
|
||||
url = git@github.com:stubbfel/libtins.git
|
||||
[submodule "lib/jsoncpp"]
|
||||
path = lib/jsoncpp
|
||||
url = https://github.com/open-source-parsers/jsoncpp.git
|
||||
|
||||
@@ -5,9 +5,20 @@ else ()
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
endif ()
|
||||
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
project (1261nat)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
SET(BUILD_SHARED_LIBS ON)
|
||||
|
||||
SET(JSONCPP_WITH_TESTS OFF CACHE BOOL "test8")
|
||||
SET(JSONCPP_WITH_POST_BUILD_UNITTEST OFF CACHE BOOL "tes9")
|
||||
SET(JSONCPP_WITH_PKGCONFIG_SUPPORT OFF CACHE BOOL "test10")
|
||||
SET(JSONCPP_WITH_CMAKE_PACKAGE OFF CACHE BOOL "test11")
|
||||
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "test12")
|
||||
SET(BUILD_STATIC_LIBS ON CACHE BOOL "test13")
|
||||
ADD_SUBDIRECTORY(lib/jsoncpp)
|
||||
|
||||
SET(LIBTINS_BUILD_SHARED OFF CACHE BOOL "test")
|
||||
SET(LIBTINS_ENABLE_CXX11 ON CACHE BOOL "test2")
|
||||
SET(LIBTINS_ENABLE_WPA2 OFF CACHE BOOL "test3")
|
||||
@@ -20,10 +31,18 @@ SET(PCAP_ROOT_DIR /usr/ CACHE PATH "test14")
|
||||
SET(PCAP_LIBRARY /usr/lib64/libpcap.so CACHE FILEPATH "test14")
|
||||
ADD_SUBDIRECTORY(lib/libtins)
|
||||
|
||||
INCLUDE_DIRECTORIES(lib/libtins/include)
|
||||
INCLUDE_DIRECTORIES(lib/libtins/include lib/jsoncpp/include)
|
||||
file(GLOB_RECURSE 1261nat_src_files "src/*.h" "src/*.cpp")
|
||||
add_executable(1261nat ${1261nat_src_files} )
|
||||
target_link_libraries (1261nat tins)
|
||||
target_link_libraries (1261nat pthread tins jsoncpp_lib_static)
|
||||
|
||||
file(COPY src/config-example.json DESTINATION ${CMAKE_BINARY_DIR} )
|
||||
install(TARGETS 1261nat
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib/static)
|
||||
install(FILES src/config-example.json DESTINATION /etc/1261nat)
|
||||
|
||||
ADD_SUBDIRECTORY(test)
|
||||
if (with-tests)
|
||||
ADD_SUBDIRECTORY(test)
|
||||
endif ()
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
CURRENT_DIR="$(pwd)"
|
||||
cd "$(dirname "$0")" || exit
|
||||
PROJECT_NAME="$(basename "$(dirname "$(pwd)")")"
|
||||
PROJECT_PATH="../projectfiles/codeblock/$PROJECT_NAME"
|
||||
mkdir -p "$PROJECT_PATH"
|
||||
cd "$PROJECT_PATH" || exit
|
||||
cmake ../../../ -G "CodeBlocks - Unix Makefiles"
|
||||
|
||||
if [ -d "../../../test" ]; then
|
||||
TEST_PROJECT_PATH="../test-$PROJECT_NAME"
|
||||
mkdir -p "$TEST_PROJECT_PATH"
|
||||
cd "$TEST_PROJECT_PATH" || exit
|
||||
cmake ../../../test -G "CodeBlocks - Unix Makefiles"
|
||||
fi
|
||||
|
||||
cd $CURRENT_DIR || exit
|
||||
File diff suppressed because it is too large
Load Diff
1
lib/jsoncpp
Submodule
1
lib/jsoncpp
Submodule
Submodule lib/jsoncpp added at 56efb6ba83
Submodule lib/libtins updated: a61a361eb1...06001815ae
@@ -1,4 +1,5 @@
|
||||
#include "AbstractNetworkInterfaceCard.h"
|
||||
#include "AbstractPacketHandler.h"
|
||||
|
||||
AbstractNetworkInterfaceCard::AbstractNetworkInterfaceCard()
|
||||
{
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
#ifndef ABSTRACTNETWORKINTERFACECARD_H
|
||||
#define ABSTRACTNETWORKINTERFACECARD_H
|
||||
|
||||
#include "AbstractPacketHandler_t.h"
|
||||
#include "AbstractRouter_t.h"
|
||||
#include "INetworkInterfaceCard.h"
|
||||
#include "IPacketHandler_t.h"
|
||||
#include "IRouter_t.h"
|
||||
|
||||
class AbstractNetworkInterfaceCard
|
||||
class AbstractNetworkInterfaceCard : public INetworkInterfaceCard
|
||||
{
|
||||
public:
|
||||
void sendPacket(/*const Tins::Pdu & pdu*/);
|
||||
void startListen();
|
||||
void stopListen();
|
||||
protected:
|
||||
public:
|
||||
protected:
|
||||
AbstractNetworkInterfaceCard();
|
||||
virtual ~AbstractNetworkInterfaceCard();
|
||||
private:
|
||||
SPtrAbstractPacketHandlerList handlerList;
|
||||
SPtrAbstractRouter router;
|
||||
private:
|
||||
SPtrIPacketHandlerList handlerList;
|
||||
SPtrIRouter router;
|
||||
};
|
||||
|
||||
#endif // ABSTRACTNETWORKINTERFACECARD_H
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#ifndef ABSTRACTPACKETHANDLER_H
|
||||
#define ABSTRACTPACKETHANDLER_H
|
||||
|
||||
#include "IPacketHandler.h"
|
||||
|
||||
class AbstractPacketHandler
|
||||
class AbstractPacketHandler : public IPacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
protected:
|
||||
public:
|
||||
protected:
|
||||
AbstractPacketHandler();
|
||||
virtual ~AbstractPacketHandler();
|
||||
|
||||
private:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // ABSTRACTPACKETHANDLER_H
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef ABSTRACTPACKETHANDLER_T_H_INCLUDED
|
||||
#define ABSTRACTPACKETHANDLER_T_H_INCLUDED
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
class AbstractPacketHandler;
|
||||
typedef std::shared_ptr<AbstractPacketHandler> SPtrAbstractPacketHandler;
|
||||
typedef std::list<SPtrAbstractPacketHandler> SPtrAbstractPacketHandlerList;
|
||||
|
||||
#endif // ABSTRACTPACKETHANDLER_T_H_INCLUDED
|
||||
@@ -4,8 +4,7 @@ AbstractRouter::AbstractRouter()
|
||||
{
|
||||
//ctor
|
||||
}
|
||||
|
||||
AbstractRouter::~AbstractRouter()
|
||||
{
|
||||
//dtor
|
||||
//dtore
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#ifndef ABSTRACTROUTER_H
|
||||
#define ABSTRACTROUTER_H
|
||||
|
||||
#include "IRouter.h"
|
||||
|
||||
class AbstractRouter
|
||||
class AbstractRouter: public IRouter
|
||||
{
|
||||
public:
|
||||
|
||||
protected:
|
||||
public:
|
||||
protected:
|
||||
AbstractRouter();
|
||||
virtual ~AbstractRouter();
|
||||
|
||||
private:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // ABSTRACTROUTER_H
|
||||
|
||||
119
src/ArpToNdpPacketHandler.cpp
Normal file
119
src/ArpToNdpPacketHandler.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "ArpToNdpPacketHandler.h"
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include "HwAddressTranslator.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
|
||||
ArpToNdpPacketHandler::ArpToNdpPacketHandler(const Tins::IPv6Address & newPrefix)
|
||||
{
|
||||
prefix = std::make_unique<Tins::IPv6Address>(newPrefix);
|
||||
}
|
||||
|
||||
ArpToNdpPacketHandler::~ArpToNdpPacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void ArpToNdpPacketHandler::setSolicitedNodeAddress(INOUT Tins::IPv6 & ipv6, IN const Tins::IPv6Address & targetIp)
|
||||
{
|
||||
UPtrIPv6Address solicitedNodeAddress = std::make_unique<Tins::IPv6Address>();
|
||||
Tins::IPv6Address & tmpRef = *solicitedNodeAddress;
|
||||
IpAddressTranslator::toSolicitedNodeAddress(targetIp, tmpRef);
|
||||
ipv6.dst_addr(tmpRef);
|
||||
}
|
||||
|
||||
bool ArpToNdpPacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handler requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipv4 packet
|
||||
const Tins::ARP * arpPdu = pdu.find_pdu<Tins::ARP>();
|
||||
if(arpPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert ipv4 addresses to ipv6 addresses
|
||||
UPtrIPv6Address senderIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
||||
UPtrIPv6Address targetIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
||||
const Tins::IPv4Address & targetIp =arpPdu->target_ip_addr();
|
||||
IpAddressTranslator::toIpv6Address(arpPdu->sender_ip_addr(), *senderIp6Address);
|
||||
IpAddressTranslator::toIpv6Address(targetIp, *targetIp6Address);
|
||||
|
||||
// create ip4 pdu
|
||||
std::unique_ptr<Tins::ICMPv6> ndpPdu;
|
||||
std::shared_ptr<Tins::IPv6> ipv6Pdu = std::make_shared<Tins::IPv6>();
|
||||
ipv6Pdu->src_addr(*senderIp6Address);
|
||||
bool isRequest = false;
|
||||
const Tins::ARP::hwaddress_type & senderHwAddr = arpPdu->sender_hw_addr();
|
||||
switch (arpPdu->opcode())
|
||||
{
|
||||
case Tins::ARP::REQUEST:
|
||||
ndpPdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
||||
setSolicitedNodeAddress(*ipv6Pdu, *targetIp6Address);
|
||||
ndpPdu->source_link_layer_addr(senderHwAddr);
|
||||
ndpPdu->target_addr(*targetIp6Address);
|
||||
isRequest = true;
|
||||
ipv6Pdu->hop_limit(255);
|
||||
break;
|
||||
|
||||
case Tins::ARP::REPLY:
|
||||
ndpPdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
||||
ipv6Pdu->dst_addr(*targetIp6Address);
|
||||
ndpPdu->target_addr(*senderIp6Address);
|
||||
ipv6Pdu->hop_limit(255);
|
||||
ndpPdu->target_link_layer_addr(senderHwAddr);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Tins::PDU> ptrOutestPdu;
|
||||
const Tins::EthernetII * ethPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if(ethPdu != nullptr)
|
||||
{
|
||||
// set eth frame
|
||||
std::shared_ptr<Tins::EthernetII> ptrEthPdu = std::make_shared<Tins::EthernetII>();
|
||||
ptrEthPdu->src_addr(ethPdu->src_addr());
|
||||
Tins::EthernetII::address_type dstMac;
|
||||
if (isRequest)
|
||||
{
|
||||
// set solicited address
|
||||
UPtrHwAddress solicitedNodeHWAddress = std::make_unique<HwAddress>();
|
||||
HwAddressTranslator::toSolicitedNodeAddress(*targetIp6Address, *solicitedNodeHWAddress);
|
||||
ptrEthPdu->dst_addr(*solicitedNodeHWAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptrEthPdu->dst_addr(ethPdu->dst_addr());
|
||||
}
|
||||
|
||||
ptrOutestPdu = ptrEthPdu;
|
||||
*ptrOutestPdu /= *ipv6Pdu;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptrOutestPdu = ipv6Pdu;
|
||||
}
|
||||
|
||||
Tins::PDU & outestPdu = *ptrOutestPdu;
|
||||
outestPdu /= *ndpPdu;
|
||||
return callBackHandler->handle(outestPdu, this);
|
||||
}
|
||||
|
||||
const Tins::IPv6Address & ArpToNdpPacketHandler::getPrefix() const
|
||||
{
|
||||
return *prefix;
|
||||
}
|
||||
|
||||
void ArpToNdpPacketHandler::setPrefix(const Tins::IPv6Address & newPrefix)
|
||||
{
|
||||
*prefix = newPrefix;
|
||||
}
|
||||
23
src/ArpToNdpPacketHandler.h
Normal file
23
src/ArpToNdpPacketHandler.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef ARPTONDPPACKETHANDLER_H
|
||||
#define ARPTONDPPACKETHANDLER_H
|
||||
|
||||
#include "AbstractPacketHandler.h"
|
||||
#include "IPacketHandler_t.h"
|
||||
#include "Ip6Packet_t.h"
|
||||
|
||||
class ArpToNdpPacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
ArpToNdpPacketHandler(const Tins::IPv6Address & prefix);
|
||||
virtual ~ArpToNdpPacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
|
||||
const Tins::IPv6Address & getPrefix() const;
|
||||
void setPrefix(const Tins::IPv6Address & newPrefix);
|
||||
void setSolicitedNodeAddress(INOUT Tins::IPv6 & ipv6, IN const Tins::IPv6Address & targetIp);
|
||||
private:
|
||||
UPtrIPv6Address prefix;
|
||||
};
|
||||
#endif
|
||||
17
src/ForwardPacketHandler.cpp
Normal file
17
src/ForwardPacketHandler.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "ForwardPacketHandler.h"
|
||||
|
||||
ForwardPacketHandler::ForwardPacketHandler(SPtrIPacketHandler forwardToHandler, SPtrIPacketHandler forwardToCallBackHandler)
|
||||
{
|
||||
targetHandler = forwardToHandler;
|
||||
targetCallBackHandler = forwardToCallBackHandler;
|
||||
}
|
||||
|
||||
ForwardPacketHandler::~ForwardPacketHandler()
|
||||
{
|
||||
//dtor
|
||||
}
|
||||
|
||||
bool ForwardPacketHandler::handle(const Tins::PDU &pdu, IPacketHandler * /*callBackHandler */)
|
||||
{
|
||||
return targetHandler->handle(pdu, targetCallBackHandler.get());
|
||||
}
|
||||
19
src/ForwardPacketHandler.h
Normal file
19
src/ForwardPacketHandler.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef FORWARDPACKETHANDLER_H
|
||||
#define FORWARDPACKETHANDLER_H
|
||||
|
||||
#include "AbstractPacketHandler.h"
|
||||
|
||||
class ForwardPacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
ForwardPacketHandler(SPtrIPacketHandler forwardToHandler, SPtrIPacketHandler forwardToCallBackHandler);
|
||||
virtual ~ForwardPacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
|
||||
private:
|
||||
SPtrIPacketHandler targetCallBackHandler;
|
||||
SPtrIPacketHandler targetHandler;
|
||||
};
|
||||
#endif
|
||||
29
src/HwAddressTranslator.cpp
Normal file
29
src/HwAddressTranslator.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "HwAddressTranslator.h"
|
||||
#include <tins/ipv6_address.h>
|
||||
|
||||
|
||||
const uint8_t HwAddressTranslator::solicitedNodeAddressPrefix[] = {0x33, 0x33, 0xff};
|
||||
|
||||
void HwAddressTranslator::toSolicitedNodeAddress(IN const Tins::IPv6Address &ipv6Address, INOUT HwAddress &resultHwAddress)
|
||||
{
|
||||
Tins::IPv6Address::const_iterator ipv6It = ipv6Address.end();
|
||||
HwAddress::iterator hwIt = resultHwAddress.end();
|
||||
|
||||
hwIt--;
|
||||
ipv6It--;
|
||||
|
||||
// copy last 3 bydes of ip v6 to hw address
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
*hwIt = *ipv6It;
|
||||
hwIt--;
|
||||
ipv6It--;
|
||||
}
|
||||
|
||||
// copy solicited Address prefix to hw address
|
||||
for (int j = 2; j > -1; j--)
|
||||
{
|
||||
*hwIt = solicitedNodeAddressPrefix[j];
|
||||
hwIt--;
|
||||
}
|
||||
}
|
||||
27
src/HwAddressTranslator.h
Normal file
27
src/HwAddressTranslator.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef HWADDRESSTRANSLATOR_H
|
||||
#define HWADDRESSTRANSLATOR_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdint.h>
|
||||
#include <tins/hw_address.h>
|
||||
#include "Main_t.h"
|
||||
#include "Ip6Packet_t.h"
|
||||
|
||||
|
||||
#ifndef DefaultSizeOf
|
||||
#define DefaultSizeOfHwAddress 6
|
||||
#endif
|
||||
|
||||
|
||||
typedef Tins::HWAddress<DefaultSizeOfHwAddress> HwAddress;
|
||||
typedef std::unique_ptr<HwAddress> UPtrHwAddress;
|
||||
|
||||
class HwAddressTranslator
|
||||
{
|
||||
|
||||
public:
|
||||
static void toSolicitedNodeAddress(IN const Tins::IPv6Address & ipv6Address, INOUT HwAddress & resultHwAddress);
|
||||
private:
|
||||
static const uint8_t solicitedNodeAddressPrefix[];
|
||||
};
|
||||
#endif
|
||||
14
src/INetworkInterfaceCard.h
Normal file
14
src/INetworkInterfaceCard.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef INETWORKINTERFACECARD_H
|
||||
#define INETWORKINTERFACECARD_H
|
||||
|
||||
#include "INetworkInterfaceCard_t.h"
|
||||
#include "IPacketHandler.h"
|
||||
|
||||
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
|
||||
17
src/INetworkInterfaceCard_t.h
Normal file
17
src/INetworkInterfaceCard_t.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef INETWORKINTERFACECARD_T_H
|
||||
#define INETWORKINTERFACECARD_T_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include "Main_t.h"
|
||||
|
||||
#ifndef DEFAULT_MTU_VAULE
|
||||
#define DEFAULT_MTU_VAULE 1500
|
||||
#endif
|
||||
|
||||
interface IPacketHandler;
|
||||
|
||||
|
||||
interface INetworkInterfaceCard;
|
||||
typedef std::shared_ptr<INetworkInterfaceCard> SPtrINetworkInterfaceCard;
|
||||
#endif
|
||||
15
src/IPacketHandler.h
Normal file
15
src/IPacketHandler.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef IPACKETHANDLER_H
|
||||
#define IPACKETHANDLER_H
|
||||
|
||||
#include "Main_t.h"
|
||||
#include "IPacketHandler_t.h"
|
||||
namespace Tins
|
||||
{
|
||||
class PDU;
|
||||
}
|
||||
|
||||
interface IPacketHandler
|
||||
{
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) = 0;
|
||||
};
|
||||
#endif
|
||||
13
src/IPacketHandler_t.h
Normal file
13
src/IPacketHandler_t.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef IPACKETHANDLER_T_H
|
||||
#define IPACKETHANDLER_T_H
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include "Main_t.h"
|
||||
|
||||
interface IPacketHandler;
|
||||
typedef std::shared_ptr<IPacketHandler> SPtrIPacketHandler;
|
||||
typedef std::unique_ptr<IPacketHandler> UPtrIPacketHandler;
|
||||
typedef std::list<SPtrIPacketHandler> SPtrIPacketHandlerList;
|
||||
|
||||
#endif // ABSTRACTPACKETHANDLER_T_H_INCLUDED
|
||||
11
src/IRouter.h
Normal file
11
src/IRouter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef IROUTER_H
|
||||
#define IROUTER_H
|
||||
|
||||
#include "IRouter_t.h"
|
||||
#include "IPacketHandler.h"
|
||||
|
||||
interface IRouter: IPacketHandler
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef ABSTRACTROUTER_T_H_INCLUDED
|
||||
#define ABSTRACTROUTER_T_H_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
#include "Main_t.h"
|
||||
|
||||
class AbstractRouter;
|
||||
typedef std::shared_ptr<AbstractRouter> SPtrAbstractRouter;
|
||||
interface IRouter;
|
||||
typedef std::shared_ptr<IRouter> SPtrIRouter;
|
||||
|
||||
#endif // ABSTRACTROUTER_T_H_INCLUDED
|
||||
65
src/Icmp4ToIcmp6PacketHandler.cpp
Normal file
65
src/Icmp4ToIcmp6PacketHandler.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "Icmp4ToIcmp6PacketHandler.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
|
||||
Icmp4ToIcmp6PacketHandler::Icmp4ToIcmp6PacketHandler(const Tins::IPv6Address & newPrefix) : Ip4ToIp6PacketHandler(newPrefix)
|
||||
{
|
||||
}
|
||||
|
||||
Icmp4ToIcmp6PacketHandler::~Icmp4ToIcmp6PacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool Icmp4ToIcmp6PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handvet requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipv4 packet
|
||||
const Tins::ICMP * icmpv4Pdu = pdu.find_pdu<Tins::ICMP>();
|
||||
if(icmpv4Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// create icmp6 pdu
|
||||
const Tins::ICMP::Flags type = icmpv4Pdu->type();
|
||||
std::unique_ptr<Tins::ICMPv6> icmpv6Pdu;
|
||||
switch (type)
|
||||
{
|
||||
case Tins::ICMP::Flags::ECHO_REPLY:
|
||||
icmpv6Pdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
|
||||
case Tins::ICMP::Flags::ECHO_REQUEST:
|
||||
icmpv6Pdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::ECHO_REQUEST);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
icmpv6Pdu->identifier(icmpv4Pdu->id());
|
||||
icmpv6Pdu->sequence(icmpv4Pdu->sequence());
|
||||
icmpv6Pdu->code(0);
|
||||
|
||||
if (icmpv4Pdu->inner_pdu() != nullptr)
|
||||
{
|
||||
icmpv6Pdu->inner_pdu(icmpv4Pdu->inner_pdu()->clone());
|
||||
}
|
||||
|
||||
// replace icmp4 with icmp6 content, adress translation will bo den by Ip4ToIp6PacketHandler
|
||||
Tins::PDU * clonePdu = pdu.clone();
|
||||
Tins::IP * ipPdu = clonePdu->find_pdu<Tins::IP>();
|
||||
if(ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ipPdu->inner_pdu(*icmpv6Pdu);
|
||||
return Ip4ToIp6PacketHandler::handle(*clonePdu, callBackHandler);
|
||||
}
|
||||
15
src/Icmp4ToIcmp6PacketHandler.h
Normal file
15
src/Icmp4ToIcmp6PacketHandler.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ICMP4TOICMP6PACKETHANDLER_H
|
||||
#define ICMP4TOICMP6PACKETHANDLER_H
|
||||
|
||||
#include "Ip4ToIp6PacketHandler.h"
|
||||
|
||||
class Icmp4ToIcmp6PacketHandler : public Ip4ToIp6PacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
Icmp4ToIcmp6PacketHandler(const Tins::IPv6Address & prefix);
|
||||
virtual ~Icmp4ToIcmp6PacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
};
|
||||
#endif
|
||||
72
src/Icmp6ToIcmp4PacketHandler.cpp
Normal file
72
src/Icmp6ToIcmp4PacketHandler.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "Icmp6ToIcmp4PacketHandler.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include "NdpToArpPacketHandler.h"
|
||||
|
||||
Icmp6ToIcmp4PacketHandler::Icmp6ToIcmp4PacketHandler() : Ip6ToIp4PacketHandler()
|
||||
{
|
||||
ndpToArpHandler = std::make_unique<NdpToArpPacketHandler>();
|
||||
}
|
||||
|
||||
Icmp6ToIcmp4PacketHandler::~Icmp6ToIcmp4PacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool Icmp6ToIcmp4PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handvet requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get icmpv6 packet
|
||||
const Tins::ICMPv6 * icmpv6Pdu = pdu.find_pdu<Tins::ICMPv6>();
|
||||
if(icmpv6Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// create icmp6 pdu
|
||||
const Tins::ICMPv6::Types type = icmpv6Pdu->type();
|
||||
std::unique_ptr<Tins::ICMP> icmpv4Pdu;
|
||||
switch (type)
|
||||
{
|
||||
case Tins::ICMPv6::ECHO_REPLY:
|
||||
icmpv4Pdu = std::make_unique<Tins::ICMP>(Tins::ICMP::Flags::ECHO_REPLY);
|
||||
break;
|
||||
|
||||
case Tins::ICMPv6::ECHO_REQUEST:
|
||||
icmpv4Pdu = std::make_unique<Tins::ICMP>(Tins::ICMP::Flags::ECHO_REQUEST);
|
||||
break;
|
||||
|
||||
case Tins::ICMPv6::NEIGHBOUR_SOLICIT:
|
||||
case Tins::ICMPv6::NEIGHBOUR_ADVERT:
|
||||
return ndpToArpHandler->handle(pdu, callBackHandler);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
icmpv4Pdu->id(icmpv6Pdu->identifier());
|
||||
icmpv4Pdu->sequence(icmpv6Pdu->sequence());
|
||||
icmpv4Pdu->code(0);
|
||||
|
||||
if (icmpv6Pdu->inner_pdu() != nullptr)
|
||||
{
|
||||
icmpv4Pdu->inner_pdu(icmpv6Pdu->inner_pdu()->clone());
|
||||
}
|
||||
|
||||
// replace icmp4 with icmp6 content, adress translation will bo den by Ip4ToIp6PacketHandler
|
||||
Tins::PDU * clonePdu = pdu.clone();
|
||||
Tins::IPv6 * ipv6Pdu = clonePdu->find_pdu<Tins::IPv6>();
|
||||
if(ipv6Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ipv6Pdu->inner_pdu(*icmpv4Pdu);
|
||||
return Ip6ToIp4PacketHandler::handle(*clonePdu, callBackHandler);
|
||||
}
|
||||
17
src/Icmp6ToIcmp4PacketHandler.h
Normal file
17
src/Icmp6ToIcmp4PacketHandler.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef ICMP6TOICMP4PACKETHANDLER_H
|
||||
#define ICMP6TOICMP4PACKETHANDLER_H
|
||||
|
||||
#include "Ip6ToIp4PacketHandler.h"
|
||||
|
||||
class Icmp6ToIcmp4PacketHandler : public Ip6ToIp4PacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
Icmp6ToIcmp4PacketHandler();
|
||||
virtual ~Icmp6ToIcmp4PacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
private:
|
||||
UPtrIPacketHandler ndpToArpHandler;
|
||||
};
|
||||
#endif
|
||||
12
src/Ip4Packet_t.h
Normal file
12
src/Ip4Packet_t.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef IP4PACKET_T_H
|
||||
#define IP4PACKET_T_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Tins
|
||||
{
|
||||
class IPv4Address;
|
||||
}
|
||||
|
||||
typedef std::unique_ptr<Tins::IPv4Address> UPtrIPv4Address;
|
||||
#endif
|
||||
76
src/Ip4ToIp6PacketHandler.cpp
Normal file
76
src/Ip4ToIp6PacketHandler.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "Ip4ToIp6PacketHandler.h"
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include "IpAddressTranslator.h"
|
||||
|
||||
Ip4ToIp6PacketHandler::Ip4ToIp6PacketHandler(const Tins::IPv6Address & newPrefix)
|
||||
{
|
||||
prefix = std::make_unique<Tins::IPv6Address>(newPrefix);
|
||||
}
|
||||
|
||||
Ip4ToIp6PacketHandler::~Ip4ToIp6PacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool Ip4ToIp6PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handvet requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipv4 packet
|
||||
const Tins::IP * ipv4Pdu = pdu.find_pdu<Tins::IP>();
|
||||
if(ipv4Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert ipv4 addresses to ipv6 addresses
|
||||
UPtrIPv6Address srcIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
||||
UPtrIPv6Address dstIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
||||
IpAddressTranslator::toIpv6Address(ipv4Pdu->src_addr(), *srcIp6Address);
|
||||
IpAddressTranslator::toIpv6Address(ipv4Pdu->dst_addr(), *dstIp6Address);
|
||||
|
||||
// create ip4 pdu
|
||||
std::unique_ptr<Tins::IPv6> ipv6Pdu = std::make_unique<Tins::IPv6>(*dstIp6Address,*srcIp6Address);
|
||||
ipv6Pdu->hop_limit(64);
|
||||
ipv6Pdu->flow_label(11);
|
||||
|
||||
// create forwarding frame
|
||||
std::unique_ptr<Tins::EthernetII> ptrForwardEthPdu = std::make_unique<Tins::EthernetII>();
|
||||
Tins::EthernetII & forwardEthPdu = *ptrForwardEthPdu;
|
||||
|
||||
// copy src and dst mac address
|
||||
const Tins::EthernetII * ethPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if(ethPdu != nullptr)
|
||||
{
|
||||
forwardEthPdu.src_addr(ethPdu->src_addr());
|
||||
forwardEthPdu.dst_addr(ethPdu->dst_addr());
|
||||
}
|
||||
|
||||
forwardEthPdu /= *ipv6Pdu;
|
||||
|
||||
//copy ipv4 payload to ip6 payload
|
||||
const Tins::PDU * ipPayloadPdu = ipv4Pdu->inner_pdu();
|
||||
if(ipPayloadPdu != nullptr)
|
||||
{
|
||||
forwardEthPdu /= *ipPayloadPdu;
|
||||
}
|
||||
|
||||
// forward frame
|
||||
return callBackHandler->handle(forwardEthPdu, this);
|
||||
}
|
||||
|
||||
const Tins::IPv6Address & Ip4ToIp6PacketHandler::getPrefix() const
|
||||
{
|
||||
return *prefix;
|
||||
}
|
||||
|
||||
void Ip4ToIp6PacketHandler::setPrefix(const Tins::IPv6Address & newPrefix)
|
||||
{
|
||||
*prefix = newPrefix;
|
||||
}
|
||||
22
src/Ip4ToIp6PacketHandler.h
Normal file
22
src/Ip4ToIp6PacketHandler.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef IP4TO6PACKETHANDLER_H
|
||||
#define IP4TO6PACKETHANDLER_H
|
||||
|
||||
#include "AbstractPacketHandler.h"
|
||||
#include "Ip6Packet_t.h"
|
||||
|
||||
|
||||
class Ip4ToIp6PacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
public:
|
||||
|
||||
Ip4ToIp6PacketHandler(const Tins::IPv6Address & prefix);
|
||||
virtual ~Ip4ToIp6PacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
|
||||
const Tins::IPv6Address & getPrefix() const;
|
||||
void setPrefix(const Tins::IPv6Address & newPrefix);
|
||||
private:
|
||||
UPtrIPv6Address prefix;
|
||||
};
|
||||
#endif
|
||||
14
src/Ip6Packet_t.h
Normal file
14
src/Ip6Packet_t.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef IP6PACKET_T_H
|
||||
#define IP6PACKET_T_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Tins
|
||||
{
|
||||
class IPv6Address;
|
||||
class IPv6;
|
||||
}
|
||||
|
||||
typedef std::unique_ptr<Tins::IPv6Address> UPtrIPv6Address;
|
||||
|
||||
#endif
|
||||
68
src/Ip6ToIp4PacketHandler.cpp
Normal file
68
src/Ip6ToIp4PacketHandler.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "Ip6ToIp4PacketHandler.h"
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include "IpAddressTranslator.h"
|
||||
|
||||
/*
|
||||
* ctor
|
||||
*/
|
||||
Ip6ToIp4PacketHandler::Ip6ToIp4PacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* dtor
|
||||
*/
|
||||
Ip6ToIp4PacketHandler::~Ip6ToIp4PacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool Ip6ToIp4PacketHandler::handle(const Tins::PDU &pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handvet requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipv6 packet
|
||||
const Tins::IPv6 * ipv6Pdu = pdu.find_pdu<Tins::IPv6>();
|
||||
if(ipv6Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert ipv6 addresses to ipv4 addresses
|
||||
const uint32_t srcIp4AddressBytes = IpAddressTranslator::toIpv4AddressBytes(ipv6Pdu->src_addr());
|
||||
const uint32_t dstIp4AddressBytes = IpAddressTranslator::toIpv4AddressBytes(ipv6Pdu->dst_addr());
|
||||
std::unique_ptr<const Tins::IPv4Address> srcIp4Address = std::make_unique<const Tins::IPv4Address>(srcIp4AddressBytes);
|
||||
std::unique_ptr<const Tins::IPv4Address> dstIp4Address = std::make_unique<const Tins::IPv4Address>(dstIp4AddressBytes);
|
||||
|
||||
// create ip4 pdu
|
||||
std::unique_ptr<const Tins::IP> ipv4Pdu = std::make_unique<const Tins::IP>(*dstIp4Address,*srcIp4Address);
|
||||
|
||||
// create forwarding frame
|
||||
std::unique_ptr<Tins::EthernetII> ptrForwardEthPdu = std::make_unique<Tins::EthernetII>();
|
||||
Tins::EthernetII & forwardEthPdu = *ptrForwardEthPdu;
|
||||
|
||||
// copy src and dsd mac address
|
||||
const Tins::EthernetII * ethPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if(ethPdu != nullptr)
|
||||
{
|
||||
forwardEthPdu.src_addr(ethPdu->src_addr());
|
||||
forwardEthPdu.dst_addr(ethPdu->dst_addr());
|
||||
}
|
||||
|
||||
forwardEthPdu /= *ipv4Pdu;
|
||||
|
||||
//copy ipv6 payload to ip4 payload
|
||||
const Tins::PDU * ipPayloadPdu = ipv6Pdu->inner_pdu();
|
||||
if(ipPayloadPdu != nullptr)
|
||||
{
|
||||
forwardEthPdu /= *ipPayloadPdu;
|
||||
}
|
||||
|
||||
// forward frame
|
||||
return callBackHandler->handle(forwardEthPdu, this);
|
||||
}
|
||||
14
src/Ip6ToIp4PacketHandler.h
Normal file
14
src/Ip6ToIp4PacketHandler.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef IP6TO4PACKETHANDLER_H
|
||||
#define IP6TO4PACKETHANDLER_H
|
||||
|
||||
#include "AbstractPacketHandler.h"
|
||||
|
||||
class Ip6ToIp4PacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
public:
|
||||
Ip6ToIp4PacketHandler();
|
||||
virtual ~Ip6ToIp4PacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
};
|
||||
#endif
|
||||
51
src/IpAddressTranslator.cpp
Normal file
51
src/IpAddressTranslator.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "IpAddressTranslator.h"
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
|
||||
#ifndef NdpPrefixValueString
|
||||
#define NdpPrefixValueString "FF02:0:0:0:0:1:FF00:0"
|
||||
#endif
|
||||
|
||||
#ifndef NdpMaskValueString
|
||||
#define NdpMaskValueString "::FF:FFFF"
|
||||
#endif
|
||||
|
||||
const size_t IpAddressTranslator::lastAddressByteIndex = Tins::IPv4Address::address_size - 1;
|
||||
const UPtrIPv6Address IpAddressTranslator::ndpPrefix = std::make_unique<Tins::IPv6Address>(NdpPrefixValueString);
|
||||
const UPtrIPv6Address IpAddressTranslator::ndpMask = std::make_unique<Tins::IPv6Address>(NdpMaskValueString);
|
||||
|
||||
void IpAddressTranslator::toSolicitedNodeAddress(const Tins::IPv4Address &ipv4Address, Tins::IPv6Address &resultIpv6Address)
|
||||
{
|
||||
toIpv6Address(ipv4Address, resultIpv6Address);
|
||||
toSolicitedNodeAddress(resultIpv6Address, resultIpv6Address);
|
||||
}
|
||||
|
||||
void IpAddressTranslator::toSolicitedNodeAddress(const Tins::IPv6Address &ipv6Address, Tins::IPv6Address &resultIpv6Address)
|
||||
{
|
||||
resultIpv6Address = (*ndpMask & ipv6Address)| *ndpPrefix;
|
||||
}
|
||||
|
||||
uint32_t IpAddressTranslator::toIpv4AddressBytes(IN const Tins::IPv6Address & ipv6Address)
|
||||
{
|
||||
uint32_t ipBytesNetworkOrder = 0;
|
||||
uint8_t * ptrIpByte = reinterpret_cast<uint8_t *>( &ipBytesNetworkOrder );
|
||||
Tins::IPv6Address::const_iterator it = ipv6Address.end();
|
||||
for (int i = lastAddressByteIndex; i > -1; i--)
|
||||
{
|
||||
it--;
|
||||
ptrIpByte[i] = *it;
|
||||
}
|
||||
|
||||
return ipBytesNetworkOrder;
|
||||
}
|
||||
void IpAddressTranslator::toIpv6Address(IN const Tins::IPv4Address & ipv4Address, INOUT Tins::IPv6Address & resultIpv6Address)
|
||||
{
|
||||
Tins::IPv6Address::iterator it = resultIpv6Address.end();
|
||||
uint32_t ipBytesNetworkOrder = ipv4Address;
|
||||
uint8_t * ptrIpByte = reinterpret_cast<uint8_t *>( &ipBytesNetworkOrder );
|
||||
for (int i = lastAddressByteIndex; i > -1; i--)
|
||||
{
|
||||
it--;
|
||||
*it = ptrIpByte[i];
|
||||
}
|
||||
}
|
||||
22
src/IpAddressTranslator.h
Normal file
22
src/IpAddressTranslator.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef IPADDRESSTRANSLATOR_H
|
||||
#define IPADDRESSTRANSLATOR_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdint.h>
|
||||
#include "Main_t.h"
|
||||
#include "Ip6Packet_t.h"
|
||||
#include "Ip4Packet_t.h"
|
||||
|
||||
class IpAddressTranslator
|
||||
{
|
||||
public:
|
||||
static void toIpv6Address(IN const Tins::IPv4Address & ipv4Address, INOUT Tins::IPv6Address & resultIpv6Address);
|
||||
static void toSolicitedNodeAddress(IN const Tins::IPv4Address & ipv4Address, INOUT Tins::IPv6Address & resultIpv6Address);
|
||||
static void toSolicitedNodeAddress(IN const Tins::IPv6Address & ipv6Address, INOUT Tins::IPv6Address & resultIpv6Address);
|
||||
static uint32_t toIpv4AddressBytes(IN const Tins::IPv6Address & ipv6Address);
|
||||
private:
|
||||
static const size_t lastAddressByteIndex;
|
||||
static const UPtrIPv6Address ndpPrefix;
|
||||
static const UPtrIPv6Address ndpMask;
|
||||
};
|
||||
#endif
|
||||
114
src/IpPacketFragmentation.cpp
Normal file
114
src/IpPacketFragmentation.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "IpPacketFragmentation.h"
|
||||
#include <algorithm>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/rawpdu.h>
|
||||
#include <tins/tcp.h>
|
||||
|
||||
const size_t IpPacketFragmentation::fragmentionHeadersize = sizeof (FragmentionHeaderUnion) - 1;
|
||||
|
||||
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, const size_t headersize)
|
||||
{
|
||||
Tins::IPv6::ext_header extensionHeader(nextHeader, 6 , startPtr);
|
||||
ipFragmentPdu.add_ext_header(extensionHeader);
|
||||
}
|
||||
|
||||
void IpPacketFragmentation::initFragmentationHeader(FragmentionHeaderStruct* ptrFragmentionHeaderStruct)
|
||||
{
|
||||
ptrFragmentionHeaderStruct->NextHeader = Tins::Constants::IP::PROTO_TCP;
|
||||
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 / mtu) + 1;
|
||||
if (fragmentationCount < 2)
|
||||
{
|
||||
return callBackHandler->handle(pdu, this);
|
||||
}
|
||||
|
||||
Tins::IPv6 * ipPdu = pdu.clone()->find_pdu<Tins::IPv6>();
|
||||
if (ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::PDU * ipDataPdu = ipPdu->inner_pdu();
|
||||
if (ipDataPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteVector ipPayload2 = ipPdu->serialize();
|
||||
ByteVector ipPayload(ipPayload2.begin() + ipPdu->header_size(), ipPayload2.end());
|
||||
uint8_t originNextHeader = ipPdu->next_header();
|
||||
const long ipPayloadSize = static_cast<const long>(ipPayload.size());
|
||||
const long fragmentationSize64B = (ipPayloadSize/ static_cast<const long>(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[2];
|
||||
initFragmentationHeader(ptrFragmentionHeaderStruct);
|
||||
|
||||
long frameOffset;
|
||||
for (frameOffset = 0; frameOffset < payLoadEndIndicator; frameOffset += fragmentationSize)
|
||||
{
|
||||
ByteVector::iterator fragmentStart = fragmentPosIt;
|
||||
fragmentPosIt = fragmentStart + fragmentationSize;
|
||||
ptrFragmentionHeaderStruct->FragmentOffset = static_cast<uint16_t>(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;
|
||||
ptrFragmentionHeaderStruct->FragmentOffset = static_cast<uint16_t>(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 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<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(originNextHeader, ptrStartFragmentionHeader, *ipFragmentPdu, IpPacketFragmentation::fragmentionHeadersize);
|
||||
SPtrRawPDU rawFragmentPdu = std::make_shared<Tins::RawPDU>(fragmentPayload->data(), static_cast<uint32_t>(fragmentPayload->size()));
|
||||
ipFragmentPdu->inner_pdu(rawFragmentPdu.get());
|
||||
ipFragmentPdu->next_header(Tins::IPv6::FRAGMENT);
|
||||
return callBackHandler->handle(*fragmentPdu, 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;
|
||||
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 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);
|
||||
};
|
||||
|
||||
#endif // IPPACKETFRAGMENTATION_H
|
||||
55
src/IpPacketFragmentation_t.h
Normal file
55
src/IpPacketFragmentation_t.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
union FragmentionHeaderUnion
|
||||
{
|
||||
FragmentionHeaderStruct Structed;
|
||||
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
|
||||
55
src/IpVersionRouter.cpp
Normal file
55
src/IpVersionRouter.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "IpVersionRouter.h"
|
||||
#include <tins/arp.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include "INetworkInterfaceCard.h"
|
||||
#include "IpPacketFragmentation.h"
|
||||
|
||||
IpVersionRouter::IpVersionRouter(SPtrINetworkInterfaceCard netv4Card, SPtrINetworkInterfaceCard netv6Card)
|
||||
{
|
||||
ipv4Card = netv4Card;
|
||||
ipv6Card = netv6Card;
|
||||
ipv6Fragmentation = std::make_unique<IpPacketFragmentation>(ipv6Card->getMtu());
|
||||
}
|
||||
|
||||
IpVersionRouter::~IpVersionRouter()
|
||||
{
|
||||
}
|
||||
|
||||
bool IpVersionRouter::handle(IN const Tins::PDU & pdu, IN IPacketHandler * /* callBackHandler*/)
|
||||
{
|
||||
const Tins::IPv6 * ipv6Pdu = pdu.find_pdu<Tins::IPv6>();
|
||||
if(ipv6Pdu != nullptr)
|
||||
{
|
||||
if (pdu.size() < ipv6Card->getMtu())
|
||||
{
|
||||
ipv6Card->sendPacket(pdu);
|
||||
return true;
|
||||
}
|
||||
|
||||
return ipv6Fragmentation->handle(pdu, this);
|
||||
}
|
||||
|
||||
const Tins::IP * ipv4Pdu = pdu.find_pdu<Tins::IP>();
|
||||
if(ipv4Pdu == nullptr)
|
||||
{
|
||||
const Tins::ARP * arpPdu = pdu.find_pdu<Tins::ARP>();
|
||||
if(arpPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ipv4Card->sendPacket(pdu);
|
||||
return true;
|
||||
}
|
||||
|
||||
INetworkInterfaceCard & IpVersionRouter::getIpv4Card() const
|
||||
{
|
||||
return *ipv4Card;
|
||||
}
|
||||
|
||||
INetworkInterfaceCard & IpVersionRouter::getIpv6Card() const
|
||||
{
|
||||
return *ipv6Card;
|
||||
}
|
||||
26
src/IpVersionRouter.h
Normal file
26
src/IpVersionRouter.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef IPVERSIONROUTER_H
|
||||
#define IPVERSIONROUTER_H
|
||||
|
||||
#include "AbstractRouter.h"
|
||||
#include "INetworkInterfaceCard_t.h"
|
||||
|
||||
|
||||
class IpVersionRouter: public AbstractRouter
|
||||
{
|
||||
public:
|
||||
IpVersionRouter(SPtrINetworkInterfaceCard netv4Card, SPtrINetworkInterfaceCard netv6Card);
|
||||
virtual ~IpVersionRouter();
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
|
||||
INetworkInterfaceCard & getIpv6Card() const;
|
||||
|
||||
INetworkInterfaceCard & getIpv4Card() const;
|
||||
|
||||
private:
|
||||
|
||||
SPtrINetworkInterfaceCard ipv6Card;
|
||||
SPtrINetworkInterfaceCard ipv4Card;
|
||||
UPtrIPacketHandler ipv6Fragmentation;
|
||||
};
|
||||
|
||||
#endif // ABSTRACTROUTER_H
|
||||
110
src/Main.cpp
110
src/Main.cpp
@@ -1,8 +1,106 @@
|
||||
#include <stdio.h>
|
||||
#include "Main_t.h"
|
||||
#include "pdutypeforwardpackethandler.h"
|
||||
#include "ArpToNdpPacketHandler.h"
|
||||
#include "Icmp4ToIcmp6PacketHandler.h"
|
||||
#include "Icmp6ToIcmp4PacketHandler.h"
|
||||
#include "Ip4ToIp6PacketHandler.h"
|
||||
#include "Ip6ToIp4PacketHandler.h"
|
||||
#include "IpVersionRouter.h"
|
||||
#include "TinsNetworkInterfaceCard.h"
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <thread>
|
||||
#include <json/json.h>
|
||||
#include <json/value.h>
|
||||
#include <fstream>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello, World\n");
|
||||
|
||||
return 0;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2){
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream config_doc(argv[1], std::ifstream::binary);
|
||||
Json::Value root;
|
||||
config_doc >> root;
|
||||
const Json::Value natpairs = root;
|
||||
|
||||
SPtrIPacketHandlerList routerList;
|
||||
std::vector<std::thread *> threadPool;
|
||||
for (Json::Value natpair : natpairs)
|
||||
{
|
||||
const std::string pairname = natpair["name"].asString();
|
||||
const Json::Value natPairItems = natpair["items"];
|
||||
SPtrTinsNetworkInterfaceCard ipv4Netcard;
|
||||
SPtrTinsNetworkInterfaceCard ipv6Netcard;
|
||||
Tins::IPv6Address prefix;
|
||||
for (Json::Value natPairItem : natPairItems)
|
||||
{
|
||||
const int itemtype = natPairItem["type"].asInt();
|
||||
const std::string netcardName = natPairItem["nic-name"].asString();
|
||||
SPtrTinsNetworkInterfaceCard netcard = std::make_shared<TinsNetworkInterfaceCard>(netcardName);
|
||||
if(natPairItem.isMember("mtu"))
|
||||
{
|
||||
netcard->setMtu(static_cast<size_t>(natPairItem["mtu"].asInt()));
|
||||
}
|
||||
switch (itemtype)
|
||||
{
|
||||
case 4:
|
||||
ipv4Netcard = netcard;
|
||||
break;
|
||||
case 6:
|
||||
ipv6Netcard = netcard;
|
||||
prefix = natPairItem["prefix"].asString();
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
SPtrIPacketHandler ip4ToIp6Handler = std::make_shared<Ip4ToIp6PacketHandler>(prefix);
|
||||
SPtrIPacketHandler ip6ToIp4Handler = std::make_shared<Ip6ToIp4PacketHandler>();
|
||||
SPtrIPacketHandler icmp4ToIcmp6Handler = std::make_shared<Icmp4ToIcmp6PacketHandler>(prefix);
|
||||
SPtrIPacketHandler icmp6ToIcmp4Handler = std::make_shared<Icmp6ToIcmp4PacketHandler>();
|
||||
SPtrIPacketHandler arpToNdpHandler = std::make_shared<ArpToNdpPacketHandler>(prefix);
|
||||
|
||||
SPtrIRouter router = std::make_shared<IpVersionRouter>(ipv4Netcard, ipv6Netcard);
|
||||
SPtrPduTypeForwardPacketHandler nat4to6ForwardHandler = std::make_shared<PduTypeForwardPacketHandler>(router);
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ARP, arpToNdpHandler));
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ICMP, icmp4ToIcmp6Handler));
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::IP, ip4ToIp6Handler));
|
||||
|
||||
SPtrPduTypeForwardPacketHandler nat6to4ForwardHandler = std::make_shared<PduTypeForwardPacketHandler>(router);
|
||||
nat6to4ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ICMPv6, icmp6ToIcmp4Handler));
|
||||
nat6to4ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::IPv6, ip6ToIp4Handler));
|
||||
ipv4Netcard->getHandlerList().push_back(nat4to6ForwardHandler);
|
||||
ipv6Netcard->getHandlerList().push_back(nat6to4ForwardHandler);
|
||||
|
||||
std::thread * ipv4Thread = new std::thread(&TinsNetworkInterfaceCard::startListen, ipv4Netcard.get());
|
||||
std::thread * ipv6Thread = new std::thread(&TinsNetworkInterfaceCard::startListen, ipv6Netcard.get());
|
||||
routerList.push_back(router);
|
||||
threadPool.push_back(ipv4Thread);
|
||||
threadPool.push_back(ipv6Thread);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
for (SPtrIPacketHandler routerHandle : routerList)
|
||||
{
|
||||
IpVersionRouter * versionRouter = dynamic_cast<IpVersionRouter *>(routerHandle.get());
|
||||
if (versionRouter == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//versionRouter->getIpv4Card().stopListen();
|
||||
//versionRouter->getIpv6Card().stopListen();
|
||||
}
|
||||
|
||||
for (std::thread * ptrThread : threadPool)
|
||||
{
|
||||
ptrThread->join();
|
||||
delete ptrThread;
|
||||
}
|
||||
|
||||
routerList.clear();
|
||||
threadPool.clear();
|
||||
}
|
||||
|
||||
40
src/Main_t.h
Normal file
40
src/Main_t.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#ifndef MAIN_T_H
|
||||
#define MAIN_T_H
|
||||
|
||||
#ifndef IN
|
||||
#define IN
|
||||
#endif
|
||||
|
||||
#ifndef OUT
|
||||
#define OUT
|
||||
#endif
|
||||
|
||||
#ifndef INOUT
|
||||
#define INOUT
|
||||
#endif
|
||||
|
||||
#ifndef interface
|
||||
#define interface struct
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<typename T, typename ... Args>
|
||||
std::unique_ptr<T> make_unique(Args && ... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args) ...));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
99
src/NdpToArpPacketHandler.cpp
Normal file
99
src/NdpToArpPacketHandler.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "NdpToArpPacketHandler.h"
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include "IpAddressTranslator.h"
|
||||
|
||||
NdpToArpPacketHandler::NdpToArpPacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
NdpToArpPacketHandler::~NdpToArpPacketHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool NdpToArpPacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
||||
{
|
||||
// callback handler requeried
|
||||
if (callBackHandler == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipv6 packet
|
||||
const Tins::IPv6 * ipPdu = pdu.find_pdu<Tins::IPv6>();
|
||||
if(ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get ipcmp packet, which has the target address field
|
||||
const Tins::ICMPv6 * ndpPdu = pdu.find_pdu<Tins::ICMPv6>();
|
||||
if(ndpPdu == nullptr || !ndpPdu->has_target_addr())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// translate target address to ipv4
|
||||
const Tins::IPv6Address & targetIp6Address = ndpPdu->target_addr();
|
||||
UPtrIPv4Address targetIp = std::make_unique<Tins::IPv4Address>(IpAddressTranslator::toIpv4AddressBytes(targetIp6Address));
|
||||
|
||||
// create arp pdu
|
||||
Tins::ICMPv6::hwaddress_type senderHwAddr;
|
||||
const Tins::ICMPv6::option * ptrHwAddressOption;
|
||||
const Tins::ICMPv6::Types ndpType = ndpPdu->type();
|
||||
if (ndpType == Tins::ICMPv6::Types::NEIGHBOUR_SOLICIT)
|
||||
{
|
||||
ptrHwAddressOption = ndpPdu->search_option(Tins::ICMPv6::OptionTypes::SOURCE_ADDRESS);
|
||||
if (ptrHwAddressOption == nullptr)
|
||||
{
|
||||
const Tins::EthernetII * ethNsPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if(ethNsPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
senderHwAddr = ethNsPdu->src_addr();
|
||||
}
|
||||
else
|
||||
{
|
||||
senderHwAddr = ptrHwAddressOption->to<Tins::ICMPv6::hwaddress_type>();
|
||||
}
|
||||
|
||||
// create arp request
|
||||
const Tins::IPv6Address & senderIp6Address = ipPdu->src_addr();
|
||||
UPtrIPv4Address senderIp = std::make_unique<Tins::IPv4Address>(IpAddressTranslator::toIpv4AddressBytes(senderIp6Address));
|
||||
Tins::EthernetII arpRequest = Tins::ARP::make_arp_request(*targetIp, *senderIp, senderHwAddr);
|
||||
return callBackHandler->handle(arpRequest, this);
|
||||
}
|
||||
|
||||
if (ndpType == Tins::ICMPv6::Types::NEIGHBOUR_ADVERT)
|
||||
{
|
||||
const Tins::EthernetII * ethNaPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if(ethNaPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ptrHwAddressOption = ndpPdu->search_option(Tins::ICMPv6::OptionTypes::TARGET_ADDRESS);
|
||||
if (ptrHwAddressOption == nullptr)
|
||||
{
|
||||
senderHwAddr = ethNaPdu->src_addr();
|
||||
}
|
||||
else
|
||||
{
|
||||
senderHwAddr = ptrHwAddressOption->to<Tins::ICMPv6::hwaddress_type>();
|
||||
}
|
||||
|
||||
// create arp reply
|
||||
const Tins::IPv6Address & dstIp6Address = ipPdu->dst_addr();
|
||||
UPtrIPv4Address dstIp = std::make_unique<Tins::IPv4Address>(IpAddressTranslator::toIpv4AddressBytes(dstIp6Address));
|
||||
Tins::EthernetII arpReply = Tins::ARP::make_arp_reply(*dstIp, *targetIp, ethNaPdu->dst_addr(), senderHwAddr);
|
||||
return callBackHandler->handle(arpReply, this);
|
||||
}
|
||||
|
||||
return false;// callBackHandler->handle(outestPdu, this);
|
||||
}
|
||||
14
src/NdpToArpPacketHandler.h
Normal file
14
src/NdpToArpPacketHandler.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef NDPTOARPPACKETHANDLER_H
|
||||
#define NDPTOARPPACKETHANDLER_H
|
||||
|
||||
#include "AbstractPacketHandler.h"
|
||||
#include "IPacketHandler_t.h"
|
||||
|
||||
class NdpToArpPacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
public:
|
||||
NdpToArpPacketHandler();
|
||||
virtual ~NdpToArpPacketHandler();
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
};
|
||||
#endif
|
||||
212
src/TinsNetworkInterfaceCard.cpp
Normal file
212
src/TinsNetworkInterfaceCard.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#include "TinsNetworkInterfaceCard.h"
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/network_interface.h>
|
||||
#include <tins/packet_sender.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) : mtu(DEFAULT_MTU_VAULE), sniffNetworkInterfaceName(networkInterface.name())
|
||||
{
|
||||
snifferConfig = std::make_unique<Tins::SnifferConfiguration>();
|
||||
snifferConfig->set_promisc_mode(true);
|
||||
snifferConfig->set_immediate_mode(true);
|
||||
packetSender = std::make_unique<Tins::PacketSender>(networkInterface);
|
||||
sendPduHashList = std::make_unique<HashList>();
|
||||
hashListMutex = std::make_unique<std::mutex>();
|
||||
isSnifferRunning = false;
|
||||
}
|
||||
|
||||
TinsNetworkInterfaceCard::~TinsNetworkInterfaceCard()
|
||||
{
|
||||
stopListen();
|
||||
}
|
||||
|
||||
std::size_t TinsNetworkInterfaceCard::calcHashValue(Tins::PDU & phyLayerLessPdu)
|
||||
{
|
||||
const Tins::ARP * arpPdu = phyLayerLessPdu.find_pdu<Tins::ARP>();
|
||||
ByteVector byteVector;
|
||||
if(arpPdu != nullptr)
|
||||
{
|
||||
Tins::ARP arpNorm(arpPdu->target_ip_addr(), arpPdu->sender_ip_addr());
|
||||
byteVector = arpNorm.serialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
byteVector = phyLayerLessPdu.serialize();
|
||||
}
|
||||
|
||||
const std::size_t byteVectorHashValue = byteVectorHash(byteVector);
|
||||
return byteVectorHashValue;
|
||||
}
|
||||
|
||||
bool TinsNetworkInterfaceCard::handle(const Tins::PDU &pdu, IPacketHandler * /*callBackHandler*/)
|
||||
{
|
||||
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 std::size_t byteVectorHashValue = calcHashValue(*phyLayerLessPdu);
|
||||
delete clonePdu;
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Tins::PDU & clonePduRef = *clonePdu;
|
||||
Tins::PDU * phyLayerLessPdu = getPhyLessPduPtr(clonePduRef);
|
||||
// layer3 only
|
||||
if (phyLayerLessPdu != nullptr)
|
||||
{
|
||||
addPduToHashList(*phyLayerLessPdu);
|
||||
packetSender->send(clonePduRef);
|
||||
}
|
||||
|
||||
delete clonePdu;
|
||||
}
|
||||
|
||||
void TinsNetworkInterfaceCard::addPduToHashList(IN Tins::PDU &pdu)
|
||||
{
|
||||
if (!isSnifferRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const std::size_t byteVectorHashValue = calcHashValue(pdu);
|
||||
std::lock_guard<std::mutex> lockGuard(*hashListMutex);
|
||||
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()
|
||||
{
|
||||
if (isSnifferRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UPtrSniffer sniffer = std::make_unique<Tins::Sniffer>(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<std::mutex> lockGuard(*hashListMutex);
|
||||
sendPduHashList->clear();
|
||||
}
|
||||
|
||||
size_t TinsNetworkInterfaceCard::getMtu() const
|
||||
{
|
||||
return DEFAULT_MTU_VAULE;
|
||||
}
|
||||
|
||||
Tins::PDU * TinsNetworkInterfaceCard::getPhyLessPduPtr(IN Tins::PDU & pdu) const
|
||||
{
|
||||
const Tins::EthernetII * ethPdu = pdu.find_pdu<Tins::EthernetII>();
|
||||
if (ethPdu == nullptr)
|
||||
{
|
||||
return &pdu;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void TinsNetworkInterfaceCard::setMtu(const size_t &value)
|
||||
{
|
||||
mtu = value;
|
||||
}
|
||||
51
src/TinsNetworkInterfaceCard.h
Normal file
51
src/TinsNetworkInterfaceCard.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef TINSNETWORKINTERFACECARD_H
|
||||
#define TINSNETWORKINTERFACECARD_H
|
||||
|
||||
#include <atomic>
|
||||
#include "TinsNetworkInterfaceCard_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 * = nullptr) override;
|
||||
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;
|
||||
|
||||
void setMtu(const size_t &value);
|
||||
|
||||
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);
|
||||
|
||||
UPtrSnifferConfiguration snifferConfig;
|
||||
UPtrPacketSender packetSender;
|
||||
static ByteVectorHash byteVectorHash;
|
||||
UPtrHashList sendPduHashList;
|
||||
UPtrMutex hashListMutex;
|
||||
std::atomic<bool> isSnifferRunning;
|
||||
SPtrIPacketHandlerList handlerList;
|
||||
std::string sniffNetworkInterfaceName;
|
||||
static std::size_t calcHashValue(Tins::PDU & phyLayerLessPdu);
|
||||
};
|
||||
#endif
|
||||
61
src/TinsNetworkInterfaceCard_t.h
Normal file
61
src/TinsNetworkInterfaceCard_t.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef TINSNETWORKINTERFACECARD_T_H
|
||||
#define TINSNETWORKINTERFACECARD_T_H
|
||||
|
||||
#include <functional>
|
||||
#include "Main_t.h"
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
class TinsNetworkInterfaceCard;
|
||||
|
||||
typedef std::shared_ptr<TinsNetworkInterfaceCard> SPtrTinsNetworkInterfaceCard;
|
||||
#endif
|
||||
33
src/config-example.json
Normal file
33
src/config-example.json
Normal file
@@ -0,0 +1,33 @@
|
||||
[
|
||||
{
|
||||
"name" : "eth0<->eth1",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"nic-name": "eth0",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"nic-name": "eth1",
|
||||
"type": 6,
|
||||
"mtu": 1000,
|
||||
"prefix": "42::"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "eth2<->eth3",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"nic-name": "eth2",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"nic-name": "eth3",
|
||||
"type": 6,
|
||||
"prefix": "23::"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
37
src/pdutypeforwardpackethandler.cpp
Normal file
37
src/pdutypeforwardpackethandler.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "pdutypeforwardpackethandler.h"
|
||||
#include <tins/ethernetII.h>
|
||||
|
||||
PduTypeForwardPacketHandler::PduTypeForwardPacketHandler( SPtrIPacketHandler forwardToCallBackHandler) : AbstractPacketHandler()
|
||||
{
|
||||
handlerQueue = std::make_unique<PduTypeHandlerQueue>();
|
||||
targetCallBackHandler = forwardToCallBackHandler;
|
||||
}
|
||||
|
||||
PduTypeForwardPacketHandler::~PduTypeForwardPacketHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool PduTypeForwardPacketHandler::handle(const Tins::PDU &pdu, IPacketHandler *callBackHandler)
|
||||
{
|
||||
for (PduTypeHandlerMapEntry entry : getHandlerQueue())
|
||||
{
|
||||
const Tins::PDU::PDUType entryType = entry.first;
|
||||
const Tins::PDU * ptrFindPdu = pdu.find_pdu<Tins::EthernetII>(entryType);
|
||||
if (ptrFindPdu == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SPtrIPacketHandler targetHandler = entry.second;
|
||||
return targetHandler->handle(pdu, targetCallBackHandler.get());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PduTypeHandlerQueue &PduTypeForwardPacketHandler::getHandlerQueue() const
|
||||
{
|
||||
return *handlerQueue;
|
||||
}
|
||||
|
||||
23
src/pdutypeforwardpackethandler.h
Normal file
23
src/pdutypeforwardpackethandler.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef PDUTYPEFORWARDPACKETHANDLER_H
|
||||
#define PDUTYPEFORWARDPACKETHANDLER_H
|
||||
#include "pdutypeforwardpackethandler_t.h"
|
||||
#include "AbstractPacketHandler.h"
|
||||
|
||||
|
||||
class PduTypeForwardPacketHandler : public AbstractPacketHandler
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
PduTypeForwardPacketHandler(SPtrIPacketHandler forwardToCallBackHandler);
|
||||
virtual ~PduTypeForwardPacketHandler();
|
||||
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler = nullptr) override;
|
||||
PduTypeHandlerQueue & getHandlerQueue() const;
|
||||
|
||||
private:
|
||||
SPtrIPacketHandler targetCallBackHandler;
|
||||
UPtrPduTypeHandlerMap handlerQueue;
|
||||
};
|
||||
|
||||
#endif // PDUTYPEFORWARDPACKETHANDLER_H
|
||||
21
src/pdutypeforwardpackethandler_t.h
Normal file
21
src/pdutypeforwardpackethandler_t.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef PDUTYPEFORWARDPACKETHANDLER_T_H
|
||||
#define PDUTYPEFORWARDPACKETHANDLER_T_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <tins/pdu.h>
|
||||
#include "IPacketHandler_t.h"
|
||||
|
||||
class PduTypeForwardPacketHandler;
|
||||
typedef PduTypeForwardPacketHandler * PtrPduTypeForwardPacketHandler;
|
||||
typedef std::shared_ptr<PduTypeForwardPacketHandler> SPtrPduTypeForwardPacketHandler;
|
||||
typedef std::unique_ptr<PduTypeForwardPacketHandler> UPtrPduTypeForwardPacketHandler;
|
||||
typedef std::weak_ptr<PduTypeForwardPacketHandler> WPtrPduTypeForwardPacketHandler;
|
||||
|
||||
typedef std::pair<Tins::PDU::PDUType, SPtrIPacketHandler> PduTypeHandlerMapEntry;
|
||||
typedef std::vector<PduTypeHandlerMapEntry> PduTypeHandlerQueue;
|
||||
typedef std::unique_ptr<PduTypeHandlerQueue> UPtrPduTypeHandlerMap;
|
||||
typedef std::shared_ptr<PduTypeHandlerQueue> SPtrPduTypeHandlerMap;
|
||||
typedef std::weak_ptr<PduTypeHandlerQueue> WPtrPduTypeHandlerMap;
|
||||
#endif // PDUTYPEFORWARDPACKETHANDLER_T_H
|
||||
|
||||
21
test/CMakeLists.txt
Normal file
21
test/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 2.4.2)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
set (CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
|
||||
else ()
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
endif ()
|
||||
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
project(test_1261nat)
|
||||
|
||||
INCLUDE_DIRECTORIES(../lib/libtins/include ../lib/jsoncpp/include)
|
||||
include_directories("lib/FakeIt/")
|
||||
include_directories("../src")
|
||||
file(COPY src/test_config.json DESTINATION ${CMAKE_BINARY_DIR}/test )
|
||||
file(GLOB_RECURSE test_1261nat_src_files "../src/*.h" "../src/*.cpp" "src/*.cpp" "lib/FakeIt/single_header/catch/fakeit.hpp")
|
||||
list(REMOVE_ITEM test_1261nat_src_files ${CMAKE_CURRENT_SOURCE_DIR}/../src/Main.cpp)
|
||||
add_executable(test_1261nat ${test_1261nat_src_files} )
|
||||
target_link_libraries (test_1261nat pthread tins jsoncpp_lib_static)
|
||||
20
test/lib/FakeIt/LICENSE
Normal file
20
test/lib/FakeIt/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Eran Pe'er
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
141
test/lib/FakeIt/README.md
Normal file
141
test/lib/FakeIt/README.md
Normal file
@@ -0,0 +1,141 @@
|
||||
FakeIt
|
||||
======
|
||||
|
||||
[](https://gitter.im/eranpeer/FakeIt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
GCC: [](https://travis-ci.org/eranpeer/FakeIt)
|
||||
[](https://coveralls.io/github/eranpeer/FakeIt?branch=master)
|
||||
|
||||
MSC: [](https://ci.appveyor.com/project/eranpeer/fakeit)
|
||||
|
||||
FakeIt is a simple mocking framework for C++. It supports GCC, Clang and MS Visual C++.
|
||||
|
||||
FakeIt is written in C++11 and can be used for testing both C++11 and C++ projects.
|
||||
|
||||
```cpp
|
||||
struct SomeInterface {
|
||||
virtual int foo(int) = 0;
|
||||
virtual int bar(string) = 0;
|
||||
};
|
||||
```
|
||||
```cpp
|
||||
// Instantiate a mock object.
|
||||
Mock<SomeInterface> mock;
|
||||
|
||||
// Setup mock behavior.
|
||||
When(Method(mock,foo)).Return(1); // Method mock.foo will return 1 once.
|
||||
|
||||
// Fetch the mock instance.
|
||||
SomeInterface &i = mock.get();
|
||||
|
||||
// Will print "1".
|
||||
cout << i.foo(0);
|
||||
|
||||
|
||||
```
|
||||
Verify method invocation
|
||||
```cpp
|
||||
Mock<SomeInterface> mock;
|
||||
|
||||
When(Method(mock,foo)).Return(0);
|
||||
|
||||
SomeInterface &i = mock.get();
|
||||
|
||||
// Production code
|
||||
i.foo(1);
|
||||
|
||||
// Verify method mock.foo was invoked.
|
||||
Verify(Method(mock,foo));
|
||||
|
||||
// Verify method mock.foo was invoked with specific arguments.
|
||||
Verify(Method(mock,foo).Using(1));
|
||||
```
|
||||
|
||||
Checkout the [Quickstart](https://github.com/eranpeer/FakeIt/wiki/Quickstart) for many more examples!
|
||||
|
||||
Download the [Latest Release](https://github.com/eranpeer/FakeIt/releases/latest) and start using FakeIt now!
|
||||
|
||||
## Features
|
||||
* Packaged as a **single header file**.
|
||||
* Very simple API based on the expressiveness of C++11.
|
||||
* Supports all major compilers: GCC, Clang and MSC++.
|
||||
* Easily integrated with [**GTest**](https://code.google.com/p/googletest/), [**MS Test**](http://en.wikipedia.org/wiki/Visual_Studio_Unit_Testing_Framework) and [**Boost Test**](http://www.boost.org/doc/libs/1_56_0/libs/test/doc/html/index.html).
|
||||
* Expressive [Arrange-Act-Assert](http://xp123.com/articles/3a-arrange-act-assert/) syntax.
|
||||
* Create mock classes or **spy existing objects** instantly in one simple line.
|
||||
* No limitation on number of method arguments.
|
||||
* Supports dynamic casting.
|
||||
|
||||
## Installation
|
||||
FakeIt is a header only framework. It does not require any installation. For extra simplicity fakeit is packaged as a single header file.
|
||||
|
||||
FakeIt is pre-configured to work with some of the major unit testing frameworks. A pre-configured version will use the assertions mechanism of the unit testing framework to integrate the generated error messages into the unit testing framework output.
|
||||
|
||||
If you don't find your unit testing framework on the list, simply use the *standalone* configuration.
|
||||
|
||||
### Using a pre-packaged single header file
|
||||
Pre-packaged single header versions of FakeIt are located under the *single_header* folder.
|
||||
Depending on the unit testing framework you use, simply add one of the pre-packaged versions to the include path of your test project:
|
||||
* <fakeit_folder>/single_header/gtest
|
||||
* <fakeit_folder>/single_header/mstest
|
||||
* <fakeit_folder>/single_header/boost
|
||||
* <fakeit_folder>/single_header/catch
|
||||
* <fakeit_folder>/single_header/tpunit
|
||||
* <fakeit_folder>/single_header/standalone
|
||||
|
||||
For example, to use fakeit with **Google Test** simply add the *single_header/gtest* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/single_header/gtest"
|
||||
```
|
||||
### Using the source header files
|
||||
Fakeit source code header files are located under the *include* foler. To use FakeIt directly from the source code all you need to do is to download the source files and add the *include* folder and the configuration folder of your choice to the include path of your project.
|
||||
For example:
|
||||
* To use fakeit with **Google Test** add the *include* folder and the *config/gtest* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/gtest"
|
||||
```
|
||||
* To use fakeit with **MS Test** add the *include* folder and the *config/mstest* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/mstest"
|
||||
```
|
||||
* To use fakeit with **Boost Test** add the *include* folder and the *config/boost* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/boost"
|
||||
```
|
||||
* To use fakeit with **Catch** add the *include* folder and the *config/catch* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/catch"
|
||||
```
|
||||
* To use fakeit with **tpunit** add the *include* folder and the *config/tpunit* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/tpunit"
|
||||
```
|
||||
* To use fakeit without any testing framework integration (**standalone**) add the *include* folder and the *config/standalone* folder to the include path of your test project:
|
||||
```
|
||||
-I"<fakeit_folder>/include" -I"<fakeit_folder>/config/standalone"
|
||||
```
|
||||
It is recommended to build and run the unit tests to make sure FakeIt fits your environment.
|
||||
#### Building and Running the Unit Tests with GCC
|
||||
```
|
||||
cd build
|
||||
make all
|
||||
```
|
||||
run the tests by typing
|
||||
```
|
||||
./fakeit_tests.exe
|
||||
```
|
||||
#### Building and Running the Unit Tests with Clang
|
||||
```
|
||||
cd build
|
||||
make -f clang_makefile all
|
||||
```
|
||||
run the tests by typing
|
||||
```
|
||||
./fakeit_tests.exe
|
||||
```
|
||||
#### Building and Running the Unit Tests with Visual Studio
|
||||
Open the tests/all_tests.vcxproj project file with Visual Studio 2013. Build and run the project and check the test results.
|
||||
## Limitations
|
||||
* Currently only GCC, Clang and MSC++ are supported.
|
||||
* Can't mock classes with multiple inheritance.
|
||||
* Can't mock classes with virtual inheritance.
|
||||
* Currently mocks are not thread safe.
|
||||
19630
test/lib/FakeIt/fakeit.hpp
Normal file
19630
test/lib/FakeIt/fakeit.hpp
Normal file
File diff suppressed because it is too large
Load Diff
114
test/src/TestArpToNdpPacketHandler.cpp
Normal file
114
test/src/TestArpToNdpPacketHandler.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <fakeit.hpp>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "ArpToNdpPacketHandler.h"
|
||||
#include "HwAddressTranslator.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
#ifndef ArpToNdpPacketHandlerTestPrefix
|
||||
#define ArpToNdpPacketHandlerTestPrefix "ff::"
|
||||
#endif
|
||||
|
||||
namespace TestArpToNdpPacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IP>() == nullptr);
|
||||
|
||||
const Tins::ICMPv6 * ndp = answerPdu.find_pdu<Tins::ICMPv6>();
|
||||
REQUIRE(ndp != nullptr);
|
||||
|
||||
const Tins::IPv6 * ip = answerPdu.find_pdu<Tins::IPv6>();
|
||||
REQUIRE(ip != nullptr);
|
||||
|
||||
const Tins::ARP * arp = currentInputPdu->find_pdu<Tins::ARP>();
|
||||
REQUIRE(arp != nullptr);
|
||||
|
||||
Tins::IPv6Address tmp_ipv6(ArpToNdpPacketHandlerTestPrefix);
|
||||
IpAddressTranslator::toIpv6Address(arp->sender_ip_addr(), tmp_ipv6);
|
||||
REQUIRE(ip->src_addr() == tmp_ipv6);
|
||||
bool isRequest = false;
|
||||
switch (arp->opcode())
|
||||
{
|
||||
case Tins::ARP::REQUEST:
|
||||
isRequest = true;
|
||||
REQUIRE(ndp->type() == Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
||||
REQUIRE(ndp->source_link_layer_addr() == arp->sender_hw_addr());
|
||||
|
||||
IpAddressTranslator::toIpv6Address(arp->target_ip_addr(), tmp_ipv6);
|
||||
REQUIRE(ndp->target_addr()== tmp_ipv6);
|
||||
|
||||
IpAddressTranslator::toSolicitedNodeAddress(arp->target_ip_addr(), tmp_ipv6);
|
||||
REQUIRE(ip->dst_addr() == tmp_ipv6);
|
||||
break;
|
||||
|
||||
case Tins::ARP::REPLY:
|
||||
REQUIRE(ndp->type() == Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
||||
REQUIRE(ndp->target_link_layer_addr() == arp->sender_hw_addr());
|
||||
REQUIRE(ndp->target_addr()== tmp_ipv6);
|
||||
|
||||
IpAddressTranslator::toIpv6Address(arp->target_ip_addr(), tmp_ipv6);
|
||||
REQUIRE(ip->dst_addr() == tmp_ipv6);
|
||||
break;
|
||||
default:
|
||||
REQUIRE( 1 == 0);
|
||||
}
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->src_addr() == arp->sender_hw_addr());
|
||||
|
||||
if (isRequest)
|
||||
{
|
||||
HwAddress tmpHw;
|
||||
HwAddressTranslator::toSolicitedNodeAddress(tmp_ipv6, tmpHw);
|
||||
REQUIRE(answerEth->dst_addr() == tmpHw);
|
||||
}
|
||||
else
|
||||
{
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
REQUIRE(answerEth->dst_addr() == arp->target_hw_addr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test ArpToNdpPacketHandler", "[ArpToNdpPacketHandler]" ) {
|
||||
ArpToNdpPacketHandler handler(ArpToNdpPacketHandlerTestPrefix);
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestArpToNdpPacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::IPv4Address to_resolve_address("192.168.0.1");
|
||||
Tins::IPv4Address own_address("192.168.0.2");
|
||||
HwAddress own_mac_address("01:02:03:12:34:56");
|
||||
Tins::EthernetII arp_request = Tins::ARP::make_arp_request(to_resolve_address, own_address, own_mac_address);
|
||||
TestArpToNdpPacketHandler::currentInputPdu = &arp_request;
|
||||
REQUIRE(handler.handle(arp_request, nullptr) == false);
|
||||
REQUIRE(handler.handle(arp_request, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
HwAddress to_resolve_mac_address("50:60:70:65:43:21");
|
||||
Tins::EthernetII arp_reply = Tins::ARP::make_arp_reply(own_address, to_resolve_address, own_mac_address, to_resolve_mac_address);
|
||||
TestArpToNdpPacketHandler::currentInputPdu = &arp_reply;
|
||||
REQUIRE(handler.handle(arp_reply, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Twice();
|
||||
}
|
||||
50
test/src/TestForwardPacketHandler.cpp
Normal file
50
test/src/TestForwardPacketHandler.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "IPacketHandler.h"
|
||||
#include "ForwardPacketHandler.h"
|
||||
#include "tins/ethernetII.h"
|
||||
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestForwardPacketHandler
|
||||
{
|
||||
IPacketHandler * ptrTargetCallback = nullptr;
|
||||
class MockForwardIPacketHandler : public IPacketHandler
|
||||
{
|
||||
public:
|
||||
int callCount = 0;
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler) override
|
||||
{
|
||||
callCount++;
|
||||
REQUIRE(ptrTargetCallback != nullptr);
|
||||
REQUIRE(ptrTargetCallback == callBackHandler);
|
||||
return callBackHandler->handle(pdu, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MockForwardCallBackIPacketHandler : public IPacketHandler
|
||||
{
|
||||
public:
|
||||
int callCount = 0;
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler) override
|
||||
{
|
||||
callCount++;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "test ForwardPacketHandler", "[ForwardPacketHandler]" )
|
||||
{
|
||||
SPtrIPacketHandler sptrTargetCallBackHandler = std::make_shared<TestForwardPacketHandler::MockForwardCallBackIPacketHandler>();
|
||||
TestForwardPacketHandler::ptrTargetCallback = sptrTargetCallBackHandler.get();
|
||||
SPtrIPacketHandler sptrTargetHandler = std::make_shared<TestForwardPacketHandler::MockForwardIPacketHandler>();
|
||||
Mock<IPacketHandler> mockCallCallbackHandler;
|
||||
Fake(Method(mockCallCallbackHandler, handle));
|
||||
SPtrIPacketHandler sptrForwardHandler = std::make_shared<ForwardPacketHandler>(sptrTargetHandler, sptrTargetCallBackHandler);
|
||||
Tins::EthernetII pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11");
|
||||
REQUIRE(sptrForwardHandler->handle(pkt, &mockCallCallbackHandler.get()) == true);
|
||||
Verify(Method(mockCallCallbackHandler, handle)).Never();
|
||||
REQUIRE(((TestForwardPacketHandler::MockForwardCallBackIPacketHandler *)sptrTargetCallBackHandler.get())->callCount == 1);
|
||||
REQUIRE(((TestForwardPacketHandler::MockForwardIPacketHandler *)sptrTargetHandler.get())->callCount == 1);
|
||||
}
|
||||
18
test/src/TestHwAddressTranslator.cpp
Normal file
18
test/src/TestHwAddressTranslator.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "fakeit.hpp"
|
||||
#include <tins/ipv6_address.h>
|
||||
#include "HwAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
|
||||
TEST_CASE( "test toHwSolicitedNodeAddress", "[HwAddressTranslator]" ) {
|
||||
HwAddress result;
|
||||
|
||||
HwAddressTranslator::toSolicitedNodeAddress(Tins::IPv6Address("2011:0DB8::"), result);
|
||||
REQUIRE(HwAddress("33:33:FF:00:00:00") == result);
|
||||
|
||||
HwAddressTranslator::toSolicitedNodeAddress(Tins::IPv6Address("2011:0DB8::ffff:ff12:3456"), result);
|
||||
REQUIRE(HwAddress("33:33:FF:12:34:56") == result);
|
||||
|
||||
HwAddressTranslator::toSolicitedNodeAddress(Tins::IPv6Address("2011:0DB8::5678:9912:3456"), result);
|
||||
REQUIRE(HwAddress("33:33:FF:12:34:56") == result);
|
||||
}
|
||||
93
test/src/TestIcmp4ToIcmp6PacketHandler.cpp
Normal file
93
test/src/TestIcmp4ToIcmp6PacketHandler.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "tins/ethernetII.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Icmp4ToIcmp6PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
|
||||
namespace TestIcmp4ToIcmp6PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IP>() == nullptr);
|
||||
|
||||
const Tins::IPv6 * ip6 = answerPdu.find_pdu<Tins::IPv6>();
|
||||
const Tins::IP * ip = currentInputPdu->find_pdu<Tins::IP>();
|
||||
REQUIRE(ip != nullptr);
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
|
||||
const Tins::ICMPv6 * icmp6 = answerPdu.find_pdu<Tins::ICMPv6>();
|
||||
const Tins::ICMP * icmp = currentInputPdu->find_pdu<Tins::ICMP>();
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp6 != nullptr);
|
||||
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
const Tins::ICMP::Flags type = icmp->type();
|
||||
switch (type) {
|
||||
case Tins::ICMP::Flags::ECHO_REPLY:
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
case Tins::ICMP::Flags::ECHO_REQUEST:
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REQUEST);
|
||||
break;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Icmp4ToIcmp6PacketHandler", "[Icmp4ToIcmp6PacketHandler]" ) {
|
||||
Icmp4ToIcmp6PacketHandler handler("1::"); // tod fix prefix
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIcmp4ToIcmp6PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / Tins::IP() / Tins::TCP();
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
Tins::ICMP echoRequest(Tins::ICMP::ECHO_REQUEST);
|
||||
echoRequest.id(23);
|
||||
echoRequest.sequence(42);
|
||||
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") / echoRequest;
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
Tins::ICMP echoReply(Tins::ICMP::ECHO_REPLY);
|
||||
echoReply.id(24);
|
||||
echoReply.sequence(45);
|
||||
pkt = Tins::EthernetII("66:55:44:33:22:11", "11:22:33:44:55:66") / Tins::IP("4.3.2.1", "1.2.3.4") / echoReply;
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Twice();
|
||||
}
|
||||
139
test/src/TestIcmp6ToIcmp4PacketHandler.cpp
Normal file
139
test/src/TestIcmp6ToIcmp4PacketHandler.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "tins/arp.h"
|
||||
#include "tins/ethernetII.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Icmp6ToIcmp4PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestIcmp6ToIcmp4PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IPv6>() == nullptr);
|
||||
|
||||
const Tins::IP * ip = answerPdu.find_pdu<Tins::IP>();
|
||||
if (ip != nullptr)
|
||||
{
|
||||
const Tins::IPv6 * ip6 = currentInputPdu->find_pdu<Tins::IPv6>();
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
}
|
||||
|
||||
const Tins::ICMPv6 * icmp6 = currentInputPdu->find_pdu<Tins::ICMPv6>();
|
||||
REQUIRE(icmp6 != nullptr);
|
||||
|
||||
const Tins::ICMP * icmp = answerPdu.find_pdu<Tins::ICMP>();
|
||||
const Tins::ARP * arp = answerPdu.find_pdu<Tins::ARP>();
|
||||
const Tins::ICMPv6::Types type = icmp6->type();
|
||||
switch (type) {
|
||||
case Tins::ICMPv6::ECHO_REPLY:
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
case Tins::ICMPv6::ECHO_REQUEST:
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REQUEST);
|
||||
break;
|
||||
case Tins::ICMPv6::NEIGHBOUR_ADVERT:
|
||||
REQUIRE(arp != nullptr);
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REPLY);
|
||||
return;
|
||||
case Tins::ICMPv6::NEIGHBOUR_SOLICIT:
|
||||
REQUIRE(arp != nullptr);
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Icmp6ToIcmp4PacketHandler", "[Icmp6ToIcmp4PacketHandler]" ) {
|
||||
Icmp6ToIcmp4PacketHandler handler;
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIcmp6ToIcmp4PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / Tins::IPv6() / Tins::TCP();
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
Tins::ICMPv6 echoRequest(Tins::ICMPv6::ECHO_REQUEST);
|
||||
echoRequest.identifier(23);
|
||||
echoRequest.sequence(42);
|
||||
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::1", "::2") / echoRequest;
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
Tins::ICMPv6 echoReply(Tins::ICMPv6::ECHO_REQUEST);
|
||||
echoReply.identifier(22);
|
||||
echoReply.sequence(21);
|
||||
pkt = Tins::EthernetII("66:55:44:33:22:11", "11:22:33:44:55:66") / Tins::IPv6("::2", "::1") / echoReply;
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Twice();
|
||||
|
||||
Tins::IPv6Address targetIp6Address("aa::55:192.168.0.1");
|
||||
Tins::IPv6Address senderIp6Address("bb::22:192.168.0.2");
|
||||
Tins::IPv6Address solicitedIp6Address;
|
||||
Tins::IPv6 ipv6NsPdu;
|
||||
Tins::IPv6 ipv6NaPdu;
|
||||
ipv6NsPdu.src_addr(senderIp6Address);
|
||||
IpAddressTranslator::toSolicitedNodeAddress(targetIp6Address, solicitedIp6Address);
|
||||
ipv6NsPdu.dst_addr(solicitedIp6Address);
|
||||
ipv6NaPdu.src_addr(targetIp6Address);
|
||||
ipv6NaPdu.dst_addr(senderIp6Address);
|
||||
|
||||
Tins::EthernetII::address_type own_mac_address("01:02:03:12:34:56");
|
||||
Tins::EthernetII::address_type to_resolve_mac_address("50:60:70:65:43:21");
|
||||
Tins::ICMPv6 ndpNsPdu(Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
||||
Tins::ICMPv6 ndpNaPdu(Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
||||
|
||||
ndpNsPdu.target_addr(targetIp6Address);
|
||||
ndpNaPdu.target_addr(targetIp6Address);
|
||||
|
||||
Tins::EthernetII ethNs(Tins::EthernetII::address_type(), own_mac_address);
|
||||
Tins::EthernetII ethNa(own_mac_address, to_resolve_mac_address);
|
||||
ethNs /= ipv6NsPdu / ndpNsPdu;
|
||||
ethNa /= ipv6NaPdu / ndpNaPdu;
|
||||
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = ðNs;
|
||||
REQUIRE(handler.handle(ethNs, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = ðNa;
|
||||
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
}
|
||||
60
test/src/TestIp4ToIp6PacketHandler.cpp
Normal file
60
test/src/TestIp4ToIp6PacketHandler.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "tins/ethernetII.h"
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Ip4ToIp6PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
|
||||
namespace TestIp4ToIp6PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IP>() == nullptr);
|
||||
|
||||
const Tins::IPv6 * ip6 = answerPdu.find_pdu<Tins::IPv6>();
|
||||
const Tins::IP * ip = currentInputPdu->find_pdu<Tins::IP>();
|
||||
REQUIRE(ip != nullptr);
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Ip4ToIp6PacketHandler", "[Ip4ToIp6PacketHandler]" ) {
|
||||
Ip4ToIp6PacketHandler handler("1::"); // tod fix prefix
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIp4ToIp6PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / Tins::IP() / Tins::TCP();
|
||||
TestIp4ToIp6PacketHandler::currentInputPdu = &pkt;
|
||||
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();
|
||||
}
|
||||
101
test/src/TestIp6Fragmentation.cpp
Normal file
101
test/src/TestIp6Fragmentation.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <algorithm>
|
||||
#include <fakeit.hpp>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include <tins/rawpdu.h>
|
||||
#include "IpPacketFragmentation.h"
|
||||
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestIp6PacketFragmentation
|
||||
{
|
||||
static Tins::PDU * currentInputPdu = nullptr;
|
||||
static size_t fragmentationCount = 0;
|
||||
static long maxfragmentationSize = 0;
|
||||
static bool firstFragment = true;
|
||||
static uint32_t id = -1;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
const Tins::IPv6 * ipPdu = answerPdu.find_pdu<Tins::IPv6>();
|
||||
if (ipPdu == nullptr)
|
||||
{
|
||||
FAIL("got no ip6 packet");
|
||||
}
|
||||
|
||||
Tins::PDU * ipDataPdu = ipPdu->inner_pdu();
|
||||
if (ipDataPdu == nullptr)
|
||||
{
|
||||
FAIL("got no ip6 inner pdu");
|
||||
}
|
||||
|
||||
const long ipPayloadSize = static_cast<const long>(ipDataPdu->size());
|
||||
REQUIRE(ipPayloadSize <= maxfragmentationSize);
|
||||
REQUIRE(ipPayloadSize > 0);
|
||||
|
||||
const Tins::IPv6::ext_header * fragmentHeader = ipPdu->search_header(Tins::IPv6::FRAGMENT);
|
||||
if (fragmentHeader == nullptr)
|
||||
{
|
||||
FAIL("got no fragment header");
|
||||
}
|
||||
|
||||
FragmentionHeaderUnion fragmentionHeaderUnion;
|
||||
FragmentionHeaderStruct * ptrFragmentionHeaderStruct = &fragmentionHeaderUnion.Structed;
|
||||
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::Constants::IP::PROTO_TCP);
|
||||
REQUIRE(ptrFragmentionHeaderStruct->Reserved == 0);
|
||||
REQUIRE(ptrFragmentionHeaderStruct->Res == 0);
|
||||
REQUIRE(ptrFragmentionHeaderStruct->MFlag == mFlag);
|
||||
REQUIRE(ptrFragmentionHeaderStruct->Identification == id);
|
||||
fragmentationCount--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TEST_MTU
|
||||
#define TEST_MTU 1500
|
||||
#endif
|
||||
|
||||
TEST_CASE( "test Ip6PacketFragmentation", "[Ip6PacketFragmentation]" ) {
|
||||
const size_t mtu = TEST_MTU;
|
||||
ByteVector mtu_Payload;
|
||||
for (size_t i = 0; i < mtu; i++)
|
||||
{
|
||||
mtu_Payload.push_back(0);
|
||||
}
|
||||
|
||||
Tins::RawPDU mtuPayload(mtu_Payload.data(), mtu);
|
||||
IpPacketFragmentation handler(1500);
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIp6PacketFragmentation::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / mtuPayload;
|
||||
TestIp6PacketFragmentation::currentInputPdu = &pkt;
|
||||
TestIp6PacketFragmentation::fragmentationCount = 3;
|
||||
TestIp6PacketFragmentation::maxfragmentationSize = mtu/2;
|
||||
|
||||
REQUIRE(handler.handle(pkt, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / mtuPayload / Tins::IPv6("::1", "::2");
|
||||
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") / Tins::TCP(1,1) /mtuPayload;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Exactly(3);
|
||||
}
|
||||
83
test/src/TestIp6ToIp4PacketHandler.cpp
Normal file
83
test/src/TestIp6ToIp4PacketHandler.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <fakeit.hpp>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Ip6ToIp4PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
#include "TinsNetworkInterfaceCard_t.h"
|
||||
using namespace fakeit;
|
||||
|
||||
|
||||
|
||||
namespace TestIp6ToIp4PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IPv6>() == nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::TCP>() != nullptr);
|
||||
|
||||
const Tins::IP * ip = answerPdu.find_pdu<Tins::IP>();
|
||||
REQUIRE(ip != nullptr);
|
||||
|
||||
const Tins::IPv6 * ip6 = currentInputPdu->find_pdu<Tins::IPv6>();
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Ip6ToIp4PacketHandler", "[Ip6ToIp4PacketHandler]" ) {
|
||||
Ip6ToIp4PacketHandler handler;
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIp6ToIp4PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::IPv6 tmpPkt = Tins::IPv6() / Tins::TCP();
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / tmpPkt;
|
||||
TestIp6ToIp4PacketHandler::currentInputPdu = &pkt;
|
||||
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::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);
|
||||
}
|
||||
114
test/src/TestIpAddressTranslator.cpp
Normal file
114
test/src/TestIpAddressTranslator.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "fakeit.hpp"
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
TEST_CASE( "test not operator", "[IpAddressTranslator]" ) {
|
||||
REQUIRE(Tins::IPv4Address("0.0.0.0") == ~Tins::IPv4Address("255.255.255.255"));
|
||||
REQUIRE(Tins::IPv4Address("0.0.0.255") == ~Tins::IPv4Address("255.255.255.0"));
|
||||
REQUIRE(Tins::IPv4Address("0.0.255.255") == ~Tins::IPv4Address("255.255.0.0"));
|
||||
REQUIRE(Tins::IPv4Address("0.255.255.255") == ~Tins::IPv4Address("255.0.0.0"));
|
||||
REQUIRE(Tins::IPv4Address("255.255.255.255") == ~Tins::IPv4Address("0.0.0.0"));
|
||||
REQUIRE(Tins::IPv4Address("0.255.1.255") == ~Tins::IPv4Address("255.0.254.0"));
|
||||
REQUIRE(Tins::IPv4Address("255.254.255.255") == ~Tins::IPv4Address("0.1.0.0"));
|
||||
|
||||
REQUIRE(Tins::IPv6Address("::0") == ~Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"));
|
||||
REQUIRE(Tins::IPv6Address("::FF") == ~Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FF00"));
|
||||
REQUIRE(Tins::IPv6Address("::FFFF") == ~Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0"));
|
||||
REQUIRE(Tins::IPv6Address("::FFFF:FFFF") == ~Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0:0"));
|
||||
REQUIRE(Tins::IPv6Address("FFFF:FFFF::FFFF:FFFF") == ~Tins::IPv6Address("0:0:FFFF:FFFF:FFFF:FFFF:0:0"));
|
||||
REQUIRE(Tins::IPv6Address("FFFF:0:FFFF:0:FFFF:0:FFFF:0") == ~Tins::IPv6Address("::FFFF:0:FFFF:0:FFFF:0:FFFF"));
|
||||
REQUIRE(Tins::IPv6Address("FFFF:1:FFFF:1:FFFF:1:FFFF:1") == ~Tins::IPv6Address("::FFFE:0:FFFE:0:FFFE:0:FFFE"));
|
||||
|
||||
REQUIRE(Tins::EthernetII::address_type("00:00:00:00:00:00") == ~Tins::EthernetII::address_type("FF:FF:FF:FF:FF:FF"));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:00:00:FF:FF:FF") == ~Tins::EthernetII::address_type("FF:FF:FF:00:00:00"));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:00:FF:FF:FF:FF") == ~Tins::EthernetII::address_type("FF:FF:00:00:00:00"));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:FF:FF:FF:FF:FF") == ~Tins::EthernetII::address_type("FF:00:00:00:00:00"));
|
||||
REQUIRE(Tins::EthernetII::address_type("FF:FF:FF:FF:FF:FF") == ~Tins::EthernetII::address_type("00:00:00:00:00:00"));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:FF:01:FF:FF:FF") == ~Tins::EthernetII::address_type("FF:00:FE:00:00:00"));
|
||||
REQUIRE(Tins::EthernetII::address_type("FF:FE:FF:FF:FF:FF") == ~Tins::EthernetII::address_type("00:01:00:00:00:00"));
|
||||
}
|
||||
|
||||
TEST_CASE( "test and operator", "[IpAddressTranslator]" ) {
|
||||
REQUIRE(Tins::IPv4Address("0.0.0.0") == (Tins::IPv4Address("0.0.0.0") & Tins::IPv4Address("255.255.255.255")));
|
||||
REQUIRE(Tins::IPv4Address("0.0.255.0") == (Tins::IPv4Address("0.0.255.255") & Tins::IPv4Address("255.255.255.0")));
|
||||
REQUIRE(Tins::IPv4Address("0.255.255.0") == (Tins::IPv4Address("0.255.255.255") & Tins::IPv4Address("255.255.255.0")));
|
||||
REQUIRE(Tins::IPv4Address("255.0.0.0") == (Tins::IPv4Address("255.255.255.255") & Tins::IPv4Address("255.0.0.0")));
|
||||
REQUIRE(Tins::IPv4Address("255.255.255.255") == (Tins::IPv4Address("255.255.255.255") & Tins::IPv4Address("255.255.255.255")));
|
||||
REQUIRE(Tins::IPv4Address("0.1.1.1") == (Tins::IPv4Address("0.255.1.255") & Tins::IPv4Address("1.1.255.1")));
|
||||
REQUIRE(Tins::IPv4Address("0.0.0.0") == (Tins::IPv4Address("255.254.255.255") & Tins::IPv4Address("0.1.0.0")));
|
||||
|
||||
REQUIRE(Tins::IPv6Address("::0") == (Tins::IPv6Address("::0") & Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")));
|
||||
REQUIRE(Tins::IPv6Address("::FF") == (Tins::IPv6Address("::FF") & Tins::IPv6Address("FFFF:FFFF:0000:FFFF:0000:FFFF:FFFF:FFFF")));
|
||||
REQUIRE(Tins::IPv6Address("1:0:1:0:1:0:1:0") == (Tins::IPv6Address("FFFF:0:FFFF:0:FFFF:0:FFFF:0") & Tins::IPv6Address("1:FFFF:1:FFFF:1:FFFF:1:FFFF")));
|
||||
|
||||
REQUIRE(Tins::EthernetII::address_type("00:00:00:00:00:00") == (Tins::EthernetII::address_type("00:00:00:00:00:00") & Tins::EthernetII::address_type("FF:FF:FF:FF:FF:FF")));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:00:00:00:00:05") == (Tins::EthernetII::address_type("00:00:00:FF:FF:FF") & Tins::EthernetII::address_type("FF:FF:FF:00:00:05")));
|
||||
REQUIRE(Tins::EthernetII::address_type("00:07:00:00:00:05") == (Tins::EthernetII::address_type("00:07:00:FF:FF:FF") & Tins::EthernetII::address_type("FF:FF:FF:00:00:05")));
|
||||
}
|
||||
|
||||
TEST_CASE( "test or operator", "[IpAddressTranslator]" ) {
|
||||
REQUIRE(Tins::IPv4Address("255.255.255.255") == (Tins::IPv4Address("0.0.0.0") | Tins::IPv4Address("255.255.255.255")));
|
||||
REQUIRE(Tins::IPv4Address("0.255.255.255") == (Tins::IPv4Address("0.0.255.255") | Tins::IPv4Address("0.255.255.0")));
|
||||
REQUIRE(Tins::IPv4Address("255.255.255.255") == (Tins::IPv4Address("0.255.255.255") | Tins::IPv4Address("255.255.255.255")));
|
||||
REQUIRE(Tins::IPv4Address("255.0.0.0") == (Tins::IPv4Address("255.0.0.0") | Tins::IPv4Address("255.0.0.0")));
|
||||
REQUIRE(Tins::IPv4Address("255.255.255.255") == (Tins::IPv4Address("255.255.255.255") | Tins::IPv4Address("255.255.255.255")));
|
||||
REQUIRE(Tins::IPv4Address("1.255.255.255") == (Tins::IPv4Address("0.255.1.255") | Tins::IPv4Address("1.1.255.1")));
|
||||
REQUIRE(Tins::IPv4Address("0.255.0.0") == (Tins::IPv4Address("0.254.0.0") | Tins::IPv4Address("0.1.0.0")));
|
||||
|
||||
REQUIRE(Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") == (Tins::IPv6Address("::0") | Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")));
|
||||
REQUIRE(Tins::IPv6Address("FFFF:FFFF:0000:FFFF:00FF:FFFF:FFFF:FFFF") == (Tins::IPv6Address("FFFF:FFFF:0000:FFFF:00AA:FFFF:FFFF:FFFF") | Tins::IPv6Address("0000:FFFF:0000:FFFF:00FF:FFFF:FFFF:FFFF")));
|
||||
REQUIRE(Tins::IPv6Address("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") == (Tins::IPv6Address("FFFF:0:FFFF:0:FFFF:0:FFFF:0") | Tins::IPv6Address("1:FFFF:1:FFFF:1:FFFF:1:FFFF")));
|
||||
|
||||
REQUIRE(Tins::EthernetII::address_type("FF:FF:FF:FF:FF:FF") == (Tins::EthernetII::address_type("00:00:00:00:00:00") | Tins::EthernetII::address_type("FF:FF:FF:FF:FF:FF")));
|
||||
REQUIRE(Tins::EthernetII::address_type("FF:FF:FF:FF:FF:05") == (Tins::EthernetII::address_type("00:00:00:FF:FF:00") | Tins::EthernetII::address_type("FF:FF:FF:00:00:05")));
|
||||
REQUIRE(Tins::EthernetII::address_type("FF:07:FF:00:00:05") == (Tins::EthernetII::address_type("00:06:00:00:00:00") | Tins::EthernetII::address_type("FF:01:FF:00:00:05")));
|
||||
}
|
||||
|
||||
TEST_CASE( "test toIpv4AddressBytes", "[IpAddressTranslator]" ) {
|
||||
REQUIRE(0 == IpAddressTranslator::toIpv4AddressBytes(Tins::IPv6Address()));
|
||||
REQUIRE(Tins::IPv4Address("0.0.0.1") == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes( "::1")));
|
||||
REQUIRE(Tins::IPv4Address("111.111.111.111") == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes("::111.111.111.111")));
|
||||
REQUIRE(Tins::IPv4Address("192.168.42.1") == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes("2011:0DB8::1111:192.168.42.1")));
|
||||
REQUIRE(Tins::IPv4Address("1.2.3.4") == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes("2011:0DB8::0102:0304")));
|
||||
}
|
||||
|
||||
TEST_CASE( "test toIpv6Address", "[IpAddressTranslator]" ) {
|
||||
Tins::IPv6Address ipv6;
|
||||
IpAddressTranslator::toIpv6Address(Tins::IPv4Address("0.0.0.1"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("::1") == ipv6);
|
||||
|
||||
IpAddressTranslator::toIpv6Address(Tins::IPv4Address("111.111.111.111"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("::111.111.111.111") == ipv6);
|
||||
|
||||
ipv6 = Tins::IPv6Address("2011:0DB8::");
|
||||
IpAddressTranslator::toIpv6Address(Tins::IPv4Address("192.168.42.1"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("2011:0DB8::192.168.42.1") == ipv6);
|
||||
|
||||
IpAddressTranslator::toIpv6Address(Tins::IPv4Address("1.2.3.4"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("2011:0DB8::0102:0304") == ipv6);
|
||||
|
||||
ipv6 = Tins::IPv6Address("2011:0DB8::ffff:ffff:ffff");
|
||||
IpAddressTranslator::toIpv6Address(Tins::IPv4Address("1.2.3.4"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("2011:0DB8::ffff:0102:0304") == ipv6);
|
||||
}
|
||||
|
||||
TEST_CASE( "test toSolicitedNodeAddress", "[IpAddressTranslator]" ) {
|
||||
Tins::IPv6Address ipv6;
|
||||
|
||||
IpAddressTranslator::toSolicitedNodeAddress(Tins::IPv6Address("2011:0DB8::"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("FF02::1:FF00:0") == ipv6);
|
||||
|
||||
IpAddressTranslator::toSolicitedNodeAddress(Tins::IPv6Address("2011:0DB8::ffff:ff12:3456"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("FF02::1:FF12:3456") == ipv6);
|
||||
|
||||
IpAddressTranslator::toSolicitedNodeAddress(Tins::IPv4Address("0.0.0.1"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("FF02::1:FF00:1") == ipv6);
|
||||
|
||||
IpAddressTranslator::toSolicitedNodeAddress(Tins::IPv4Address("1.2.3.4"), ipv6);
|
||||
REQUIRE(Tins::IPv6Address("FF02::1:FF02:0304") == ipv6);
|
||||
|
||||
|
||||
}
|
||||
118
test/src/TestMain.cpp
Normal file
118
test/src/TestMain.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "Main_t.h"
|
||||
#include <fakeit.hpp>
|
||||
#include <chrono>
|
||||
#include "pdutypeforwardpackethandler.h"
|
||||
#include "ArpToNdpPacketHandler.h"
|
||||
#include "Icmp4ToIcmp6PacketHandler.h"
|
||||
#include "Icmp6ToIcmp4PacketHandler.h"
|
||||
#include "Ip4ToIp6PacketHandler.h"
|
||||
#include "Ip6ToIp4PacketHandler.h"
|
||||
#include "IpVersionRouter.h"
|
||||
#include "TinsNetworkInterfaceCard.h"
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <thread>
|
||||
#include <json/json.h>
|
||||
#include <json/value.h>
|
||||
#include <fstream>
|
||||
|
||||
TEST_CASE( "test main setup", "[test_main]" )
|
||||
{
|
||||
|
||||
std::ifstream config_doc("test_config.json", std::ifstream::binary);
|
||||
Json::Value root;
|
||||
config_doc >> root;
|
||||
const Json::Value natpairs = root;
|
||||
|
||||
SPtrIPacketHandlerList routerList;
|
||||
std::vector<std::thread *> threadPool;
|
||||
int mtuCount = 0;
|
||||
for (Json::Value natpair : natpairs)
|
||||
{
|
||||
const std::string pairname = natpair["name"].asString();
|
||||
REQUIRE(pairname == "foo");
|
||||
const Json::Value natPairItems = natpair["items"];
|
||||
SPtrTinsNetworkInterfaceCard ipv4Netcard;
|
||||
SPtrTinsNetworkInterfaceCard ipv6Netcard;
|
||||
Tins::IPv6Address prefix;
|
||||
for (Json::Value natPairItem : natPairItems)
|
||||
{
|
||||
const std::string itemname = natPairItem["nic-name"].asString();
|
||||
REQUIRE(itemname == "lo");
|
||||
const int itemtype = natPairItem["type"].asInt();
|
||||
bool result = itemtype == 4 || itemtype == 6;
|
||||
REQUIRE(result);
|
||||
if (itemtype == 6)
|
||||
{
|
||||
REQUIRE(natPairItem["prefix"].asString() == "42::");
|
||||
}
|
||||
|
||||
const std::string netcardName = natPairItem["nic-name"].asString();
|
||||
SPtrTinsNetworkInterfaceCard netcard = std::make_shared<TinsNetworkInterfaceCard>(netcardName);
|
||||
if(natPairItem.isMember("mtu"))
|
||||
{
|
||||
mtuCount++;
|
||||
REQUIRE(natPairItem["mtu"].asInt() == 1000);
|
||||
}
|
||||
switch (itemtype)
|
||||
{
|
||||
case 4:
|
||||
ipv4Netcard = netcard;
|
||||
break;
|
||||
case 6:
|
||||
ipv6Netcard = netcard;
|
||||
prefix = natPairItem["prefix"].asString();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(mtuCount ==1);
|
||||
SPtrIPacketHandler ip4ToIp6Handler = std::make_shared<Ip4ToIp6PacketHandler>(prefix);
|
||||
SPtrIPacketHandler ip6ToIp4Handler = std::make_shared<Ip6ToIp4PacketHandler>();
|
||||
SPtrIPacketHandler icmp4ToIcmp6Handler = std::make_shared<Icmp4ToIcmp6PacketHandler>(prefix);
|
||||
SPtrIPacketHandler icmp6ToIcmp4Handler = std::make_shared<Icmp6ToIcmp4PacketHandler>();
|
||||
SPtrIPacketHandler arpToNdpHandler = std::make_shared<ArpToNdpPacketHandler>(prefix);
|
||||
|
||||
SPtrIRouter router = std::make_shared<IpVersionRouter>(ipv4Netcard, ipv6Netcard);
|
||||
SPtrPduTypeForwardPacketHandler nat4to6ForwardHandler = std::make_shared<PduTypeForwardPacketHandler>(router);
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ARP, arpToNdpHandler));
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ICMP, icmp4ToIcmp6Handler));
|
||||
nat4to6ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::IP, ip4ToIp6Handler));
|
||||
|
||||
SPtrPduTypeForwardPacketHandler nat6to4ForwardHandler = std::make_shared<PduTypeForwardPacketHandler>(router);
|
||||
nat6to4ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ICMPv6, icmp6ToIcmp4Handler));
|
||||
nat6to4ForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::IPv6, ip6ToIp4Handler));
|
||||
ipv4Netcard->getHandlerList().push_back(nat4to6ForwardHandler);
|
||||
ipv6Netcard->getHandlerList().push_back(nat6to4ForwardHandler);
|
||||
|
||||
std::thread * ipv4Thread = new std::thread(&TinsNetworkInterfaceCard::startListen, ipv4Netcard.get());
|
||||
std::thread * ipv6Thread = new std::thread(&TinsNetworkInterfaceCard::startListen, ipv6Netcard.get());
|
||||
routerList.push_back(router);
|
||||
threadPool.push_back(ipv4Thread);
|
||||
threadPool.push_back(ipv6Thread);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
for (SPtrIPacketHandler routerHandle : routerList)
|
||||
{
|
||||
IpVersionRouter * versionRouter = dynamic_cast<IpVersionRouter *>(routerHandle.get());
|
||||
if (versionRouter == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
versionRouter->getIpv4Card().stopListen();
|
||||
versionRouter->getIpv6Card().stopListen();
|
||||
}
|
||||
|
||||
for (std::thread * ptrThread : threadPool)
|
||||
{
|
||||
ptrThread->join();
|
||||
delete ptrThread;
|
||||
}
|
||||
|
||||
routerList.clear();
|
||||
threadPool.clear();
|
||||
}
|
||||
181
test/src/TestNdpToArpPacketHandler.cpp
Normal file
181
test/src/TestNdpToArpPacketHandler.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include <fakeit.hpp>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "NdpToArpPacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestNdpToArpPacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
|
||||
const Tins::ICMPv6 * ndp = currentInputPdu->find_pdu<Tins::ICMPv6>();
|
||||
REQUIRE(ndp != nullptr);
|
||||
|
||||
const Tins::IPv6 * ip = currentInputPdu->find_pdu<Tins::IPv6>();
|
||||
REQUIRE(ndp != nullptr);
|
||||
|
||||
const Tins::ARP * arp = answerPdu.find_pdu<Tins::ARP>();
|
||||
REQUIRE(arp != nullptr);
|
||||
|
||||
REQUIRE(arp->sender_ip_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip->src_addr())));
|
||||
|
||||
Tins::EthernetII::address_type senderHwAddr;
|
||||
const Tins::ICMPv6::option * ptrHwAddressOption;
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
const Tins::ICMPv6::Types ndpType = ndp->type();
|
||||
bool isRequest = false;
|
||||
if (ndpType == Tins::ICMPv6::Types::NEIGHBOUR_SOLICIT)
|
||||
{
|
||||
isRequest = true;
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REQUEST);
|
||||
ptrHwAddressOption = ndp->search_option(Tins::ICMPv6::OptionTypes::SOURCE_ADDRESS);
|
||||
if (ptrHwAddressOption == nullptr)
|
||||
{
|
||||
if(answerEth == nullptr)
|
||||
{
|
||||
REQUIRE(1 == 0);
|
||||
}
|
||||
|
||||
|
||||
REQUIRE(answerEth->dst_addr() == Tins::EthernetII::BROADCAST);
|
||||
senderHwAddr = answerEth->src_addr();
|
||||
}
|
||||
else
|
||||
{
|
||||
senderHwAddr = ptrHwAddressOption->to<Tins::ICMPv6::hwaddress_type>();
|
||||
}
|
||||
|
||||
REQUIRE(arp->sender_hw_addr() == senderHwAddr);
|
||||
REQUIRE(arp->target_hw_addr() == Tins::EthernetII::address_type());
|
||||
}
|
||||
|
||||
if (ndpType == Tins::ICMPv6::Types::NEIGHBOUR_ADVERT)
|
||||
{
|
||||
REQUIRE(arp->target_ip_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip->dst_addr())));
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REPLY);
|
||||
if(answerEth == nullptr)
|
||||
{
|
||||
REQUIRE(1 == 0);
|
||||
}
|
||||
|
||||
ptrHwAddressOption = ndp->search_option(Tins::ICMPv6::OptionTypes::TARGET_ADDRESS);
|
||||
if (ptrHwAddressOption == nullptr)
|
||||
{
|
||||
senderHwAddr = answerEth->src_addr();
|
||||
}
|
||||
else
|
||||
{
|
||||
senderHwAddr = ptrHwAddressOption->to<Tins::ICMPv6::hwaddress_type>();
|
||||
}
|
||||
|
||||
REQUIRE(arp->sender_hw_addr() == senderHwAddr);
|
||||
REQUIRE(arp->target_hw_addr() == answerEth->dst_addr());
|
||||
}
|
||||
|
||||
if (currEth == nullptr || answerEth==nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
if (isRequest)
|
||||
{
|
||||
REQUIRE(answerEth->dst_addr() == Tins::EthernetII::BROADCAST);
|
||||
}
|
||||
else
|
||||
{
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test NdptoArpPacketHandler", "[NdptoArpPacketHandler]" ) {
|
||||
NdpToArpPacketHandler handler;
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestNdpToArpPacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::IPv6Address targetIp6Address("aa::55:192.168.0.1");
|
||||
Tins::IPv6Address senderIp6Address("bb::22:192.168.0.2");
|
||||
Tins::IPv6Address solicitedIp6Address;
|
||||
Tins::IPv6 ipv6NsPdu;
|
||||
Tins::IPv6 ipv6NaPdu;
|
||||
ipv6NsPdu.src_addr(senderIp6Address);
|
||||
IpAddressTranslator::toSolicitedNodeAddress(targetIp6Address, solicitedIp6Address);
|
||||
ipv6NsPdu.dst_addr(solicitedIp6Address);
|
||||
ipv6NaPdu.src_addr(targetIp6Address);
|
||||
ipv6NaPdu.dst_addr(senderIp6Address);
|
||||
|
||||
Tins::EthernetII::address_type own_mac_address("01:02:03:12:34:56");
|
||||
Tins::EthernetII::address_type to_resolve_mac_address("50:60:70:65:43:21");
|
||||
Tins::ICMPv6 ndpNsPdu(Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
||||
Tins::ICMPv6 ndpNaPdu(Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
||||
|
||||
ndpNsPdu.target_addr(targetIp6Address);
|
||||
ndpNaPdu.target_addr(targetIp6Address);
|
||||
|
||||
Tins::EthernetII ethNs(Tins::EthernetII::address_type(), own_mac_address);
|
||||
Tins::EthernetII ethNa(own_mac_address, to_resolve_mac_address);
|
||||
|
||||
ipv6NsPdu /= ndpNsPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = &ipv6NsPdu;
|
||||
REQUIRE(handler.handle(ipv6NsPdu, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
REQUIRE(handler.handle(ipv6NsPdu, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
ethNs /= ipv6NsPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = ðNs;
|
||||
REQUIRE(handler.handle(ethNs, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
ipv6NsPdu.release_inner_pdu();
|
||||
ethNs.release_inner_pdu();
|
||||
ndpNsPdu.source_link_layer_addr(own_mac_address);
|
||||
ipv6NsPdu /= ndpNsPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = &ipv6NsPdu;
|
||||
REQUIRE(handler.handle(ipv6NsPdu, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
|
||||
ipv6NaPdu /= ndpNaPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = &ipv6NaPdu;
|
||||
REQUIRE(handler.handle(ipv6NaPdu, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Exactly(2);
|
||||
|
||||
REQUIRE(handler.handle(ipv6NaPdu, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Exactly(2);
|
||||
|
||||
ethNa /= ipv6NaPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = ðNa;
|
||||
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
|
||||
ipv6NaPdu.release_inner_pdu();
|
||||
ethNa.release_inner_pdu();
|
||||
ndpNaPdu.target_link_layer_addr(to_resolve_mac_address);
|
||||
ipv6NaPdu /= ndpNaPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = &ipv6NaPdu;
|
||||
REQUIRE(handler.handle(ipv6NaPdu, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Exactly(3);
|
||||
|
||||
ethNa /= ipv6NaPdu;
|
||||
TestNdpToArpPacketHandler::currentInputPdu = ðNa;
|
||||
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
}
|
||||
75
test/src/TestPduTypeForwardPaketHandler.cpp
Normal file
75
test/src/TestPduTypeForwardPaketHandler.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "IPacketHandler.h"
|
||||
#include "pdutypeforwardpackethandler.h"
|
||||
#include "tins/ethernetII.h"
|
||||
#include "tins/ip.h"
|
||||
#include "tins/ipv6.h"
|
||||
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestPduTypePacketForwardPacketHandler
|
||||
{
|
||||
IPacketHandler * ptrTargetCallback = nullptr;
|
||||
class MockPduTypeForwardIPacketHandler : public IPacketHandler
|
||||
{
|
||||
public:
|
||||
int callCount = 0;
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler) override
|
||||
{
|
||||
callCount++;
|
||||
REQUIRE(ptrTargetCallback != nullptr);
|
||||
REQUIRE(ptrTargetCallback == callBackHandler);
|
||||
return callBackHandler->handle(pdu, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MockPduTypeForwardCallBackIPacketHandler : public IPacketHandler
|
||||
{
|
||||
public:
|
||||
int callCount = 0;
|
||||
virtual bool handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler) override
|
||||
{
|
||||
callCount++;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "test PduTypeForwardPacketHandler", "[PduTypeForwardPacketHandler]" )
|
||||
{
|
||||
SPtrIPacketHandler sptrTargetCallBackHandler = std::make_shared<TestPduTypePacketForwardPacketHandler::MockPduTypeForwardCallBackIPacketHandler>();
|
||||
TestPduTypePacketForwardPacketHandler::ptrTargetCallback = sptrTargetCallBackHandler.get();
|
||||
SPtrIPacketHandler sptrTargetHandler = std::make_shared<TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler>();
|
||||
Mock<IPacketHandler> mockCallCallbackHandler;
|
||||
Fake(Method(mockCallCallbackHandler, handle));
|
||||
SPtrPduTypeForwardPacketHandler sptrPduTypeForwardHandler = std::make_shared<PduTypeForwardPacketHandler>(sptrTargetCallBackHandler);
|
||||
Tins::EthernetII pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11");
|
||||
REQUIRE(sptrPduTypeForwardHandler->handle(pkt, &mockCallCallbackHandler.get()) == false);
|
||||
Verify(Method(mockCallCallbackHandler, handle)).Never();
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardCallBackIPacketHandler *)sptrTargetCallBackHandler.get())->callCount == 0);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler.get())->callCount == 0);
|
||||
|
||||
|
||||
sptrPduTypeForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::ETHERNET_II,sptrTargetHandler));
|
||||
REQUIRE(sptrPduTypeForwardHandler->handle(pkt, &mockCallCallbackHandler.get()) == true);
|
||||
Verify(Method(mockCallCallbackHandler, handle)).Never();
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardCallBackIPacketHandler *)sptrTargetCallBackHandler.get())->callCount == 1);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler.get())->callCount == 1);
|
||||
|
||||
Tins::IP pkt2 = Tins::IP("1.1.1.1", "2.2.2.2");
|
||||
SPtrIPacketHandler sptrTargetHandler2 = std::make_shared<TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler>();
|
||||
sptrPduTypeForwardHandler->getHandlerQueue().push_back(PduTypeHandlerMapEntry(Tins::PDU::IP, sptrTargetHandler2));
|
||||
REQUIRE(sptrPduTypeForwardHandler->handle(pkt2, &mockCallCallbackHandler.get()) == true);
|
||||
Verify(Method(mockCallCallbackHandler, handle)).Never();
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardCallBackIPacketHandler *)sptrTargetCallBackHandler.get())->callCount == 2);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler.get())->callCount == 1);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler2.get())->callCount == 1);
|
||||
|
||||
Tins::IPv6 pkt3 = Tins::IPv6("1::1", "2::2");
|
||||
REQUIRE(sptrPduTypeForwardHandler->handle(pkt3, &mockCallCallbackHandler.get()) == false);
|
||||
Verify(Method(mockCallCallbackHandler, handle)).Never();
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardCallBackIPacketHandler *)sptrTargetCallBackHandler.get())->callCount == 2);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler.get())->callCount == 1);
|
||||
REQUIRE(((TestPduTypePacketForwardPacketHandler::MockPduTypeForwardIPacketHandler *)sptrTargetHandler2.get())->callCount == 1);
|
||||
}
|
||||
104
test/src/TestTinsNetworkCard.cpp
Normal file
104
test/src/TestTinsNetworkCard.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "fakeit.hpp"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <tins/arp.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include <tins/sniffer.h>
|
||||
#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<Tins::IP>();
|
||||
const Tins::IP * ip2 = currentInputPdu->find_pdu<Tins::IP>();
|
||||
if(ip1 != nullptr && (ip1->dst_addr() == ip2->dst_addr()))
|
||||
{
|
||||
foundPduCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Tins::ARP * arp1 = pdu.find_pdu<Tins::ARP>();
|
||||
const Tins::ARP * arp2 = currentInputPdu->find_pdu<Tins::ARP>();
|
||||
if(arp1 != nullptr && (arp1->target_ip_addr() == arp2->target_ip_addr()))
|
||||
{
|
||||
foundPduCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "test send and receive Packet", "[TinsNetworkInterfaceCard_SendRec]" )
|
||||
{
|
||||
|
||||
SPtrTinsNetworkInterfaceCard ptrPacketSender = std::make_shared<TinsNetworkInterfaceCard>(Tins::IPv4Address("127.0.0.1"));
|
||||
SPtrTinsNetworkInterfaceCard ptrPacketSniffer = std::make_shared<TinsNetworkInterfaceCard>(Tins::IPv4Address("127.0.0.1"));
|
||||
SPtrIPacketHandler sptrMockHandler = std::make_shared<TestTinsNetworkInterfaceCard::MockPacketHandler>();
|
||||
Mock<IPacketHandler> 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);
|
||||
|
||||
pkt = Tins::ARP::make_arp_request("1.2.3.4", "4.3.2.1", "11:22:33:44:55:66");
|
||||
std::thread sniffThread4(&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();
|
||||
sniffThread4.join();
|
||||
REQUIRE(TestTinsNetworkInterfaceCard::foundPduCount == 5);
|
||||
}
|
||||
33
test/src/test_config.json
Normal file
33
test/src/test_config.json
Normal file
@@ -0,0 +1,33 @@
|
||||
[
|
||||
{
|
||||
"name" : "foo",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"nic-name": "lo",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"nic-name": "lo",
|
||||
"type": 6,
|
||||
"mtu": 1000,
|
||||
"prefix": "42::"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "foo",
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"nic-name": "lo",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"nic-name": "lo",
|
||||
"type": 6,
|
||||
"prefix": "42::"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
26
test/src/testcase.cpp
Normal file
26
test/src/testcase.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include "fakeit.hpp"
|
||||
using namespace fakeit;
|
||||
|
||||
struct SomeInterface {
|
||||
virtual int foo(int) = 0;
|
||||
virtual int bar(int,int) = 0;
|
||||
};
|
||||
|
||||
TEST_CASE( "test foo succss", "[footest]" ) {
|
||||
// Stub a method to return a value once
|
||||
Mock<SomeInterface> mock;
|
||||
|
||||
// Stub a method to return a value once
|
||||
When(Method(mock,foo)).AlwaysReturn(1);
|
||||
|
||||
SomeInterface & i = mock.get();
|
||||
// Production code:
|
||||
i.foo(1);
|
||||
i.foo(2);
|
||||
i.foo(3);
|
||||
|
||||
//c checks
|
||||
Verify(Method(mock,foo));
|
||||
REQUIRE(1 == 1);
|
||||
}
|
||||
Reference in New Issue
Block a user