internet: (fixes #385) IPv6 NA are now sent directly by the NetDevice
This commit is contained in:
committed by
Tommaso Pecorella
parent
707a929eb2
commit
8d4e5772c8
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user