add tests for icmp handler
This commit is contained in:
@@ -25,5 +25,4 @@ file(GLOB_RECURSE 1261nat_src_files "src/*.h" "src/*.cpp")
|
||||
add_executable(1261nat ${1261nat_src_files} )
|
||||
target_link_libraries (1261nat tins)
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY(test)
|
||||
|
||||
@@ -29,15 +29,18 @@ bool Icmp4ToIcmp6PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandl
|
||||
// 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_REQUEST);
|
||||
break;
|
||||
case Tins::ICMP::Flags::ECHO_REQUEST:
|
||||
icmpv6Pdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
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());
|
||||
@@ -45,13 +48,13 @@ bool Icmp4ToIcmp6PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandl
|
||||
icmpv6Pdu->code(0);
|
||||
|
||||
// replace icmp4 with icmp6 content, adress translation will bo den by Ip4ToIp6PacketHandler
|
||||
const Tins::IP * ipPdu = pdu.find_pdu<Tins::IP>();
|
||||
Tins::PDU * clonePdu = pdu.clone();
|
||||
Tins::IP * ipPdu = clonePdu->find_pdu<Tins::IP>();
|
||||
if(ipPdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::IP * cloneIpPdu = ipPdu->clone();
|
||||
cloneIpPdu->inner_pdu(*icmpv6Pdu);
|
||||
return Ip4ToIp6PacketHandler::handle(*cloneIpPdu, callBackHandler);
|
||||
ipPdu->inner_pdu(*icmpv6Pdu);
|
||||
return Ip4ToIp6PacketHandler::handle(*clonePdu, callBackHandler);
|
||||
}
|
||||
|
||||
@@ -31,18 +31,22 @@ bool Icmp6ToIcmp4PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandl
|
||||
// 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_REQUEST);
|
||||
break;
|
||||
case Tins::ICMPv6::ECHO_REQUEST:
|
||||
icmpv4Pdu = std::make_unique<Tins::ICMP>(Tins::ICMP::Flags::ECHO_REPLY);
|
||||
break;
|
||||
case Tins::ICMPv6::NEIGHBOUR_SOLICIT:
|
||||
case Tins::ICMPv6::NEIGHBOUR_ADVERT:
|
||||
return ndpToArpHandler->handle(pdu, callBackHandler);
|
||||
default:
|
||||
return false;
|
||||
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());
|
||||
@@ -50,13 +54,13 @@ bool Icmp6ToIcmp4PacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandl
|
||||
icmpv4Pdu->code(0);
|
||||
|
||||
// replace icmp4 with icmp6 content, adress translation will bo den by Ip4ToIp6PacketHandler
|
||||
const Tins::IPv6 * ipv6Pdu = pdu.find_pdu<Tins::IPv6>();
|
||||
Tins::PDU * clonePdu = pdu.clone();
|
||||
Tins::IPv6 * ipv6Pdu = clonePdu->find_pdu<Tins::IPv6>();
|
||||
if(ipv6Pdu == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tins::IPv6 * cloneIpv6Pdu = ipv6Pdu->clone();
|
||||
cloneIpv6Pdu->inner_pdu(*icmpv4Pdu);
|
||||
return Ip6ToIp4PacketHandler::handle(*cloneIpv6Pdu, callBackHandler);
|
||||
ipv6Pdu->inner_pdu(*icmpv4Pdu);
|
||||
return Ip6ToIp4PacketHandler::handle(*clonePdu, callBackHandler);
|
||||
}
|
||||
|
||||
93
test/src/TestIcmp4ToIcmp6PacketHandler.cpp
Normal file
93
test/src/TestIcmp4ToIcmp6PacketHandler.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "tins/ethernetII.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Icmp4ToIcmp6PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
|
||||
namespace TestIcmp4ToIcmp6PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IP>() == nullptr);
|
||||
|
||||
const Tins::IPv6 * ip6 = answerPdu.find_pdu<Tins::IPv6>();
|
||||
const Tins::IP * ip = currentInputPdu->find_pdu<Tins::IP>();
|
||||
REQUIRE(ip != nullptr);
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
|
||||
const Tins::ICMPv6 * icmp6 = answerPdu.find_pdu<Tins::ICMPv6>();
|
||||
const Tins::ICMP * icmp = currentInputPdu->find_pdu<Tins::ICMP>();
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp6 != nullptr);
|
||||
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
const Tins::ICMP::Flags type = icmp->type();
|
||||
switch (type) {
|
||||
case Tins::ICMP::Flags::ECHO_REPLY:
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
case Tins::ICMP::Flags::ECHO_REQUEST:
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REQUEST);
|
||||
break;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Icmp4ToIcmp6PacketHandler", "[Icmp4ToIcmp6PacketHandler]" ) {
|
||||
Icmp4ToIcmp6PacketHandler handler("1::"); // tod fix prefix
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIcmp4ToIcmp6PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / Tins::IP() / Tins::TCP();
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
Tins::ICMP echoRequest(Tins::ICMP::ECHO_REQUEST);
|
||||
echoRequest.id(23);
|
||||
echoRequest.sequence(42);
|
||||
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IP("1.2.3.4", "4.3.2.1") / echoRequest;
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
Tins::ICMP echoReply(Tins::ICMP::ECHO_REPLY);
|
||||
echoReply.id(24);
|
||||
echoReply.sequence(45);
|
||||
pkt = Tins::EthernetII("66:55:44:33:22:11", "11:22:33:44:55:66") / Tins::IP("4.3.2.1", "1.2.3.4") / echoReply;
|
||||
TestIcmp4ToIcmp6PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Twice();
|
||||
}
|
||||
139
test/src/TestIcmp6ToIcmp4PacketHandler.cpp
Normal file
139
test/src/TestIcmp6ToIcmp4PacketHandler.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "fakeit.hpp"
|
||||
#include "tins/arp.h"
|
||||
#include "tins/ethernetII.h"
|
||||
#include <tins/icmp.h>
|
||||
#include <tins/icmpv6.h>
|
||||
#include <tins/ip.h>
|
||||
#include <tins/ipv6.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/tcp.h>
|
||||
#include "Icmp6ToIcmp4PacketHandler.h"
|
||||
#include "IpAddressTranslator.h"
|
||||
using namespace fakeit;
|
||||
|
||||
namespace TestIcmp6ToIcmp4PacketHandler
|
||||
{
|
||||
Tins::PDU * currentInputPdu = nullptr;
|
||||
|
||||
void compareToInputPdu(const Tins::PDU & answerPdu)
|
||||
{
|
||||
REQUIRE(currentInputPdu != nullptr);
|
||||
REQUIRE(answerPdu.find_pdu<Tins::IPv6>() == nullptr);
|
||||
|
||||
const Tins::IP * ip = answerPdu.find_pdu<Tins::IP>();
|
||||
if (ip != nullptr)
|
||||
{
|
||||
const Tins::IPv6 * ip6 = currentInputPdu->find_pdu<Tins::IPv6>();
|
||||
REQUIRE(ip6 != nullptr);
|
||||
REQUIRE(ip->src_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->src_addr())));
|
||||
REQUIRE(ip->dst_addr() == Tins::IPv4Address(IpAddressTranslator::toIpv4AddressBytes(ip6->dst_addr())));
|
||||
REQUIRE(answerPdu.inner_pdu() != nullptr);
|
||||
}
|
||||
|
||||
const Tins::ICMPv6 * icmp6 = currentInputPdu->find_pdu<Tins::ICMPv6>();
|
||||
REQUIRE(icmp6 != nullptr);
|
||||
|
||||
const Tins::ICMP * icmp = answerPdu.find_pdu<Tins::ICMP>();
|
||||
const Tins::ARP * arp = answerPdu.find_pdu<Tins::ARP>();
|
||||
const Tins::ICMPv6::Types type = icmp6->type();
|
||||
switch (type) {
|
||||
case Tins::ICMPv6::ECHO_REPLY:
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REPLY);
|
||||
break;
|
||||
case Tins::ICMPv6::ECHO_REQUEST:
|
||||
REQUIRE(icmp != nullptr);
|
||||
REQUIRE(icmp->id() == icmp6->identifier());
|
||||
REQUIRE(icmp6->sequence() == icmp->sequence());
|
||||
REQUIRE(icmp6->type() == Tins::ICMPv6::ECHO_REQUEST);
|
||||
break;
|
||||
case Tins::ICMPv6::NEIGHBOUR_ADVERT:
|
||||
REQUIRE(arp != nullptr);
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REPLY);
|
||||
return;
|
||||
case Tins::ICMPv6::NEIGHBOUR_SOLICIT:
|
||||
REQUIRE(arp != nullptr);
|
||||
REQUIRE(arp->opcode() == Tins::ARP::REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * currEth = currentInputPdu->find_pdu<Tins::EthernetII>();
|
||||
if (currEth == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Tins::EthernetII * answerEth = answerPdu.find_pdu<Tins::EthernetII>();
|
||||
REQUIRE(answerEth->src_addr() == currEth->src_addr());
|
||||
REQUIRE(answerEth->dst_addr() == currEth->dst_addr());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "test Icmp6ToIcmp4PacketHandler", "[Icmp6ToIcmp4PacketHandler]" ) {
|
||||
Icmp6ToIcmp4PacketHandler handler;
|
||||
Mock<IPacketHandler> mockHandler;
|
||||
When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...)
|
||||
{
|
||||
TestIcmp6ToIcmp4PacketHandler::compareToInputPdu(pdu);
|
||||
return true;
|
||||
});
|
||||
|
||||
Tins::EthernetII pkt = Tins::EthernetII() / Tins::IPv6() / Tins::TCP();
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, nullptr) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == false);
|
||||
Verify(Method(mockHandler, handle)).Never();
|
||||
|
||||
Tins::ICMPv6 echoRequest(Tins::ICMPv6::ECHO_REQUEST);
|
||||
echoRequest.identifier(23);
|
||||
echoRequest.sequence(42);
|
||||
pkt = Tins::EthernetII("11:22:33:44:55:66", "66:55:44:33:22:11") / Tins::IPv6("::1", "::2") / echoRequest;
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Once();
|
||||
|
||||
Tins::ICMPv6 echoReply(Tins::ICMPv6::ECHO_REQUEST);
|
||||
echoReply.identifier(22);
|
||||
echoReply.sequence(21);
|
||||
pkt = Tins::EthernetII("66:55:44:33:22:11", "11:22:33:44:55:66") / Tins::IPv6("::2", "::1") / echoReply;
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = &pkt;
|
||||
REQUIRE(handler.handle(pkt, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).Twice();
|
||||
|
||||
Tins::IPv6Address targetIp6Address("aa::55:192.168.0.1");
|
||||
Tins::IPv6Address senderIp6Address("bb::22:192.168.0.2");
|
||||
Tins::IPv6Address solicitedIp6Address;
|
||||
Tins::IPv6 ipv6NsPdu;
|
||||
Tins::IPv6 ipv6NaPdu;
|
||||
ipv6NsPdu.src_addr(senderIp6Address);
|
||||
IpAddressTranslator::toSolicitedNodeAddress(targetIp6Address, solicitedIp6Address);
|
||||
ipv6NsPdu.dst_addr(solicitedIp6Address);
|
||||
ipv6NaPdu.src_addr(targetIp6Address);
|
||||
ipv6NaPdu.dst_addr(senderIp6Address);
|
||||
|
||||
Tins::EthernetII::address_type own_mac_address("01:02:03:12:34:56");
|
||||
Tins::EthernetII::address_type to_resolve_mac_address("50:60:70:65:43:21");
|
||||
Tins::ICMPv6 ndpNsPdu(Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
||||
Tins::ICMPv6 ndpNaPdu(Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
||||
|
||||
ndpNsPdu.target_addr(targetIp6Address);
|
||||
ndpNaPdu.target_addr(targetIp6Address);
|
||||
|
||||
Tins::EthernetII ethNs(Tins::EthernetII::address_type(), own_mac_address);
|
||||
Tins::EthernetII ethNa(own_mac_address, to_resolve_mac_address);
|
||||
ethNs /= ipv6NsPdu / ndpNsPdu;
|
||||
ethNa /= ipv6NaPdu / ndpNaPdu;
|
||||
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = ðNs;
|
||||
REQUIRE(handler.handle(ethNs, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
|
||||
TestIcmp6ToIcmp4PacketHandler::currentInputPdu = ðNa;
|
||||
REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true);
|
||||
Verify(Method(mockHandler, handle)).AtLeastOnce();
|
||||
}
|
||||
Reference in New Issue
Block a user