add NdpToArpPacketHandler

This commit is contained in:
stubbfel
2017-02-16 23:33:50 +01:00
parent 86ff923e8a
commit 471bd9459c
5 changed files with 117 additions and 4 deletions

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