in simulation/src/internet/model/ipv6-l3-protocol.cc [1342:1452]
void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& ip, uint32_t iif)
{
NS_LOG_FUNCTION (this << packet << ip << iif);
Ptr<Packet> p = packet->Copy ();
Ptr<IpL4Protocol> protocol = 0;
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
Ptr<Ipv6Extension> ipv6Extension = 0;
Ipv6Address src = ip.GetSource ();
Ipv6Address dst = ip.GetDestination ();
uint8_t nextHeader = ip.GetNextHeader ();
uint8_t nextHeaderPosition = 0;
bool isDropped = false;
bool stopProcessing = false;
DropReason dropReason;
// check for a malformed hop-by-hop extension
// this is a common case when forging IPv6 raw packets
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
uint8_t buf;
p->CopyData (&buf, 1);
if (buf == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
NS_LOG_WARN("Double Ipv6Header::IPV6_EXT_HOP_BY_HOP in packet, dropping packet");
return;
}
}
/* process all the extensions found and the layer 4 protocol */
do
{
/* it return 0 for non-extension (i.e. layer 4 protocol) */
ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
if (ipv6Extension)
{
uint8_t nextHeaderStep = 0;
uint8_t curHeader = nextHeader;
nextHeaderStep = ipv6Extension->Process (p, nextHeaderPosition, ip, dst, &nextHeader, stopProcessing, isDropped, dropReason);
nextHeaderPosition += nextHeaderStep;
if (isDropped)
{
m_dropTrace (ip, packet, dropReason, this, iif);
}
if (stopProcessing)
{
return;
}
NS_ASSERT_MSG (nextHeaderStep != 0 || curHeader == Ipv6Header::IPV6_EXT_FRAGMENTATION,
"Zero-size IPv6 Option Header, aborting" << *packet );
}
else
{
protocol = GetProtocol (nextHeader, iif);
if (!protocol)
{
NS_LOG_LOGIC ("Unknown Next Header. Drop!");
// For ICMPv6 Error packets
Ptr<Packet> malformedPacket = packet->Copy ();
malformedPacket->AddHeader (ip);
if (nextHeaderPosition == 0)
{
GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, 40);
}
else
{
GetIcmpv6 ()->SendErrorParameterError (malformedPacket, dst, Icmpv6Header::ICMPV6_UNKNOWN_NEXT_HEADER, ip.GetSerializedSize () + nextHeaderPosition);
}
m_dropTrace (ip, p, DROP_UNKNOWN_PROTOCOL, this, iif);
break;
}
else
{
p->RemoveAtStart (nextHeaderPosition);
/* protocol->Receive (p, src, dst, incomingInterface); */
/* L4 protocol */
Ptr<Packet> copy = p->Copy ();
m_localDeliverTrace (ip, p, iif);
enum IpL4Protocol::RxStatus status = protocol->Receive (p, ip, GetInterface (iif));
switch (status)
{
case IpL4Protocol::RX_OK:
break;
case IpL4Protocol::RX_CSUM_FAILED:
break;
case IpL4Protocol::RX_ENDPOINT_CLOSED:
break;
case IpL4Protocol::RX_ENDPOINT_UNREACH:
if (ip.GetDestination ().IsMulticast ())
{
/* do not rely on multicast address */
break;
}
copy->AddHeader (ip);
GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSource (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
}
}
}
}
while (ipv6Extension);
}