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; }