diff --git a/test/src/TestArpToNdpPacketHandler.cpp b/test/src/TestArpToNdpPacketHandler.cpp index 6555172..2f4655a 100644 --- a/test/src/TestArpToNdpPacketHandler.cpp +++ b/test/src/TestArpToNdpPacketHandler.cpp @@ -12,8 +12,8 @@ #include "IpAddressTranslator.h" using namespace fakeit; -#ifndef ArpToNdpPacketHandler -#define ArpToNdpPacketHandlerTestPrefix "ff::" +#ifndef ArpToNdpPacketHandlerTestPrefix +#define ArpToNdpPacketHandlerTestPrefix "ff::" #endif namespace TestArpToNdpPacketHandler @@ -29,7 +29,7 @@ namespace TestArpToNdpPacketHandler REQUIRE(ndp != nullptr); const Tins::IPv6 * ip = answerPdu.find_pdu(); - REQUIRE(ndp != nullptr); + REQUIRE(ip != nullptr); const Tins::ARP * arp = currentInputPdu->find_pdu(); REQUIRE(arp != nullptr); diff --git a/test/src/TestNdpToArpPacketHandler.cpp b/test/src/TestNdpToArpPacketHandler.cpp new file mode 100644 index 0000000..e7e0148 --- /dev/null +++ b/test/src/TestNdpToArpPacketHandler.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(); + REQUIRE(ndp != nullptr); + + const Tins::IPv6 * ip = currentInputPdu->find_pdu(); + REQUIRE(ndp != nullptr); + + const Tins::ARP * arp = answerPdu.find_pdu(); + 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(); + const Tins::EthernetII * answerEth = answerPdu.find_pdu(); + 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(); + } + + 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(); + } + + 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 mockHandler; + When(Method(mockHandler, handle)).AlwaysDo([] (IN const Tins::PDU & pdu,...) + { + TestNdpToArpPacketHandler::compareToInputPdu(pdu); + return true; + }); + + Tins::IPv6Address targetIp6Address("aa::55:192.168.0.1"); + Tins::IPv6Address senderIp6Address("bb::22:192.168.0.2"); + Tins::IPv6Address solicitedIp6Address; + Tins::IPv6 ipv6NsPdu; + Tins::IPv6 ipv6NaPdu; + ipv6NsPdu.src_addr(senderIp6Address); + IpAddressTranslator::toSolicitedNodeAddress(targetIp6Address, solicitedIp6Address); + ipv6NsPdu.dst_addr(solicitedIp6Address); + ipv6NaPdu.src_addr(targetIp6Address); + ipv6NaPdu.dst_addr(senderIp6Address); + + Tins::EthernetII::address_type own_mac_address("01:02:03:12:34:56"); + Tins::EthernetII::address_type to_resolve_mac_address("50:60:70:65:43:21"); + Tins::ICMPv6 ndpNsPdu(Tins::ICMPv6::NEIGHBOUR_SOLICIT); + Tins::ICMPv6 ndpNaPdu(Tins::ICMPv6::NEIGHBOUR_ADVERT); + + ndpNsPdu.target_addr(targetIp6Address); + ndpNaPdu.target_addr(targetIp6Address); + + Tins::EthernetII ethNs(Tins::EthernetII::address_type(), own_mac_address); + Tins::EthernetII ethNa(own_mac_address, to_resolve_mac_address); + + ipv6NsPdu /= ndpNsPdu; + TestNdpToArpPacketHandler::currentInputPdu = &ipv6NsPdu; + REQUIRE(handler.handle(ipv6NsPdu, nullptr) == false); + Verify(Method(mockHandler, handle)).Never(); + + REQUIRE(handler.handle(ipv6NsPdu, &mockHandler.get()) == false); + Verify(Method(mockHandler, handle)).Never(); + + ethNs /= ipv6NsPdu; + TestNdpToArpPacketHandler::currentInputPdu = ðNs; + REQUIRE(handler.handle(ethNs, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).Once(); + + ipv6NsPdu.release_inner_pdu(); + ethNs.release_inner_pdu(); + ndpNsPdu.source_link_layer_addr(own_mac_address); + ipv6NsPdu /= ndpNsPdu; + TestNdpToArpPacketHandler::currentInputPdu = &ipv6NsPdu; + REQUIRE(handler.handle(ipv6NsPdu, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).AtLeastOnce(); + + ipv6NaPdu /= ndpNaPdu; + TestNdpToArpPacketHandler::currentInputPdu = &ipv6NaPdu; + REQUIRE(handler.handle(ipv6NaPdu, nullptr) == false); + Verify(Method(mockHandler, handle)).Exactly(2); + + REQUIRE(handler.handle(ipv6NaPdu, &mockHandler.get()) == false); + Verify(Method(mockHandler, handle)).Exactly(2); + + ethNa /= ipv6NaPdu; + TestNdpToArpPacketHandler::currentInputPdu = ðNa; + REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).AtLeastOnce(); + + ipv6NaPdu.release_inner_pdu(); + ethNa.release_inner_pdu(); + ndpNaPdu.target_link_layer_addr(to_resolve_mac_address); + ipv6NaPdu /= ndpNaPdu; + TestNdpToArpPacketHandler::currentInputPdu = &ipv6NaPdu; + REQUIRE(handler.handle(ipv6NaPdu, &mockHandler.get()) == false); + Verify(Method(mockHandler, handle)).Exactly(3); + + ethNa /= ipv6NaPdu; + TestNdpToArpPacketHandler::currentInputPdu = ðNa; + REQUIRE(handler.handle(ethNa, &mockHandler.get()) == true); + Verify(Method(mockHandler, handle)).AtLeastOnce(); +}