internet: (fixes #385) IPv6 NA are now sent directly by the NetDevice

This commit is contained in:
Tommaso Pecorella
2021-04-10 00:31:51 +02:00
committed by Tommaso Pecorella
parent 707a929eb2
commit 8d4e5772c8

View File

@@ -522,45 +522,74 @@ void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv
return;
}
Icmpv6OptionLinkLayerAddress lla (1);
Address hardwareAddress;
NdiscCache::Entry* entry = 0;
Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
uint8_t flags = 0;
/* XXX search all options following the NS header */
/* search all options following the NS header */
Icmpv6OptionLinkLayerAddress sllaoHdr (true);
bool next = true;
bool hasSllao = false;
while (next == true)
{
uint8_t type;
packet->CopyData (&type, sizeof (type));
switch (type)
{
case Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE:
if (!hasSllao)
{
packet->RemoveHeader (sllaoHdr);
hasSllao = true;
}
break;
default:
/* unknow option, quit */
next = false;
}
if (packet->GetSize () == 0)
{
next = false;
}
}
Address replyMacAddress;
if (src != Ipv6Address::GetAny ())
{
uint8_t type;
packet->CopyData (&type, sizeof(type));
if (type != Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE)
{
return;
}
/* Get LLA */
packet->RemoveHeader (lla);
entry = cache->Lookup (src);
if (!entry)
{
if (!hasSllao)
{
NS_LOG_LOGIC ("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a NCE, discarding.");
return;
}
entry = cache->Add (src);
entry->SetRouter (false);
entry->MarkStale (lla.GetAddress ());
entry->MarkStale (sllaoHdr.GetAddress ());
replyMacAddress = sllaoHdr.GetAddress ();
}
else if (entry->GetMacAddress () != lla.GetAddress ())
else if (hasSllao && (entry->GetMacAddress () != sllaoHdr.GetAddress ()))
{
entry->MarkStale (lla.GetAddress ());
entry->MarkStale (sllaoHdr.GetAddress ());
replyMacAddress = sllaoHdr.GetAddress ();
}
else
{
replyMacAddress = entry->GetMacAddress ();
}
flags = 3; /* S + O flags */
}
else
{
/* it means someone do a DAD */
/* it's a DAD */
flags = 1; /* O flag */
replyMacAddress = interface->GetDevice ()->GetMulticast (dst);
}
/* send a NA to src */
@@ -571,14 +600,16 @@ void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv
flags += 4; /* R flag */
}
hardwareAddress = interface->GetDevice ()->GetAddress ();
Address hardwareAddress = interface->GetDevice ()->GetAddress ();
NdiscCache::Ipv6PayloadHeaderPair p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (),
src.IsAny () ? dst : src, // DAD replies must go to the multicast group it was sent to.
&hardwareAddress,
flags );
interface->Send (p.first, p.second, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
/* not a NS for us discard it */
// We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not change it beyond what we did already).
Ptr<Packet> pkt = p.first;
pkt->AddHeader (p.second);
interface->GetDevice ()->Send (pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
}
NdiscCache::Ipv6PayloadHeaderPair Icmpv6L4Protocol::ForgeRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress)