add NdpToArpPacketHandler
This commit is contained in:
99
src/NdpToArpPacketHandler.cpp
Normal file
99
src/NdpToArpPacketHandler.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user