error_t pppSendEchoRep(PppContext *context,
                       const PppEchoPacket *echoReqPacket, PppProtocol protocol)
{
    error_t error;
    size_t length;
    size_t offset;
    NetBuffer *buffer;
    PppEchoPacket *echoRepPacket;

    //Retrieve the length of the Echo-Request packet
    length = ntohs(echoReqPacket->length);

    //Make sure the length is valid
    if(length < sizeof(PppEchoPacket))
        return ERROR_INVALID_LENGTH;
    if(length > context->peerConfig.mru)
        return ERROR_INVALID_LENGTH;

    //Allocate a buffer memory to hold the Echo-Reply packet
    buffer = pppAllocBuffer(sizeof(PppEchoPacket), &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the Echo-Reply packet
    echoRepPacket = netBufferAt(buffer, offset);

    //Format packet header
    echoRepPacket->code = PPP_CODE_CODE_REJ;
    echoRepPacket->identifier = echoReqPacket->identifier;
    echoRepPacket->length = htons(length);
    echoRepPacket->magicNumber = context->localConfig.magicNumber;

    //The data field of the Echo-Request packet is copied into the data
    //field of the Echo-Reply packet
    error = netBufferAppend(buffer, echoReqPacket->data, length - sizeof(PppEchoPacket));

    //Check status code
    if(!error)
    {
        //Debug message
        TRACE_INFO("Sending Echo-Reply packet (%" PRIuSIZE " bytes)...\r\n", length);

        //Send PPP frame
        error = pppSendFrame(context->interface, buffer, offset, protocol);
    }

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
error_t pppSendProtocolRej(PppContext *context, uint8_t identifier,
                           uint16_t protocol, const uint8_t *information, size_t length)
{
    error_t error;
    size_t offset;
    NetBuffer *buffer;
    PppProtocolRejPacket *protocolRejPacket;

    //Calculate the length of the Protocol-Reject packet
    length += sizeof(PppProtocolRejPacket);

    //The Rejected-Information must be truncated to comply with
    //the peer's established MRU
    length = MIN(length, context->peerConfig.mru);

    //Allocate a buffer memory to hold the Protocol-Reject packet
    buffer = pppAllocBuffer(sizeof(PppProtocolRejPacket), &offset);
    //Failed to allocate memory?
    if(!buffer) return ERROR_OUT_OF_MEMORY;

    //Point to the Protocol-Reject packet
    protocolRejPacket = netBufferAt(buffer, offset);

    //Format packet header
    protocolRejPacket->code = PPP_CODE_PROTOCOL_REJ;
    protocolRejPacket->identifier = identifier;
    protocolRejPacket->length = htons(length);
    protocolRejPacket->rejectedProtocol = htons(protocol);

    //The Rejected-Information field contains a copy of the
    //packet which is being rejected
    error = netBufferAppend(buffer, information,
                            length - sizeof(PppProtocolRejPacket));

    //Check status code
    if(!error)
    {
        //Debug message
        TRACE_INFO("Sending Protocol-Reject packet (%" PRIuSIZE " bytes)...\r\n", length);

        //Send PPP frame
        error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
    }

    //Free previously allocated memory block
    netBufferFree(buffer);
    //Return status code
    return error;
}
示例#3
0
error_t udpSendDatagram(Socket *socket, const IpAddr *destIpAddr,
                        uint16_t destPort, const void *data, size_t length, size_t *written)
{
    error_t error;
    size_t offset;
    NetBuffer *buffer;

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

    //Copy data payload
    error = netBufferAppend(buffer, data, length);

    //Successful processing?
    if(!error)
    {
        //Send UDP datagram
        error = udpSendDatagramEx(socket->interface, socket->localPort,
                                  destIpAddr, destPort, buffer, offset, socket->ttl);
    }

    //Successful processing?
    if(!error)
    {
        //Total number of data bytes successfully transmitted
        if(written != NULL)
            *written = length;
    }

    //Free previously allocated memory
    netBufferFree(buffer);
    //Return status code
    return error;
}
示例#4
0
error_t rawSocketSendEthPacket(Socket *socket,
   const void *data, size_t length, size_t *written)
{
   error_t error;
   uint32_t crc;
   NetBuffer *buffer;
   NetInterface *interface;

   //Select the relevant network interface
   if(!socket->interface)
      interface = netGetDefaultInterface();
   else
      interface = socket->interface;

   //Allocate a buffer memory to hold the raw Ethernet packet
   buffer = netBufferAlloc(0);
   //Failed to allocate buffer?
   if(!buffer) return ERROR_OUT_OF_MEMORY;

   //Copy the raw data
   error = netBufferAppend(buffer, data, length);

   //Successful processing?
   if(!error)
   {
      //Automatic padding not supported by hardware?
      if(!interface->nicDriver->autoPadding)
      {
         //The host controller should manually add padding
         //to the packet before transmitting it
         if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE))
         {
            //Add padding as necessary
            size_t n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length;

            //Append padding bytes
            error = netBufferAppend(buffer, ethPadding, n);
            //Any error to report?
            if(error) return error;

            //Adjust frame length
            length += n;
         }
      }
      //CRC generation not supported by hardware?
      if(!interface->nicDriver->autoCrcGen)
      {
         //Compute CRC over the header and payload
         crc = ethCalcCrcEx(buffer, 0, length);
         //Convert from host byte order to little-endian byte order
         crc = htole32(crc);

         //Append the calculated CRC value
         error = netBufferAppend(buffer, &crc, sizeof(crc));
         //Any error to report?
         if(error) return error;

         //Adjust frame length
         length += sizeof(crc);
      }

      //Debug message
      TRACE_DEBUG("Sending raw Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);

      //Send the resulting packet over the specified link
      error = nicSendPacket(interface, buffer, 0);
   }

   //Successful processing?
   if(!error)
   {
      //Total number of bytes successfully transmitted
      if(written != NULL)
         *written = length;
   }

   //Free previously allocated memory block
   netBufferFree(buffer);
   //Return status code
   return error;
}
示例#5
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;
}