Пример #1
0
error_t udpSendDatagramEx(NetInterface *interface, uint16_t srcPort, const IpAddr *destIpAddr,
                          uint16_t destPort, NetBuffer *buffer, size_t offset, uint8_t ttl)
{
    error_t error;
    size_t length;
    UdpHeader *header;
    IpPseudoHeader pseudoHeader;

    //Make room for the UDP header
    offset -= sizeof(UdpHeader);
    //Retrieve the length of the datagram
    length = netBufferGetLength(buffer) - offset;

    //Point to the UDP header
    header = netBufferAt(buffer, offset);
    //Sanity check
    if(!header) return ERROR_FAILURE;

    //Format UDP header
    header->srcPort = htons(srcPort);
    header->destPort = htons(destPort);
    header->length = htons(length);
    header->checksum = 0;

#if (IPV4_SUPPORT == ENABLED)
    //Destination address is an IPv4 address?
    if(destIpAddr->length == sizeof(Ipv4Addr))
    {
        Ipv4Addr srcIpAddr;

        //Select the source IPv4 address and the relevant network interface
        //to use when sending data to the specified destination host
        error = ipv4SelectSourceAddr(&interface, destIpAddr->ipv4Addr, &srcIpAddr);
        //Any error to report?
        if(error) return error;

        //Format IPv4 pseudo header
        pseudoHeader.length = sizeof(Ipv4PseudoHeader);
        pseudoHeader.ipv4Data.srcAddr = srcIpAddr;
        pseudoHeader.ipv4Data.destAddr = destIpAddr->ipv4Addr;
        pseudoHeader.ipv4Data.reserved = 0;
        pseudoHeader.ipv4Data.protocol = IPV4_PROTOCOL_UDP;
        pseudoHeader.ipv4Data.length = htons(length);

        //Calculate UDP header checksum
        header->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader.ipv4Data,
                           sizeof(Ipv4PseudoHeader), buffer, offset, length);
    }
    else
#endif
#if (IPV6_SUPPORT == ENABLED)
        //Destination address is an IPv6 address?
        if(destIpAddr->length == sizeof(Ipv6Addr))
        {
            //Select the source IPv6 address and the relevant network interface
            //to use when sending data to the specified destination host
            error = ipv6SelectSourceAddr(&interface,
                                         &destIpAddr->ipv6Addr, &pseudoHeader.ipv6Data.srcAddr);
            //Any error to report?
            if(error) return error;

            //Format IPv6 pseudo header
            pseudoHeader.length = sizeof(Ipv6PseudoHeader);
            pseudoHeader.ipv6Data.destAddr = destIpAddr->ipv6Addr;
            pseudoHeader.ipv6Data.length = htonl(length);
            pseudoHeader.ipv6Data.reserved = 0;
            pseudoHeader.ipv6Data.nextHeader = IPV6_UDP_HEADER;

            //Calculate UDP header checksum
            header->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader.ipv6Data,
                               sizeof(Ipv6PseudoHeader), buffer, offset, length);
        }
        else
#endif
            //Invalid destination address?
        {
            //An internal error has occurred
            return ERROR_FAILURE;
        }

    //Debug message
    TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)\r\n", length);
    //Dump UDP header contents for debugging purpose
    udpDumpHeader(header);

    //Send UDP datagram
    return ipSendDatagram(interface, &pseudoHeader, buffer, offset, ttl);
}
Пример #2
0
error_t rawSocketSendIpPacket(Socket *socket, const IpAddr *destIpAddr,
   const void *data, size_t length, size_t *written)
{
   error_t error;
   size_t offset;
   uint_t timeToLive;
   NetBuffer *buffer;
   NetInterface *interface;
   IpPseudoHeader pseudoHeader;

   //The socket may be bound to a particular network interface
   interface = socket->interface;

   //Allocate a buffer memory to hold the raw IP datagram
   buffer = ipAllocBuffer(0, &offset);
   //Failed to allocate memory?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Start of exception handling block
   do
   {
      //Copy the raw data
      error = netBufferAppend(buffer, data, length);
      //Any error to report?
      if(error) break;

#if (IPV4_SUPPORT == ENABLED)
      //Destination address is an IPv4 address?
      if(destIpAddr->length == sizeof(Ipv4Addr))
      {
         Ipv4Addr srcIpAddr;

         //Select the source IPv4 address and the relevant network interface
         //to use when sending data to the specified destination host
         error = ipv4SelectSourceAddr(&interface, destIpAddr->ipv4Addr, &srcIpAddr);
         //Any error to report?
         if(error) break;

         //Format IPv4 pseudo header
         pseudoHeader.length = sizeof(Ipv4PseudoHeader);
         pseudoHeader.ipv4Data.srcAddr = srcIpAddr;
         pseudoHeader.ipv4Data.destAddr = destIpAddr->ipv4Addr;
         pseudoHeader.ipv4Data.reserved = 0;
         pseudoHeader.ipv4Data.protocol = socket->protocol;
         pseudoHeader.ipv4Data.length = htons(length);

         //Set TTL value
         timeToLive = IPV4_DEFAULT_TTL;
      }
      else
#endif
#if (IPV6_SUPPORT == ENABLED)
      //Destination address is an IPv6 address?
      if(destIpAddr->length == sizeof(Ipv6Addr))
      {
         //Select the source IPv6 address and the relevant network interface
         //to use when sending data to the specified destination host
         error = ipv6SelectSourceAddr(&interface,
            &destIpAddr->ipv6Addr, &pseudoHeader.ipv6Data.srcAddr);

         //Any error to report?
         if(error) break;

         //Format IPv6 pseudo header
         pseudoHeader.length = sizeof(Ipv6PseudoHeader);
         pseudoHeader.ipv6Data.destAddr = destIpAddr->ipv6Addr;
         pseudoHeader.ipv6Data.length = htonl(length);
         pseudoHeader.ipv6Data.reserved = 0;
         pseudoHeader.ipv6Data.nextHeader = socket->protocol;

         //Set Hop Limit value
         timeToLive = IPV6_DEFAULT_HOP_LIMIT;
      }
      else
#endif
      //Invalid destination address?
      {
         //An internal error has occurred
         error = ERROR_FAILURE;
         //Exit immediately
         break;
      }

      //Send raw IP datagram
      error = ipSendDatagram(interface, &pseudoHeader, buffer, offset, timeToLive);
      //Failed to send data?
      if(error) break;

      //Total number of bytes successfully transmitted
      if(written != NULL)
         *written = length;

      //End of exception handling block
   } while(0);

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}