Exemplo n.º 1
0
error_t ipv4FragmentDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   uint16_t id, const ChunkedBuffer *payload, size_t payloadOffset, uint8_t timeToLive)
{
   error_t error;
   size_t offset;
   size_t length;
   size_t payloadLength;
   size_t fragmentOffset;
   ChunkedBuffer *fragment;

   //Retrieve the length of the payload
   payloadLength = chunkedBufferGetLength(payload) - payloadOffset;

   //Allocate a memory buffer to hold IP fragments
   fragment = ipAllocBuffer(0, &fragmentOffset);
   //Failed to allocate memory?
   if(!fragment)
      return ERROR_OUT_OF_MEMORY;

   //Split the payload into multiple IP fragments
   for(offset = 0; offset < payloadLength; offset += length)
   {
      //Flush the contents of the fragment
      error = chunkedBufferSetLength(fragment, fragmentOffset);
      //Sanity check
      if(error) break;

      //Process the last fragment?
      if((payloadLength - offset) <= IPV4_MAX_FRAG_SIZE)
      {
         //Size of the current fragment
         length = payloadLength - offset;
         //Copy fragment data
         chunkedBufferConcat(fragment, payload, payloadOffset + offset, length);

         //Do not set the MF flag for the last fragment
         error = ipv4SendPacket(interface, pseudoHeader, id,
            offset / 8, fragment, fragmentOffset, timeToLive);
      }
      else
      {
         //Size of the current fragment (must be a multiple of 8-byte blocks)
         length = IPV4_MAX_FRAG_SIZE;
         //Copy fragment data
         chunkedBufferConcat(fragment, payload, payloadOffset + offset, length);

         //Fragmented packets must have the MF flag set
         error = ipv4SendPacket(interface, pseudoHeader, id,
            IPV4_FLAG_MF | (offset / 8), fragment, fragmentOffset, timeToLive);
      }

      //Failed to send current IP packet?
      if(error) break;
   }

   //Free previously allocated memory
   chunkedBufferFree(fragment);
   //Return status code
   return error;
}
Exemplo n.º 2
0
error_t ipv4SendDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
   NetBuffer *buffer, size_t offset, uint8_t ttl)
{
   error_t error;
   size_t length;
   uint16_t id;

   //Retrieve the length of payload
   length = netBufferGetLength(buffer) - offset;

   //Check whether the TTL value is zero
   if(ttl == 0)
   {
      //Use default Time-To-Live value
      ttl = IPV4_DEFAULT_TTL;
   }

   //Identification field is primarily used to identify
   //fragments of an original IP datagram
   id = osAtomicInc16(&interface->ipv4Identification);

   //If the payload length is smaller than the network
   //interface MTU then no fragmentation is needed
   if((length + sizeof(Ipv4Header)) <= interface->ipv4Config.mtu)
   {
      //Send data as is
      error = ipv4SendPacket(interface,
         pseudoHeader, id, 0, buffer, offset, ttl);
   }
   //If the payload length exceeds the network interface MTU
   //then the device must fragment the data
   else
   {
#if (IPV4_FRAG_SUPPORT == ENABLED)
      //Fragment IP datagram into smaller packets
      error = ipv4FragmentDatagram(interface,
         pseudoHeader, id, buffer, offset, ttl);
#else
      //Fragmentation is not supported
      error = ERROR_MESSAGE_TOO_LONG;
#endif
   }

   //Return status code
   return error;
}
Exemplo n.º 3
0
error_t ipv4SendDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader,
                         ChunkedBuffer *buffer, size_t offset, uint8_t timeToLive)
{
    error_t error;
    size_t length;
    uint16_t id;

    //Retrieve the length of payload
    length = chunkedBufferGetLength(buffer) - offset;

    //Identification field is primarily used to identify
    //fragments of an original IP datagram
    id = osAtomicInc16(&interface->ipv4Identification);

    //If the payload length is smaller than the network
    //interface MTU then no fragmentation is needed
    if(length <= IPV4_MAX_PAYLOAD_SIZE)
    {
        //Send data as is
        error = ipv4SendPacket(interface,
                               pseudoHeader, id, 0, buffer, offset, timeToLive);
    }
    //If the payload length exceeds the network interface MTU
    //then the device must fragment the data
    else
    {
#if (IPV4_FRAG_SUPPORT == ENABLED)
        //Fragment IP datagram into smaller packets
        error = ipv4FragmentDatagram(interface,
                                     pseudoHeader, id, buffer, offset, timeToLive);
#else
        //Fragmentation is not supported
        error = ERROR_MESSAGE_TOO_LONG;
#endif
    }

    //Return status code
    return error;
}