Webserver+3d print

Dependents:   Nucleo

cyclone_tcp/ppp/ppp_misc.c

Committer:
Sergunb
Date:
2017-02-04
Revision:
0:8918a71cdbe9

File content as of revision 0:8918a71cdbe9:

/**
 * @file ppp_misc.c
 * @brief PPP miscellaneous functions
 *
 * @section License
 *
 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 1.7.6
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL PPP_TRACE_LEVEL

//Dependencies
#include "core/net.h"
#include "ppp/ppp_misc.h"
#include "ppp/ppp_debug.h"
#include "ppp/lcp.h"
#include "ppp/ipcp.h"
#include "ppp/ipv6cp.h"
#include "debug.h"

//Check TCP/IP stack configuration
#if (PPP_SUPPORT == ENABLED)


/**
 * @brief Send Configure-Ack, Nak or Reject packet
 * @param[in] context PPP context
 * @param[in] configureReqPacket Pointer to the incoming Configure-Request
 * @param[in] protocol Protocol field
 * @param[in] code Code field
 * @return Error code
 **/

error_t pppSendConfigureAckNak(PppContext *context,
   const PppConfigurePacket *configureReqPacket, PppProtocol protocol, PppCode code)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppConfigurePacket *configureAckNakPacket;
   PppOption *option;

   //Initialize status code
   error = NO_ERROR;
   //Retrieve the length of the Configure-Request packet
   length = ntohs(configureReqPacket->length);

   //Allocate a buffer memory to hold the Configure-Ack, Nak or Reject packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(buffer == NULL)
      return ERROR_OUT_OF_MEMORY;

   //Point to the beginning of the packet
   configureAckNakPacket = netBufferAt(buffer, offset);

   //Format packet header
   configureAckNakPacket->code = code;
   configureAckNakPacket->identifier = configureReqPacket->identifier;
   configureAckNakPacket->length = sizeof(PppConfigurePacket);

   //Retrieve the length of the option list
   length -= sizeof(PppConfigurePacket);
   //Point to the first option
   option = (PppOption *) configureReqPacket->options;

   //Parse configuration options
   while(length > 0)
   {
      //LCP protocol?
      if(protocol == PPP_PROTOCOL_LCP)
      {
         //Parse LCP option
         lcpParseOption(context, option, length, configureAckNakPacket);
      }
#if (IPV4_SUPPORT == ENABLED)
      //IPCP protocol?
      else if(protocol == PPP_PROTOCOL_IPCP)
      {
         //Parse IPCP option
         ipcpParseOption(context, option, length, configureAckNakPacket);
      }
#endif
#if (IPV6_SUPPORT == ENABLED)
      //IPV6CP protocol?
      else if(protocol == PPP_PROTOCOL_IPV6CP)
      {
         //Parse IPV6CP option
         ipv6cpParseOption(context, option, length, configureAckNakPacket);
      }
#endif

      //Remaining bytes to process
      length -= option->length;
      //Jump to the next option
      option = (PppOption *) ((uint8_t *) option + option->length);
   }

   //Adjust the length of the multi-part buffer
   netBufferSetLength(buffer, offset + configureAckNakPacket->length);
   //Convert length field to network byte order
   configureAckNakPacket->length = htons(configureAckNakPacket->length);

   //Debug message
   if(code == PPP_CODE_CONFIGURE_ACK)
   {
      TRACE_INFO("Sending Configure-Ack packet (%" PRIuSIZE " bytes)...\r\n",
         ntohs(configureAckNakPacket->length));
   }
   else if(code == PPP_CODE_CONFIGURE_NAK)
   {
      TRACE_INFO("Sending Configure-Nak packet (%" PRIuSIZE " bytes)...\r\n",
         ntohs(configureAckNakPacket->length));
   }
   else if(code == PPP_CODE_CONFIGURE_REJ)
   {
      TRACE_INFO("Sending Configure-Reject packet (%" PRIuSIZE " bytes)...\r\n",
         ntohs(configureAckNakPacket->length));
   }

   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) configureAckNakPacket,
      ntohs(configureAckNakPacket->length), protocol);

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

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


/**
 * @brief Send Terminate-Request packet
 * @param[in] context PPP context
 * @param[in] identifier Identifier field
 * @param[in] protocol Protocol field
 * @return Error code
 **/

error_t pppSendTerminateReq(PppContext *context,
   uint8_t identifier, PppProtocol protocol)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppTerminatePacket *terminateReqPacket;

   //Length of the Terminate-Request packet
   length = sizeof(PppTerminatePacket);

   //Allocate a buffer memory to hold the Terminate-Request packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(buffer == NULL)
      return ERROR_OUT_OF_MEMORY;

   //Point to the Terminate-Request packet
   terminateReqPacket = netBufferAt(buffer, offset);

   //Format packet header
   terminateReqPacket->code = PPP_CODE_TERMINATE_REQ;
   terminateReqPacket->identifier = identifier;
   terminateReqPacket->length = htons(length);

   //Debug message
   TRACE_INFO("Sending Terminate-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) terminateReqPacket, length, protocol);

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

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


/**
 * @brief Send Terminate-Ack packet
 * @param[in] context PPP context
 * @param[in] identifier Identifier field
 * @param[in] protocol Protocol field
 * @return Error code
 **/

error_t pppSendTerminateAck(PppContext *context,
   uint8_t identifier, PppProtocol protocol)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppTerminatePacket *terminateAckPacket;

   //Length of the Terminate-Ack packet
   length = sizeof(PppTerminatePacket);

   //Allocate a buffer memory to hold the Terminate-Ack packet
   buffer = pppAllocBuffer(length, &offset);
   //Failed to allocate memory?
   if(buffer == NULL)
      return ERROR_OUT_OF_MEMORY;

   //Point to the Terminate-Ack packet
   terminateAckPacket = netBufferAt(buffer, offset);

   //Format packet header
   terminateAckPacket->code = PPP_CODE_TERMINATE_ACK;
   terminateAckPacket->identifier = identifier;
   terminateAckPacket->length = htons(length);

   //Debug message
   TRACE_INFO("Sending Terminate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length);
   //Dump packet contents for debugging purpose
   pppDumpPacket((PppPacket *) terminateAckPacket, length, protocol);

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

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


/**
 * @brief Send Code-Reject packet
 * @param[in] context PPP context
 * @param[in] packet Un-interpretable packet received from the peer
 * @param[in] identifier Identifier field
 * @param[in] protocol Protocol field
 * @return Error code
 **/

error_t pppSendCodeRej(PppContext *context, const PppPacket *packet,
   uint8_t identifier, PppProtocol protocol)
{
   error_t error;
   size_t length;
   size_t offset;
   NetBuffer *buffer;
   PppCodeRejPacket *codeRejPacket;

   //Calculate the length of the Code-Reject packet
   length = ntohs(packet->length) + sizeof(PppCodeRejPacket);

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

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

   //Point to the Code-Reject packet
   codeRejPacket = netBufferAt(buffer, offset);

   //Format packet header
   codeRejPacket->code = PPP_CODE_CODE_REJ;
   codeRejPacket->identifier = identifier;
   codeRejPacket->length = htons(length);

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

   //Check status code
   if(!error)
   {
      //Debug message
      TRACE_INFO("Sending Code-Reject 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;
}


/**
 * @brief Send Protocol-Reject packet
 * @param[in] context PPP context
 * @param[in] identifier Identifier field
 * @param[in] protocol Rejected protocol
 * @param[in] information Rejected information
 * @param[in] length Length of the rejected information
 * @return Error code
 **/

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


/**
 * @brief Send Echo-Reply packet
 * @param[in] context PPP context
 * @param[in] echoReqPacket Echo-Request packet received from the peer
 * @param[in] protocol Protocol field
 * @return Error code
 **/

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 == NULL)
      return ERROR_OUT_OF_MEMORY;

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

   //Format packet header
   echoRepPacket->code = PPP_CODE_ECHO_REP;
   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;
}


/**
 * @brief Add an option to a Configure packet
 * @param[in,out] packet Pointer to the Configure packet
 * @param[in] optionType Option type
 * @param[in] optionValue Option value
 * @param[in] optionLen Length of the option value
 * @return Error code
 **/

error_t pppAddOption(PppConfigurePacket *packet, uint8_t optionType,
   const void *optionValue, uint8_t optionLen)
{
   PppOption *option;

   //Make sure the length is valid
   if(optionLen > (UINT8_MAX - sizeof(PppOption)))
      return ERROR_INVALID_LENGTH;

   //Point to the end of the Configure packet
   option = (PppOption *) ((uint8_t *) packet + packet->length);

   //Write specified option at current location
   option->type = optionType;
   option->length = optionLen + sizeof(PppOption);
   //Copy option data
   memcpy(option->data, optionValue, optionLen);

   //Update the length of the Configure packet
   packet->length += optionLen + sizeof(PppOption);

   //Successful processing
   return NO_ERROR;
}

#endif