示例#1
0
error_t lcpProcessConfigureReq(PppContext *context,
   const PppConfigurePacket *configureReqPacket)
{
   error_t error;
   size_t length;
   bool_t notRecognizable;
   bool_t notAcceptable;
   PppOption *option;

   //Debug message
   TRACE_INFO("\r\nLCP Receive-Configure-Request event\r\n");

   //Initialize variables
   error = NO_ERROR;
   notRecognizable = FALSE;
   notAcceptable = FALSE;

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

   //Parse configuration options
   while(length > 0)
   {
      //Parse current option
      error = lcpParseOption(context, option, length, NULL);

      //Any error to report?
      if(error == ERROR_INVALID_TYPE)
      {
         //Option not recognizable
         notRecognizable = TRUE;
         //Catch error
         error = NO_ERROR;
      }
      else if(error == ERROR_INVALID_VALUE)
      {
         //Option not acceptable for configuration
         notAcceptable = TRUE;
         //Catch error
         error = NO_ERROR;
      }
      else if(error)
      {
         //Malformed Configure-Request packet
         break;
      }

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

   //Valid Configure-Request packet received from the peer?
   if(!error)
   {
      //Check flags
      if(notRecognizable)
      {
         //If some configuration options received in the Configure-Request are not
         //recognizable or not acceptable for negociation, then the implementation
         //must transmit a Configure-Reject
         pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
            configureReqPacket, PPP_CODE_CONFIGURE_REJ);
      }
      else if(notAcceptable)
      {
         //If all configuration options are recognizable, but some values are not
         //acceptable, then the implementation must transmit a Configure-Nak
         pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
            configureReqPacket, PPP_CODE_CONFIGURE_NAK);
      }
      else
      {
         //If every configuration option received in the Configure-Request is
         //recognizable and all values are acceptable, then the implementation
         //must transmit a Configure-Ack
         pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
            configureReqPacket, PPP_CODE_CONFIGURE_ACK);
      }
   }

   //Return status code
   return error;
}
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) 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)
        //IPCP protocol?
        else if(protocol == PPP_PROTOCOL_IPCP)
        {
            //Parse IPCP option
            ipcpParseOption(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;
}