diff --git a/src/ArpToNdpPacketHandler.cpp b/src/ArpToNdpPacketHandler.cpp index 2ba7da3..88de743 100644 --- a/src/ArpToNdpPacketHandler.cpp +++ b/src/ArpToNdpPacketHandler.cpp @@ -1,5 +1,4 @@ #include "ArpToNdpPacketHandler.h" -#include #include #include #include @@ -28,7 +27,7 @@ void ArpToNdpPacketHandler::setSolicitedNodeAddress(INOUT Tins::IPv6 & ipv6, IN bool ArpToNdpPacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler) { - // callback handvet requeried + // callback handler requeried if (callBackHandler == nullptr) { return false; diff --git a/src/ArpToNdpPacketHandler.h b/src/ArpToNdpPacketHandler.h index f4e729b..3c9317a 100644 --- a/src/ArpToNdpPacketHandler.h +++ b/src/ArpToNdpPacketHandler.h @@ -4,7 +4,6 @@ #include "AbstractPacketHandler.h" #include "IPacketHandler_t.h" #include "Ip6Packet_t.h" -#include "Ip4Packet_t.h" class ArpToNdpPacketHandler : public AbstractPacketHandler { diff --git a/src/NdpToArpPacketHandler.cpp b/src/NdpToArpPacketHandler.cpp new file mode 100644 index 0000000..2000a9d --- /dev/null +++ b/src/NdpToArpPacketHandler.cpp @@ -0,0 +1,99 @@ +#include "NdpToArpPacketHandler.h" +#include +#include +#include +#include +#include +#include +#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(); + if(ipPdu == nullptr) + { + return false; + } + + // get ipcmp packet, which has the target address field + const Tins::ICMPv6 * ndpPdu = pdu.find_pdu(); + 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(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(); + if(ethNsPdu == nullptr) + { + return false; + } + + senderHwAddr = ethNsPdu->src_addr(); + } + else + { + senderHwAddr = ptrHwAddressOption->to(); + } + + // create arp request + const Tins::IPv6Address & senderIp6Address = ipPdu->src_addr(); + UPtrIPv4Address senderIp = std::make_unique(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(); + 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(); + } + + // create arp reply + const Tins::IPv6Address & dstIp6Address = ipPdu->dst_addr(); + UPtrIPv4Address dstIp = std::make_unique(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); +} diff --git a/src/NdpToArpPacketHandler.h b/src/NdpToArpPacketHandler.h new file mode 100644 index 0000000..3ecd213 --- /dev/null +++ b/src/NdpToArpPacketHandler.h @@ -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 diff --git a/test/src/TestArpToNdpPacketHandler.cpp b/test/src/TestArpToNdpPacketHandler.cpp index cbdf8fc..6555172 100644 --- a/test/src/TestArpToNdpPacketHandler.cpp +++ b/test/src/TestArpToNdpPacketHandler.cpp @@ -42,6 +42,7 @@ namespace TestArpToNdpPacketHandler { 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); @@ -52,6 +53,7 @@ namespace TestArpToNdpPacketHandler 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); @@ -105,7 +107,7 @@ TEST_CASE( "test ArpToNdpPacketHandler", "[ArpToNdpPacketHandler]" ) { 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(to_resolve_address, own_address, to_resolve_mac_address, own_mac_address); + 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();