100 lines
2.9 KiB
C++
100 lines
2.9 KiB
C++
#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);
|
|
}
|