Compare commits

22 Commits

Author SHA1 Message Date
stubbfel
c7b58a2e62 updat jsoncpp and cleanup build env 2017-06-16 22:25:35 +02:00
stubbfel
225fd3870f finish ipv6 fragmentation 2017-06-16 15:23:28 +02:00
stubbfel
5185c025d8 add ip fragmentation test and fixes 2017-06-14 23:53:45 +02:00
stubbfel
1345a8013c add IpFragmentation 2017-06-09 00:47:02 +02:00
stubbfel
c0b8a1b5e0 fix calc of arp hash value 2017-06-08 21:38:27 +02:00
stubbfel
d202fdc778 write testmain 2017-05-27 01:33:17 +02:00
stubbfel
008f67e1f1 add pdutypeforwardhander 2017-05-26 18:58:42 +02:00
stubbfel
131d57e808 add ForwardHandler 2017-03-24 19:59:55 +01:00
stubbfel
0facb2f57b add test fo receive and sending packets 2017-03-16 23:36:14 +01:00
stubbfel
76e86f556a getPhyLessPduPtr -> skip ethernet pdus 2017-03-02 00:38:04 +01:00
stubbfel
1f40e10d5c add src/TinsNetworkInterfaceCard_t.h (send pdu and store their hash in a thread safe list) 2017-03-02 00:14:53 +01:00
stubbfel
1664136d14 add tests for icmp handler 2017-02-19 23:31:50 +01:00
stubbfel
45b738c8e2 add icmps handler 2017-02-19 22:28:52 +01:00
stubbfel
6cecaacb23 add test for ndpto arp handler 2017-02-18 22:31:54 +01:00
stubbfel
471bd9459c add NdpToArpPacketHandler 2017-02-16 23:33:50 +01:00
stubbfel
86ff923e8a add test src 2017-02-16 00:55:04 +01:00
stubbfel
9b65fca64a add hw adress translator, add solicitedNodeAddress traslation , finisched arp to ndp handler 2017-02-16 00:47:27 +01:00
stubbfel
7e7e66f0b7 use |-operator to calc solicited-node address (draft)
geändert:       lib/libtins
	geändert:       src/ArpToNdpPacketHandler.cpp
	geändert:       src/Main.cpp
2016-12-15 01:01:07 +01:00
stubbfel
7a781d6d46 Auf Branch develop
zum Commit vorgemerkte Änderungen:
	geändert:       src/AbstractRouter.h
	neue Datei:     src/ArpToNdpPacketHandler.cpp
	neue Datei:     src/ArpToNdpPacketHandler.h
	neue Datei:     src/INetworkInterfaceCard_t.h
	neue Datei:     src/Ip4Packet_t.h
	geändert:       src/Ip6Packet_t.h
	neue Datei:     src/IpVersionRouter.cpp
	neue Datei:     src/IpVersionRouter.h
2016-12-11 23:02:56 +01:00
stubbfel
6979ae8bb2 add ip4 to ip6 handler 2016-12-06 22:15:17 +01:00
stubbfel
79d7336689 add test for handler 2016-12-05 23:39:05 +01:00
stubbfel
41f8c9243f add Ip6toipv4Handler 2016-12-02 01:04:42 +01:00
72 changed files with 22909 additions and 2038 deletions

3
.gitignore vendored
View File

@@ -1,8 +1,9 @@
# Created by https://www.gitignore.io/api/c++,linux,codeblocks # Created by https://www.gitignore.io/api/c++,linux,codeblocks
# project # project
test test/vm
projectfiles projectfiles
CMakeLists.txt.user
### C++ ### ### C++ ###
# Prerequisites # Prerequisites

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "lib/libtins"] [submodule "lib/libtins"]
path = lib/libtins path = lib/libtins
url = git@github.com:stubbfel/libtins.git url = git@github.com:stubbfel/libtins.git
[submodule "lib/jsoncpp"]
path = lib/jsoncpp
url = https://github.com/open-source-parsers/jsoncpp.git

View File

@@ -5,9 +5,20 @@ else ()
set (CMAKE_CXX_STANDARD 11) set (CMAKE_CXX_STANDARD 11)
endif () endif ()
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
project (1261nat) 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_BUILD_SHARED OFF CACHE BOOL "test")
SET(LIBTINS_ENABLE_CXX11 ON CACHE BOOL "test2") SET(LIBTINS_ENABLE_CXX11 ON CACHE BOOL "test2")
SET(LIBTINS_ENABLE_WPA2 OFF CACHE BOOL "test3") 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") SET(PCAP_LIBRARY /usr/lib64/libpcap.so CACHE FILEPATH "test14")
ADD_SUBDIRECTORY(lib/libtins) 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") file(GLOB_RECURSE 1261nat_src_files "src/*.h" "src/*.cpp")
add_executable(1261nat ${1261nat_src_files} ) 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 ()

View File

@@ -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

Submodule lib/jsoncpp added at 56efb6ba83

View File

@@ -1,11 +1,12 @@
#include "AbstractNetworkInterfaceCard.h" #include "AbstractNetworkInterfaceCard.h"
#include "AbstractPacketHandler.h"
AbstractNetworkInterfaceCard::AbstractNetworkInterfaceCard() AbstractNetworkInterfaceCard::AbstractNetworkInterfaceCard()
{ {
//ctor //ctor
} }
AbstractNetworkInterfaceCard::~AbstractNetworkInterfaceCard() AbstractNetworkInterfaceCard::~AbstractNetworkInterfaceCard()
{ {
//dtor //dtor
} }

View File

@@ -1,21 +1,19 @@
#ifndef ABSTRACTNETWORKINTERFACECARD_H #ifndef ABSTRACTNETWORKINTERFACECARD_H
#define ABSTRACTNETWORKINTERFACECARD_H #define ABSTRACTNETWORKINTERFACECARD_H
#include "AbstractPacketHandler_t.h" #include "INetworkInterfaceCard.h"
#include "AbstractRouter_t.h" #include "IPacketHandler_t.h"
#include "IRouter_t.h"
class AbstractNetworkInterfaceCard class AbstractNetworkInterfaceCard : public INetworkInterfaceCard
{ {
public: public:
void sendPacket(/*const Tins::Pdu & pdu*/); protected:
void startListen(); AbstractNetworkInterfaceCard();
void stopListen(); virtual ~AbstractNetworkInterfaceCard();
protected: private:
AbstractNetworkInterfaceCard(); SPtrIPacketHandlerList handlerList;
virtual ~AbstractNetworkInterfaceCard(); SPtrIRouter router;
private:
SPtrAbstractPacketHandlerList handlerList;
SPtrAbstractRouter router;
}; };
#endif // ABSTRACTNETWORKINTERFACECARD_H #endif // ABSTRACTNETWORKINTERFACECARD_H

View File

@@ -1,16 +1,15 @@
#ifndef ABSTRACTPACKETHANDLER_H #ifndef ABSTRACTPACKETHANDLER_H
#define ABSTRACTPACKETHANDLER_H #define ABSTRACTPACKETHANDLER_H
#include "IPacketHandler.h"
class AbstractPacketHandler class AbstractPacketHandler : public IPacketHandler
{ {
public: public:
protected:
protected: AbstractPacketHandler();
AbstractPacketHandler(); virtual ~AbstractPacketHandler();
virtual ~AbstractPacketHandler(); private:
private:
}; };
#endif // ABSTRACTPACKETHANDLER_H #endif // ABSTRACTPACKETHANDLER_H

View File

@@ -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

View File

@@ -2,10 +2,9 @@
AbstractRouter::AbstractRouter() AbstractRouter::AbstractRouter()
{ {
//ctor //ctor
} }
AbstractRouter::~AbstractRouter() AbstractRouter::~AbstractRouter()
{ {
//dtor //dtore
} }

View File

@@ -1,16 +1,15 @@
#ifndef ABSTRACTROUTER_H #ifndef ABSTRACTROUTER_H
#define ABSTRACTROUTER_H #define ABSTRACTROUTER_H
#include "IRouter.h"
class AbstractRouter class AbstractRouter: public IRouter
{ {
public: public:
protected:
protected: AbstractRouter();
AbstractRouter(); virtual ~AbstractRouter();
virtual ~AbstractRouter(); private:
private:
}; };
#endif // ABSTRACTROUTER_H #endif // ABSTRACTROUTER_H

View 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;
}

View 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

View 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());
}

View 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

View 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
View 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

View 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

View 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
View 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
View 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
View File

@@ -0,0 +1,11 @@
#ifndef IROUTER_H
#define IROUTER_H
#include "IRouter_t.h"
#include "IPacketHandler.h"
interface IRouter: IPacketHandler
{
};
#endif

View File

@@ -1,9 +1,9 @@
#ifndef ABSTRACTROUTER_T_H_INCLUDED #ifndef ABSTRACTROUTER_T_H_INCLUDED
#define ABSTRACTROUTER_T_H_INCLUDED #define ABSTRACTROUTER_T_H_INCLUDED
#include <memory> #include "Main_t.h"
class AbstractRouter; interface IRouter;
typedef std::shared_ptr<AbstractRouter> SPtrAbstractRouter; typedef std::shared_ptr<IRouter> SPtrIRouter;
#endif // ABSTRACTROUTER_T_H_INCLUDED #endif // ABSTRACTROUTER_T_H_INCLUDED

View 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);
}

View 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

View 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);
}

View 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
View 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

View 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;
}

View 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
View 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

View 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);
}

View 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

View 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
View 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

View 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);
}

View 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

View 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
View 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
View 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

View File

@@ -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) int main(int argc, char** argv)
{ {
printf("Hello, World\n"); if (argc < 2){
return -1;
}
return 0; 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
View 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

View 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);
}

View 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

View 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;
}

View 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

View 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
View 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::"
}
]
}
]

View 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;
}

View 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

View 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
View 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
View 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
View File

@@ -0,0 +1,141 @@
FakeIt
======
[![Join the chat at https://gitter.im/eranpeer/FakeIt](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eranpeer/FakeIt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
GCC: [![Build Status GCC](https://travis-ci.org/eranpeer/FakeIt.svg?branch=master)](https://travis-ci.org/eranpeer/FakeIt)
[![Coverage Status](https://coveralls.io/repos/eranpeer/FakeIt/badge.svg?branch=master&service=github)](https://coveralls.io/github/eranpeer/FakeIt?branch=master)
MSC: [![Build status MSC](https://ci.appveyor.com/api/projects/status/sy2dk8se2yoxaqve)](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

File diff suppressed because it is too large Load Diff

View 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();
}

View 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);
}

View 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);
}

View 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();
}

View 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 = &ethNs;
REQUIRE(handler.handle(ethNs, &mockHandler.get()) == true);
Verify(Method(mockHandler, handle)).AtLeastOnce();
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &ethNa;
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
Verify(Method(mockHandler, handle)).AtLeastOnce();
}

View 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();
}

View 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);
}

View 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);
}

View 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
View 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();
}

View 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 = &ethNs;
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 = &ethNa;
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 = &ethNa;
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
Verify(Method(mockHandler, handle)).AtLeastOnce();
}

View 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);
}

View 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
View 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
View 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);
}