Example #1
0
void ipv4FragTick(NetInterface *interface)
{
   error_t error;
   uint_t i;
   time_t time;
   Ipv4HoleDesc *hole;

   //Acquire exclusive access to the reassembly queue
   osMutexAcquire(interface->ipv4FragQueueMutex);

   //Get current time
   time = osGetTickCount();

   //Loop through the reassembly queue
   for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
   {
      //Point to the current entry in the reassembly queue
      Ipv4FragDesc *frag = &interface->ipv4FragQueue[i];

      //Make sure the entry is currently in use
      if(frag->buffer.chunkCount > 0)
      {
         //If the timer runs out, the partially-reassembled datagram must be
         //discarded and ICMP Time Exceeded message sent to the source host
         if((time - frag->timestamp) >= IPV4_FRAG_TIME_TO_LIVE)
         {
            //Debug message
            TRACE_INFO("IPv4 fragment reassembly timeout...\r\n");
            //Dump IP header contents for debugging purpose
            ipv4DumpHeader(frag->buffer.chunk[0].address);

            //Point to the first hole descriptor
            hole = ipv4FindHole(frag, frag->firstHole);

            //Make sure the fragment zero has been received
            //before sending an ICMP message
            if(hole != NULL && hole->first > 0)
            {
               //Fix the size of the reconstructed datagram
               error = chunkedBufferSetLength((ChunkedBuffer *) &frag->buffer,
                  frag->headerLength + hole->first);

               //Check status code
               if(!error)
               {
                  //Send an ICMP Time Exceeded message
                  icmpSendErrorMessage(interface, ICMP_TYPE_TIME_EXCEEDED,
                     ICMP_CODE_REASSEMBLY_TIME_EXCEEDED, 0, (ChunkedBuffer *) &frag->buffer);
               }
            }

            //Drop the partially reconstructed datagram
            chunkedBufferSetLength((ChunkedBuffer *) &frag->buffer, 0);
         }
      }
   }

   //Release exclusive access to the reassembly queue
   osMutexRelease(interface->ipv4FragQueueMutex);
}
Example #2
0
void ipv4ProcessDatagram(NetInterface *interface,
                         const MacAddr *srcMacAddr, const ChunkedBuffer *buffer)
{
    error_t error;
    size_t offset;
    size_t length;
    Ipv4Header *header;
    IpPseudoHeader pseudoHeader;

    //Retrieve the length of the IPv4 datagram
    length = chunkedBufferGetLength(buffer);

    //Point to the IPv4 header
    header = chunkedBufferAt(buffer, 0);
    //Sanity check
    if(!header) return;

    //Debug message
    TRACE_INFO("IPv4 datagram received (%u bytes)...\r\n", length);
    //Dump IP header contents for debugging purpose
    ipv4DumpHeader(header);

    //Get the offset to the payload
    offset = header->headerLength * 4;
    //Compute the length of the payload
    length -= header->headerLength * 4;

    //Form the IPv4 pseudo header
    pseudoHeader.length = sizeof(Ipv4PseudoHeader);
    pseudoHeader.ipv4Data.srcAddr = header->srcAddr;
    pseudoHeader.ipv4Data.destAddr = header->destAddr;
    pseudoHeader.ipv4Data.reserved = 0;
    pseudoHeader.ipv4Data.protocol = header->protocol;
    pseudoHeader.ipv4Data.length = htons(length);

    //Check the protocol field
    switch(header->protocol)
    {
    //ICMP protocol?
    case IPV4_PROTOCOL_ICMP:
        //Process incoming ICMP message
        icmpProcessMessage(interface, header->srcAddr, buffer, offset);
#if (RAW_SOCKET_SUPPORT == ENABLED)
        //Allow raw sockets to process ICMP messages
        rawSocketProcessDatagram(interface, &pseudoHeader, buffer, offset);
#endif
        //No error to report
        error = NO_ERROR;
        //Continue processing
        break;

#if (IGMP_SUPPORT == ENABLED)
    //IGMP protocol?
    case IPV4_PROTOCOL_IGMP:
        //Process incoming IGMP message
        igmpProcessMessage(interface, buffer, offset);
#if (RAW_SOCKET_SUPPORT == ENABLED)
        //Allow raw sockets to process IGMP messages
        rawSocketProcessDatagram(interface, &pseudoHeader, buffer, offset);
#endif
        //No error to report
        error = NO_ERROR;
        //Continue processing
        break;
#endif

#if (TCP_SUPPORT == ENABLED)
    //TCP protocol?
    case IPV4_PROTOCOL_TCP:
        //Process incoming TCP segment
        tcpProcessSegment(interface, &pseudoHeader, buffer, offset);
        //No error to report
        error = NO_ERROR;
        //Continue processing
        break;
#endif

#if (UDP_SUPPORT == ENABLED)
    //UDP protocol?
    case IPV4_PROTOCOL_UDP:
        //Process incoming UDP datagram
        error = udpProcessDatagram(interface, &pseudoHeader, buffer, offset);
        //Continue processing
        break;
#endif

    //Unknown protocol?
    default:
#if (RAW_SOCKET_SUPPORT == ENABLED)
        //Allow raw sockets to process IPv4 packets
        error = rawSocketProcessDatagram(interface, &pseudoHeader, buffer, offset);
#else
        //Report an error
        error = ERROR_PROTOCOL_UNREACHABLE;
#endif
        //Continue processing
        break;
    }

    //Unreachable protocol?
    if(error == ERROR_PROTOCOL_UNREACHABLE)
    {
        //Send a Destination Unreachable message
        icmpSendErrorMessage(interface, ICMP_TYPE_DEST_UNREACHABLE,
                             ICMP_CODE_PROTOCOL_UNREACHABLE, 0, buffer);
    }
    //Unreachable port?
    else if(error == ERROR_PORT_UNREACHABLE)
    {
        //Send a Destination Unreachable message
        icmpSendErrorMessage(interface, ICMP_TYPE_DEST_UNREACHABLE,
                             ICMP_CODE_PORT_UNREACHABLE, 0, buffer);
    }
}