void Ipv6L3Protocol::LocalDeliver()

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