void chapProcessPacket(PppContext *context, const PppPacket *packet, size_t length) { //Ensure the length of the incoming CHAP packet is valid if(length < sizeof(PppPacket)) return; //Check the length field if(ntohs(packet->length) > length) return; if(ntohs(packet->length) < sizeof(PppPacket)) return; //Save the length of the CHAP packet length = ntohs(packet->length); //Debug message TRACE_INFO("CHAP packet received (%" PRIuSIZE " bytes)...\r\n", length); //Dump CHAP packet contents for debugging purpose pppDumpPacket(packet, length, PPP_PROTOCOL_CHAP); //CHAP is done at initial link establishment, and could also be //requested after link establishment if(context->pppPhase != PPP_PHASE_AUTHENTICATE && context->pppPhase != PPP_PHASE_NETWORK) { //Any packets received during any other phase must be silently discarded return; } //Check CHAP code field switch(packet->code) { //Challenge packet? case CHAP_CODE_CHALLENGE: //Process Challenge packet chapProcessChallenge(context, (ChapChallengePacket *) packet, length); break; //Response packet? case CHAP_CODE_RESPONSE: //Process Response packet chapProcessResponse(context, (ChapResponsePacket *) packet, length); break; //Success packet? case CHAP_CODE_SUCCESS: //Process Success packet chapProcessSuccess(context, (ChapSuccessPacket *) packet, length); break; //Failure packet? case CHAP_CODE_FAILURE: //Process Failure packet chapProcessFailure(context, (ChapFailurePacket *) packet, length); break; //Unknown code field default: //Silently drop the incoming packet break; } }
error_t chapSendResponse(PppContext *context, const uint8_t *value) { error_t error; size_t n; size_t length; size_t offset; NetBuffer *buffer; ChapResponsePacket *responsePacket; //Retrieve the length of the username n = strlen(context->username); //Calculate the length of the Response packet length = sizeof(ChapResponsePacket) + MD5_DIGEST_SIZE + n; //Allocate a buffer memory to hold the Response packet buffer = pppAllocBuffer(length, &offset); //Failed to allocate memory? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the Response packet responsePacket = netBufferAt(buffer, offset); //Format packet header responsePacket->code = CHAP_CODE_RESPONSE; responsePacket->identifier = context->chapFsm.peerIdentifier; responsePacket->length = htons(length); responsePacket->valueSize = MD5_DIGEST_SIZE; //Copy the Response value memcpy(responsePacket->value, value, MD5_DIGEST_SIZE); //The Name field is one or more octets representing the //identification of the system transmitting the packet memcpy(responsePacket->value + MD5_DIGEST_SIZE, context->username, n); //Debug message TRACE_INFO("Sending CHAP Response packet (%" PRIuSIZE " bytes)...\r\n", length); //Dump packet contents for debugging purpose pppDumpPacket((PppPacket *) responsePacket, length, PPP_PROTOCOL_CHAP); //Send PPP frame error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); //Free previously allocated memory block netBufferFree(buffer); //Return status code return error; }
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) 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; }
error_t chapSendFailure(PppContext *context) { error_t error; size_t length; size_t offset; NetBuffer *buffer; PppPacket *failurePacket; //Retrieve the length of the Failure packet length = sizeof(PppPacket); //Allocate a buffer memory to hold the Failure packet buffer = pppAllocBuffer(length, &offset); //Failed to allocate memory? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the Failure packet failurePacket = netBufferAt(buffer, offset); //Format packet header failurePacket->code = CHAP_CODE_FAILURE; failurePacket->identifier = context->chapFsm.localIdentifier; failurePacket->length = htons(length); //Debug message TRACE_INFO("Sending CHAP Failure packet (%" PRIuSIZE " bytes)...\r\n", length); //Dump packet contents for debugging purpose pppDumpPacket((PppPacket *) failurePacket, length, PPP_PROTOCOL_CHAP); //Send PPP frame error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); //Free previously allocated memory block netBufferFree(buffer); //Return status code return error; }
error_t lcpSendConfigureReq(PppContext *context) { error_t error; size_t length; size_t offset; NetBuffer *buffer; PppConfigurePacket *configureReqPacket; //Debug message TRACE_INFO("LCP Send-Configure-Request callback\r\n"); //Calculate the maximum size of the Configure-Request packet length = sizeof(PppConfigurePacket) + sizeof(LcpMruOption) + sizeof(LcpAccmOption); //Allocate a buffer memory to hold the packet buffer = pppAllocBuffer(length, &offset); //Failed to allocate memory? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the Configure-Request packet configureReqPacket = netBufferAt(buffer, offset); //Format packet header configureReqPacket->code = PPP_CODE_CONFIGURE_REQ; configureReqPacket->identifier = ++context->lcpFsm.identifier; configureReqPacket->length = sizeof(PppConfigurePacket); //Make sure the Maximum-Receive-Unit option has not been previously rejected if(!context->localConfig.mruRejected) { //Convert MRU to network byte order uint16_t value = htons(context->localConfig.mru); //Add option pppAddOption(configureReqPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t)); } //Make sure the Async-Control-Character-Map option has not been previously rejected if(!context->localConfig.accmRejected) { //Convert ACCM to network byte order uint32_t value = htonl(context->localConfig.accm); //Add option pppAddOption(configureReqPacket, LCP_OPTION_ACCM, &value, sizeof(uint32_t)); } //Save packet length length = configureReqPacket->length; //Convert length field to network byte order configureReqPacket->length = htons(length); //Adjust the length of the multi-part buffer netBufferSetLength(buffer, offset + length); //Debug message TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length); //Dump packet contents for debugging purpose pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_LCP); //Send PPP frame error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP); //The restart counter is decremented each time a Configure-Request is sent if(context->lcpFsm.restartCounter > 0) context->lcpFsm.restartCounter--; //Save the time at which the packet was sent context->lcpFsm.timestamp = osGetSystemTime(); //Free previously allocated memory block netBufferFree(buffer); //Return status code return error; }
void lcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length) { //Ensure the length of the incoming LCP packet is valid if(length < sizeof(PppPacket)) return; //Check the length field if(ntohs(packet->length) > length) return; if(ntohs(packet->length) < sizeof(PppPacket)) return; //Save the length of the LCP packet length = ntohs(packet->length); //Debug message TRACE_INFO("LCP packet received (%" PRIuSIZE " bytes)...\r\n", length); //Dump LCP packet contents for debugging purpose pppDumpPacket(packet, length, PPP_PROTOCOL_LCP); //Check LCP code field switch(packet->code) { //Configure-Request packet? case PPP_CODE_CONFIGURE_REQ: //Process Configure-Request packet lcpProcessConfigureReq(context, (PppConfigurePacket *) packet); break; //Configure-Ack packet? case PPP_CODE_CONFIGURE_ACK: //Process Configure-Ack packet lcpProcessConfigureAck(context, (PppConfigurePacket *) packet); break; //Configure-Nak packet? case PPP_CODE_CONFIGURE_NAK: //Process Configure-Nak packet lcpProcessConfigureNak(context, (PppConfigurePacket *) packet); break; //Configure-Reject packet? case PPP_CODE_CONFIGURE_REJ: //Process Configure-Reject packet lcpProcessConfigureReject(context, (PppConfigurePacket *) packet); break; //Terminate-Request packet? case PPP_CODE_TERMINATE_REQ: //Process Terminate-Request packet lcpProcessTerminateReq(context, (PppTerminatePacket *) packet); break; //Terminate-Ack packet? case PPP_CODE_TERMINATE_ACK: //Process Terminate-Ack packet lcpProcessTerminateAck(context, (PppTerminatePacket *) packet); break; //Code-Reject packet? case PPP_CODE_CODE_REJ: //Process Code-Reject packet lcpProcessCodeRej(context, (PppCodeRejPacket *) packet); break; //Protocol-Reject packet? case PPP_CODE_PROTOCOL_REJ: //Process Protocol-Reject packet lcpProcessProtocolRej(context, (PppProtocolRejPacket *) packet); break; //Echo-Request packet? case PPP_CODE_ECHO_REQ: //Process Echo-Request packet lcpProcessEchoReq(context, (PppEchoPacket *) packet); break; //Echo-Reply packet? case PPP_CODE_ECHO_REP: //Process Echo-Reply packet lcpProcessEchoRep(context, (PppEchoPacket *) packet); break; //Discard-Request packet? case PPP_CODE_DISCARD_REQ: //Process Discard-Request packet lcpProcessDiscardReq(context, (PppDiscardReqPacket *) packet); break; //Unknown code field default: //The packet is un-interpretable lcpProcessUnknownCode(context, packet); break; } }
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; }
error_t chapSendChallenge(PppContext *context) { error_t error; size_t n; size_t length; size_t offset; NetBuffer *buffer; ChapChallengePacket *challengePacket; //Retrieve the length of the username n = strlen(context->username); //Calculate the length of the Challenge packet length = sizeof(ChapChallengePacket) + MD5_DIGEST_SIZE + n; //Allocate a buffer memory to hold the Challenge packet buffer = pppAllocBuffer(length, &offset); //Failed to allocate memory? if(!buffer) return ERROR_OUT_OF_MEMORY; //Point to the Challenge packet challengePacket = netBufferAt(buffer, offset); //Format packet header challengePacket->code = CHAP_CODE_CHALLENGE; challengePacket->identifier = ++context->chapFsm.localIdentifier; challengePacket->length = htons(length); challengePacket->valueSize = MD5_DIGEST_SIZE; //Make sure that the callback function has been registered if(context->settings.randCallback != NULL) { //Generate a random challenge value error = context->settings.randCallback( context->chapFsm.challenge, MD5_DIGEST_SIZE); } else { //Report an error error = ERROR_FAILURE; } //Check status code if(!error) { //Copy the challenge value memcpy(challengePacket->value, context->chapFsm.challenge, MD5_DIGEST_SIZE); //The Name field is one or more octets representing the //identification of the system transmitting the packet memcpy(challengePacket->value + MD5_DIGEST_SIZE, context->username, n); //Debug message TRACE_INFO("Sending CHAP Challenge packet (%" PRIuSIZE " bytes)...\r\n", length); //Dump packet contents for debugging purpose pppDumpPacket((PppPacket *) challengePacket, length, PPP_PROTOCOL_CHAP); //Send PPP frame error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); //The restart counter is decremented each time a Challenge packet is sent if(context->chapFsm.restartCounter > 0) context->chapFsm.restartCounter--; //Save the time at which the packet was sent context->chapFsm.timestamp = osGetSystemTime(); } //Free previously allocated memory block netBufferFree(buffer); //Return status code return error; }