119 lines
3.4 KiB
C++
119 lines
3.4 KiB
C++
#include "ArpToNdpPacketHandler.h"
|
|
#include <regex>
|
|
#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 "HwAddressTranslator.h"
|
|
#include "IpAddressTranslator.h"
|
|
|
|
ArpToNdpPacketHandler::ArpToNdpPacketHandler(const Tins::IPv6Address & newPrefix)
|
|
{
|
|
prefix = std::make_unique<Tins::IPv6Address>(newPrefix);
|
|
}
|
|
|
|
ArpToNdpPacketHandler::~ArpToNdpPacketHandler()
|
|
{
|
|
}
|
|
|
|
void ArpToNdpPacketHandler::setSolicitedNodeAddress(INOUT Tins::IPv6 & ipv6, IN const Tins::IPv6Address & targetIp)
|
|
{
|
|
UPtrIPv6Address solicitedNodeAddress = std::make_unique<Tins::IPv6Address>();
|
|
Tins::IPv6Address & tmpRef = *solicitedNodeAddress;
|
|
IpAddressTranslator::toSolicitedNodeAddress(targetIp, tmpRef);
|
|
ipv6.dst_addr(tmpRef);
|
|
}
|
|
|
|
bool ArpToNdpPacketHandler::handle(IN const Tins::PDU & pdu, IN IPacketHandler * callBackHandler)
|
|
{
|
|
// callback handvet requeried
|
|
if (callBackHandler == nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// get ipv4 packet
|
|
const Tins::ARP * arpPdu = pdu.find_pdu<Tins::ARP>();
|
|
if(arpPdu == nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// convert ipv4 addresses to ipv6 addresses
|
|
UPtrIPv6Address senderIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
|
UPtrIPv6Address targetIp6Address = std::make_unique<Tins::IPv6Address>(*prefix);
|
|
const Tins::IPv4Address & targetIp =arpPdu->target_ip_addr();
|
|
IpAddressTranslator::toIpv6Address(arpPdu->sender_ip_addr(), *senderIp6Address);
|
|
IpAddressTranslator::toIpv6Address(targetIp, *targetIp6Address);
|
|
|
|
// create ip4 pdu
|
|
std::unique_ptr<Tins::ICMPv6> ndpPdu;
|
|
std::shared_ptr<Tins::IPv6> ipv6Pdu = std::make_shared<Tins::IPv6>();
|
|
ipv6Pdu->src_addr(*senderIp6Address);
|
|
bool isRequest = false;
|
|
const Tins::ARP::hwaddress_type & senderHwAddr = arpPdu->sender_hw_addr();
|
|
switch (arpPdu->opcode())
|
|
{
|
|
case Tins::ARP::REQUEST:
|
|
ndpPdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::NEIGHBOUR_SOLICIT);
|
|
setSolicitedNodeAddress(*ipv6Pdu, *targetIp6Address);
|
|
ndpPdu->source_link_layer_addr(senderHwAddr);
|
|
ndpPdu->target_addr(*targetIp6Address);
|
|
isRequest = true;
|
|
break;
|
|
|
|
case Tins::ARP::REPLY:
|
|
ndpPdu = std::make_unique<Tins::ICMPv6>(Tins::ICMPv6::NEIGHBOUR_ADVERT);
|
|
ipv6Pdu->dst_addr(*targetIp6Address);
|
|
ndpPdu->target_addr(*senderIp6Address);
|
|
ndpPdu->target_link_layer_addr(senderHwAddr);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
std::shared_ptr<Tins::PDU> ptrOutestPdu;
|
|
const Tins::EthernetII * ethPdu = pdu.find_pdu<Tins::EthernetII>();
|
|
if(ethPdu != nullptr)
|
|
{
|
|
// set eth frame
|
|
std::shared_ptr<Tins::EthernetII> ptrEthPdu = std::make_shared<Tins::EthernetII>();
|
|
ptrEthPdu->src_addr(ethPdu->src_addr());
|
|
Tins::EthernetII::address_type dstMac;
|
|
if (isRequest)
|
|
{
|
|
// set solicited address
|
|
UPtrHwAddress solicitedNodeHWAddress = std::make_unique<HwAddress>();
|
|
HwAddressTranslator::toSolicitedNodeAddress(*targetIp6Address, *solicitedNodeHWAddress);
|
|
ptrEthPdu->dst_addr(*solicitedNodeHWAddress);
|
|
}
|
|
else
|
|
{
|
|
ptrEthPdu->dst_addr(ethPdu->dst_addr());
|
|
}
|
|
|
|
ptrOutestPdu = ptrEthPdu;
|
|
*ptrOutestPdu /= *ipv6Pdu;
|
|
}
|
|
else
|
|
{
|
|
ptrOutestPdu = ipv6Pdu;
|
|
}
|
|
|
|
Tins::PDU & outestPdu = *ptrOutestPdu;
|
|
outestPdu /= *ndpPdu;
|
|
return callBackHandler->handle(outestPdu, this);
|
|
}
|
|
|
|
const Tins::IPv6Address & ArpToNdpPacketHandler::getPrefix() const
|
|
{
|
|
return *prefix;
|
|
}
|
|
|
|
void ArpToNdpPacketHandler::setPrefix(const Tins::IPv6Address & newPrefix)
|
|
{
|
|
*prefix = newPrefix;
|
|
}
|