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