Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lcp.c Source File

lcp.c

Go to the documentation of this file.
00001 /**
00002  * @file lcp.c
00003  * @brief LCP (PPP Link Control Protocol)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL PPP_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "ppp/ppp_fsm.h"
00035 #include "ppp/ppp_misc.h"
00036 #include "ppp/ppp_debug.h"
00037 #include "ppp/lcp.h"
00038 #include "ppp/ipcp.h"
00039 #include "ppp/ipv6cp.h"
00040 #include "ppp/pap.h"
00041 #include "ppp/chap.h"
00042 #include "debug.h"
00043 
00044 //Check TCP/IP stack configuration
00045 #if (PPP_SUPPORT == ENABLED)
00046 
00047 
00048 /**
00049  * @brief LCP FSM callbacks
00050  **/
00051 
00052 const PppCallbacks lcpCallbacks =
00053 {
00054    lcpThisLayerUp,
00055    lcpThisLayerDown,
00056    lcpThisLayerStarted,
00057    lcpThisLayerFinished,
00058    lcpInitRestartCount,
00059    lcpZeroRestartCount,
00060    lcpSendConfigureReq,
00061    lcpSendConfigureAck,
00062    lcpSendConfigureNak,
00063    lcpSendConfigureRej,
00064    lcpSendTerminateReq,
00065    lcpSendTerminateAck,
00066    lcpSendCodeRej,
00067    lcpSendEchoRep
00068 };
00069 
00070 
00071 /**
00072  * @brief LCP Open event
00073  * @param[in] context PPP context
00074  * @return Error code
00075  **/
00076 
00077 error_t lcpOpen(PppContext *context)
00078 {
00079    //Debug message
00080    TRACE_INFO("\r\nLCP Open event\r\n");
00081 
00082    //Advance to the Establish phase
00083    context->pppPhase = PPP_PHASE_ESTABLISH;
00084 
00085    //The link is administratively available for traffic
00086    pppOpenEvent(context, &context->lcpFsm, &lcpCallbacks);
00087    //The lower layer is ready to carry packets
00088    pppUpEvent(context, &context->lcpFsm, &lcpCallbacks);
00089 
00090    //Successful processing
00091    return NO_ERROR;
00092 }
00093 
00094 
00095 /**
00096  * @brief LCP Close event
00097  * @param[in] context PPP context
00098  * @return Error code
00099  **/
00100 
00101 error_t lcpClose(PppContext *context)
00102 {
00103    //Debug message
00104    TRACE_INFO("\r\nLCP Close event\r\n");
00105 
00106    //The link is no longer available for traffic
00107    pppCloseEvent(context, &context->lcpFsm, &lcpCallbacks);
00108 
00109    //Successful processing
00110    return NO_ERROR;
00111 }
00112 
00113 
00114 /**
00115  * @brief LCP timer handler
00116  *
00117  * This routine must be periodically called by the TCP/IP stack to
00118  * manage retransmissions
00119  *
00120  * @param[in] context PPP context
00121  **/
00122 
00123 void lcpTick(PppContext *context)
00124 {
00125    //Check whether the restart timer is running
00126    if(context->lcpFsm.state >= PPP_STATE_4_CLOSING &&
00127       context->lcpFsm.state <= PPP_STATE_8_ACK_SENT)
00128    {
00129       //Get current time
00130       systime_t time = osGetSystemTime();
00131 
00132       //Check restart timer
00133       if((time - context->lcpFsm.timestamp) >= PPP_RESTART_TIMER)
00134       {
00135          //Debug message
00136          TRACE_INFO("\r\nLCP Timeout event\r\n");
00137 
00138          //The restart timer is used to retransmit Configure-Request
00139          //and Terminate-Request packets
00140          pppTimeoutEvent(context, &context->lcpFsm, &lcpCallbacks);
00141       }
00142    }
00143 }
00144 
00145 
00146 /**
00147  * @brief Process an incoming LCP packet
00148  * @param[in] context PPP context
00149  * @param[in] packet LCP packet received from the peer
00150  * @param[in] length Length of the packet, in bytes
00151  **/
00152 
00153 void lcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
00154 {
00155    //Ensure the length of the incoming LCP packet is valid
00156    if(length < sizeof(PppPacket))
00157       return;
00158 
00159    //Check the length field
00160    if(ntohs(packet->length) > length)
00161       return;
00162    if(ntohs(packet->length) < sizeof(PppPacket))
00163       return;
00164 
00165    //Save the length of the LCP packet
00166    length = ntohs(packet->length);
00167 
00168    //Debug message
00169    TRACE_INFO("LCP packet received (%" PRIuSIZE " bytes)...\r\n", length);
00170    //Dump LCP packet contents for debugging purpose
00171    pppDumpPacket(packet, length, PPP_PROTOCOL_LCP);
00172 
00173    //Check LCP code field
00174    switch(packet->code)
00175    {
00176    //Configure-Request packet?
00177    case PPP_CODE_CONFIGURE_REQ:
00178       //Process Configure-Request packet
00179       lcpProcessConfigureReq(context, (PppConfigurePacket *) packet);
00180       break;
00181    //Configure-Ack packet?
00182    case PPP_CODE_CONFIGURE_ACK:
00183       //Process Configure-Ack packet
00184       lcpProcessConfigureAck(context, (PppConfigurePacket *) packet);
00185       break;
00186    //Configure-Nak packet?
00187    case PPP_CODE_CONFIGURE_NAK:
00188       //Process Configure-Nak packet
00189       lcpProcessConfigureNak(context, (PppConfigurePacket *) packet);
00190       break;
00191    //Configure-Reject packet?
00192    case PPP_CODE_CONFIGURE_REJ:
00193       //Process Configure-Reject packet
00194       lcpProcessConfigureReject(context, (PppConfigurePacket *) packet);
00195       break;
00196    //Terminate-Request packet?
00197    case PPP_CODE_TERMINATE_REQ:
00198       //Process Terminate-Request packet
00199       lcpProcessTerminateReq(context, (PppTerminatePacket *) packet);
00200       break;
00201    //Terminate-Ack packet?
00202    case PPP_CODE_TERMINATE_ACK:
00203       //Process Terminate-Ack packet
00204       lcpProcessTerminateAck(context, (PppTerminatePacket *) packet);
00205       break;
00206    //Code-Reject packet?
00207    case PPP_CODE_CODE_REJ:
00208       //Process Code-Reject packet
00209       lcpProcessCodeRej(context, (PppCodeRejPacket *) packet);
00210       break;
00211    //Protocol-Reject packet?
00212    case PPP_CODE_PROTOCOL_REJ:
00213       //Process Protocol-Reject packet
00214       lcpProcessProtocolRej(context, (PppProtocolRejPacket *) packet);
00215       break;
00216    //Echo-Request packet?
00217    case PPP_CODE_ECHO_REQ:
00218       //Process Echo-Request packet
00219       lcpProcessEchoReq(context, (PppEchoPacket *) packet);
00220       break;
00221    //Echo-Reply packet?
00222    case PPP_CODE_ECHO_REP:
00223       //Process Echo-Reply packet
00224       lcpProcessEchoRep(context, (PppEchoPacket *) packet);
00225       break;
00226    //Discard-Request packet?
00227    case PPP_CODE_DISCARD_REQ:
00228       //Process Discard-Request packet
00229       lcpProcessDiscardReq(context, (PppDiscardReqPacket *) packet);
00230       break;
00231    //Unknown code field
00232    default:
00233       //The packet is un-interpretable
00234       lcpProcessUnknownCode(context, packet);
00235       break;
00236    }
00237 }
00238 
00239 
00240 /**
00241  * @brief Process Configure-Request packet
00242  * @param[in] context PPP context
00243  * @param[in] configureReqPacket Packet received from the peer
00244  * @return Error code
00245  **/
00246 
00247 error_t lcpProcessConfigureReq(PppContext *context,
00248    const PppConfigurePacket *configureReqPacket)
00249 {
00250    error_t error;
00251    size_t length;
00252    bool_t notRecognizable;
00253    bool_t notAcceptable;
00254    PppOption *option;
00255 
00256    //Debug message
00257    TRACE_INFO("\r\nLCP Receive-Configure-Request event\r\n");
00258 
00259    //Initialize variables
00260    error = NO_ERROR;
00261    notRecognizable = FALSE;
00262    notAcceptable = FALSE;
00263 
00264    //Retrieve the length of the option list
00265    length = ntohs(configureReqPacket->length) - sizeof(PppConfigurePacket);
00266    //Point to the first option
00267    option = (PppOption *) configureReqPacket->options;
00268 
00269    //Parse configuration options
00270    while(length > 0)
00271    {
00272       //Parse current option
00273       error = lcpParseOption(context, option, length, NULL);
00274 
00275       //Any error to report?
00276       if(error == ERROR_INVALID_TYPE)
00277       {
00278          //Option not recognizable
00279          notRecognizable = TRUE;
00280          //Catch error
00281          error = NO_ERROR;
00282       }
00283       else if(error == ERROR_INVALID_VALUE)
00284       {
00285          //Option not acceptable for configuration
00286          notAcceptable = TRUE;
00287          //Catch error
00288          error = NO_ERROR;
00289       }
00290       else if(error)
00291       {
00292          //Malformed Configure-Request packet
00293          break;
00294       }
00295 
00296       //Remaining bytes to process
00297       length -= option->length;
00298       //Jump to the next option
00299       option = (PppOption *) ((uint8_t *) option + option->length);
00300    }
00301 
00302    //Valid Configure-Request packet received from the peer?
00303    if(!error)
00304    {
00305       //Check flags
00306       if(notRecognizable)
00307       {
00308          //If some configuration options received in the Configure-Request are not
00309          //recognizable or not acceptable for negotiation, then the implementation
00310          //must transmit a Configure-Reject
00311          pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
00312             configureReqPacket, PPP_CODE_CONFIGURE_REJ);
00313       }
00314       else if(notAcceptable)
00315       {
00316          //If all configuration options are recognizable, but some values are not
00317          //acceptable, then the implementation must transmit a Configure-Nak
00318          pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
00319             configureReqPacket, PPP_CODE_CONFIGURE_NAK);
00320       }
00321       else
00322       {
00323          //If every configuration option received in the Configure-Request is
00324          //recognizable and all values are acceptable, then the implementation
00325          //must transmit a Configure-Ack
00326          pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
00327             configureReqPacket, PPP_CODE_CONFIGURE_ACK);
00328       }
00329    }
00330 
00331    //Return status code
00332    return error;
00333 }
00334 
00335 
00336 /**
00337  * @brief Process Configure-Ack packet
00338  * @param[in] context PPP context
00339  * @param[in] configureAckPacket Packet received from the peer
00340  * @return Error code
00341  **/
00342 
00343 error_t lcpProcessConfigureAck(PppContext *context,
00344    const PppConfigurePacket *configureAckPacket)
00345 {
00346    //Debug message
00347    TRACE_INFO("\r\nLCP Receive-Configure-Ack event\r\n");
00348 
00349    //When a packet is received with an invalid Identifier field, the
00350    //packet is silently discarded without affecting the automaton
00351    if(configureAckPacket->identifier != context->lcpFsm.identifier)
00352       return ERROR_WRONG_IDENTIFIER;
00353 
00354    //A valid Configure-Ack packet has been received from the peer
00355    pppRcvConfigureAckEvent(context, &context->lcpFsm, &lcpCallbacks);
00356 
00357    //Successful processing
00358    return NO_ERROR;
00359 }
00360 
00361 
00362 /**
00363  * @brief Process Configure-Nak packet
00364  * @param[in] context PPP context
00365  * @param[in] configureNakPacket Packet received from the peer
00366  * @return Error code
00367  **/
00368 
00369 error_t lcpProcessConfigureNak(PppContext *context,
00370    const PppConfigurePacket *configureNakPacket)
00371 {
00372    size_t length;
00373    PppOption *option;
00374 
00375    //Debug message
00376    TRACE_INFO("LCP Receive-Configure-Nak event\r\n");
00377 
00378    //When a packet is received with an invalid Identifier field, the
00379    //packet is silently discarded without affecting the automaton
00380    if(configureNakPacket->identifier != context->lcpFsm.identifier)
00381       return ERROR_WRONG_IDENTIFIER;
00382 
00383    //Retrieve the length of the option list
00384    length = ntohs(configureNakPacket->length) - sizeof(PppConfigurePacket);
00385    //Point to the first option
00386    option = (PppOption *) configureNakPacket->options;
00387 
00388    //Parse configuration options
00389    while(length > 0)
00390    {
00391       //Check option length
00392       if(option->length < sizeof(PppOption))
00393          return ERROR_INVALID_LENGTH;
00394       if(option->length > length)
00395          return ERROR_INVALID_LENGTH;
00396 
00397       //Maximum-Receive-Unit option?
00398       if(option->type == LCP_OPTION_MRU)
00399       {
00400          //Cast option
00401          LcpMruOption *mruOption = (LcpMruOption *) option;
00402 
00403          //Check option length
00404          if(mruOption->length != sizeof(LcpMruOption))
00405             return ERROR_INVALID_LENGTH;
00406 
00407          //Save value
00408          context->localConfig.mru = ntohs(mruOption->mru);
00409          //Make sure the MRU is acceptable
00410          context->localConfig.mru = MAX(context->localConfig.mru, PPP_MIN_MRU);
00411          context->localConfig.mru = MIN(context->localConfig.mru, PPP_MAX_MRU);
00412       }
00413       else if(option->type == LCP_OPTION_ACCM)
00414       {
00415          //Cast option
00416          LcpAccmOption *accmOption = (LcpAccmOption *) option;
00417 
00418          //Check option length
00419          if(accmOption->length != sizeof(LcpAccmOption))
00420             return ERROR_INVALID_LENGTH;
00421 
00422          //Save value
00423          context->localConfig.accm = ntohl(accmOption->accm);
00424       }
00425       //Authentication-Protocol option?
00426       else if(option->type == LCP_OPTION_AUTH_PROTOCOL)
00427       {
00428          //Cast option
00429          LcpAuthProtocolOption *authProtocolOption = (LcpAuthProtocolOption *) option;
00430 
00431          //Check option length
00432          if(authProtocolOption->length < sizeof(LcpAuthProtocolOption))
00433             return ERROR_INVALID_LENGTH;
00434 
00435          //Check the value provided by the peer
00436          if(ntohs(authProtocolOption->protocol) == PPP_PROTOCOL_PAP)
00437          {
00438 #if (PAP_SUPPORT == ENABLED)
00439             //Manage authentication policy
00440             if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP)
00441             {
00442                //Select PAP authentication protocol
00443                context->localConfig.authProtocol = PPP_PROTOCOL_PAP;
00444             }
00445 #endif
00446          }
00447          else if(ntohs(authProtocolOption->protocol) == PPP_PROTOCOL_CHAP)
00448          {
00449 #if (CHAP_SUPPORT == ENABLED)
00450             //Make sure that the length of the option is correct
00451             if(authProtocolOption->length > sizeof(LcpAuthProtocolOption))
00452             {
00453                //Check the algorithm identifier
00454                if(authProtocolOption->data[0] == CHAP_ALGO_ID_CHAP_MD5)
00455                {
00456                   //Manage authentication policy
00457                   if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5)
00458                   {
00459                      //Select CHAP with MD5 authentication protocol
00460                      context->localConfig.authProtocol = PPP_PROTOCOL_CHAP;
00461                      context->localConfig.authAlgo = CHAP_ALGO_ID_CHAP_MD5;
00462                   }
00463                }
00464             }
00465 #endif
00466          }
00467       }
00468 
00469       //Remaining bytes to process
00470       length -= option->length;
00471       //Jump to the next option
00472       option = (PppOption *) ((uint8_t *) option + option->length);
00473    }
00474 
00475    //A valid Configure-Nak or Configure-Reject packet has been received from the peer
00476    pppRcvConfigureNakEvent(context, &context->lcpFsm, &lcpCallbacks);
00477 
00478    //Successful processing
00479    return NO_ERROR;
00480 }
00481 
00482 
00483 /**
00484  * @brief Process Configure-Reject packet
00485  * @param[in] context PPP context
00486  * @param[in] configureRejPacket Packet received from the peer
00487  * @return Error code
00488  **/
00489 
00490 error_t lcpProcessConfigureReject(PppContext *context,
00491    const PppConfigurePacket *configureRejPacket)
00492 {
00493    size_t length;
00494    PppOption *option;
00495 
00496    //Debug message
00497    TRACE_INFO("\r\nLCP Receive-Configure-Reject event\r\n");
00498 
00499    //When a packet is received with an invalid Identifier field, the
00500    //packet is silently discarded without affecting the automaton
00501    if(configureRejPacket->identifier != context->lcpFsm.identifier)
00502       return ERROR_WRONG_IDENTIFIER;
00503 
00504    //Retrieve the length of the option list
00505    length = ntohs(configureRejPacket->length) - sizeof(PppConfigurePacket);
00506    //Point to the first option
00507    option = (PppOption *) configureRejPacket->options;
00508 
00509    //Parse configuration options
00510    while(length > 0)
00511    {
00512       //Check option length
00513       if(option->length < sizeof(PppOption))
00514          return ERROR_INVALID_LENGTH;
00515       if(option->length > length)
00516          return ERROR_INVALID_LENGTH;
00517 
00518       //Maximum-Receive-Unit option?
00519       if(option->type == LCP_OPTION_MRU)
00520       {
00521          //The option is not recognized by the peer
00522          context->localConfig.mruRejected = TRUE;
00523          //Restore default value
00524          context->localConfig.mru = PPP_DEFAULT_MRU;
00525       }
00526       //Async-Control-Character-Map option?
00527       else if(option->type == LCP_OPTION_ACCM)
00528       {
00529          //The option is not recognized by the peer
00530          context->localConfig.accmRejected = TRUE;
00531          //Restore default value
00532          context->localConfig.accm = PPP_DEFAULT_ACCM;
00533       }
00534       //Authentication-Protocol option?
00535       else if(option->type == LCP_OPTION_AUTH_PROTOCOL)
00536       {
00537          //This is an unrecoverable error that terminates the connection
00538          pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
00539          //Exit immediately
00540          return ERROR_FAILURE;
00541       }
00542       //Magic-Number option?
00543       else if(option->type == LCP_OPTION_MAGIC_NUMBER)
00544       {
00545          //The option is not recognized by the peer
00546          context->localConfig.magicNumberRejected = TRUE;
00547          //Restore default value
00548          context->localConfig.magicNumber = PPP_DEFAULT_MAGIC_NUMBER;
00549       }
00550       //Protocol-Field-Compression option?
00551       else if(option->type == LCP_OPTION_PFC)
00552       {
00553          //The option is not recognized by the peer
00554          context->localConfig.pfcRejected = TRUE;
00555          //Restore default value
00556          context->localConfig.pfc = FALSE;
00557       }
00558       //Address-and-Control-Field-Compression option?
00559       else if(option->type == LCP_OPTION_ACFC)
00560       {
00561          //The option is not recognized by the peer
00562          context->localConfig.acfcRejected = TRUE;
00563          //Restore default value
00564          context->localConfig.acfc = FALSE;
00565       }
00566 
00567       //Remaining bytes to process
00568       length -= option->length;
00569       //Jump to the next option
00570       option = (PppOption *) ((uint8_t *) option + option->length);
00571    }
00572 
00573    //A valid Configure-Nak or Configure-Reject packet has been received from the peer
00574    pppRcvConfigureNakEvent(context, &context->lcpFsm, &lcpCallbacks);
00575 
00576    //Successful processing
00577    return NO_ERROR;
00578 }
00579 
00580 
00581 /**
00582  * @brief Process Terminate-Request packet
00583  * @param[in] context PPP context
00584  * @param[in] terminateReqPacket Packet received from the peer
00585  * @return Error code
00586  **/
00587 
00588 error_t lcpProcessTerminateReq(PppContext *context,
00589    const PppTerminatePacket *terminateReqPacket)
00590 {
00591    //Debug message
00592    TRACE_INFO("\r\nLCP Receive-Terminate-Request event\r\n");
00593 
00594    //The Terminate-Request indicates the desire of the peer to close the connection
00595    pppRcvTerminateReqEvent(context, &context->lcpFsm,
00596       &lcpCallbacks, terminateReqPacket);
00597 
00598    //Successful processing
00599    return NO_ERROR;
00600 }
00601 
00602 
00603 /**
00604  * @brief Process Terminate-Ack packet
00605  * @param[in] context PPP context
00606  * @param[in] terminateAckPacket Packet received from the peer
00607  * @return Error code
00608  **/
00609 
00610 error_t lcpProcessTerminateAck(PppContext *context,
00611    const PppTerminatePacket *terminateAckPacket)
00612 {
00613    //Debug message
00614    TRACE_INFO("\r\nLCP Receive-Terminate-Ack event\r\n");
00615 
00616    //The Terminate-Ack packet is usually a response to a Terminate-Request
00617    //packet. This packet may also indicate that the peer is in Closed or
00618    //Stopped states, and serves to re-synchronize the link configuration
00619    pppRcvTerminateAckEvent(context, &context->lcpFsm, &lcpCallbacks);
00620 
00621    //Successful processing
00622    return NO_ERROR;
00623 }
00624 
00625 
00626 /**
00627  * @brief Process Code-Reject packet
00628  * @param[in] context PPP context
00629  * @param[in] codeRejPacket Packet received from the peer
00630  * @return Error code
00631  **/
00632 
00633 error_t lcpProcessCodeRej(PppContext *context,
00634    const PppCodeRejPacket *codeRejPacket)
00635 {
00636    size_t length;
00637    PppPacket *packet;
00638 
00639    //Debug message
00640    TRACE_INFO("\r\nLCP Receive-Code-Reject event\r\n");
00641 
00642    //Point to the rejected packet
00643    packet = (PppPacket *) codeRejPacket->rejectedPacket;
00644    //Retrieve the length of the rejected packet
00645    length = ntohs(codeRejPacket->length) - sizeof(PppCodeRejPacket);
00646 
00647    //Make sure the length of the rejected packet is valid
00648    if(length < sizeof(PppPacket))
00649       return ERROR_INVALID_LENGTH;
00650 
00651    //Check whether the rejected value is acceptable or catastrophic
00652    if(packet->code < PPP_CODE_CONFIGURE_REQ ||
00653       packet->code > PPP_CODE_DISCARD_REQ)
00654    {
00655       //The RXJ+ event arises when the rejected value is acceptable, such
00656       //as a Code-Reject of an extended code, or a Protocol-Reject of a
00657       //NCP. These are within the scope of normal operation
00658       pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
00659    }
00660    else
00661    {
00662       //The RXJ- event arises when the rejected value is catastrophic, such
00663       //as a Code-Reject of Configure-Request! This event communicates an
00664       //unrecoverable error that terminates the connection
00665       pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
00666    }
00667 
00668    //Successful processing
00669    return NO_ERROR;
00670 }
00671 
00672 
00673 /**
00674  * @brief Process Protocol-Reject packet
00675  * @param[in] context PPP context
00676  * @param[in] protocolRejPacket Packet received from the peer
00677  * @return Error code
00678  **/
00679 
00680 error_t lcpProcessProtocolRej(PppContext *context,
00681    const PppProtocolRejPacket *protocolRejPacket)
00682 {
00683    size_t length;
00684    uint16_t protocol;
00685 
00686    //Debug message
00687    TRACE_INFO("\r\nLCP Receive-Protocol-Reject event\r\n");
00688 
00689    //Retrieve the length of the packet
00690    length = ntohs(protocolRejPacket->length);
00691 
00692    //Make sure the length of the Protocol-Reject packet is valid
00693    if(length < sizeof(PppProtocolRejPacket))
00694       return ERROR_INVALID_LENGTH;
00695 
00696    //Convert the Rejected-Protocol field to host byte order
00697    protocol = ntohs(protocolRejPacket->rejectedProtocol);
00698 
00699    //Check Rejected-Protocol field value
00700    switch(protocol)
00701    {
00702    //LCP protocol?
00703    case PPP_PROTOCOL_LCP:
00704       //The rejected value is catastrophic. This event communicates
00705       //an unrecoverable error that terminates the connection
00706       pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
00707       break;
00708 
00709    //IPv4 or IPCP protocol?
00710    case PPP_PROTOCOL_IP:
00711    case PPP_PROTOCOL_IPCP:
00712       //The implementation must stop sending the offending packet type
00713       context->ipRejected = TRUE;
00714       //This is within the scope of normal operation...
00715       pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
00716       break;
00717 
00718    //IPv6 or IPV6CP protocol?
00719    case PPP_PROTOCOL_IPV6:
00720    case PPP_PROTOCOL_IPV6CP:
00721       //The implementation must stop sending the offending packet type
00722       context->ipv6Rejected = TRUE;
00723       //This is within the scope of normal operation...
00724       pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
00725       break;
00726 
00727    //Unknown protocol?
00728    default:
00729       //Just for sanity's sake...
00730       break;
00731    }
00732 
00733    //Successful processing
00734    return NO_ERROR;
00735 }
00736 
00737 
00738 /**
00739  * @brief Process Echo-Request packet
00740  * @param[in] context PPP context
00741  * @param[in] echoReqPacket Packet received from the peer
00742  * @return Error code
00743  **/
00744 
00745 error_t lcpProcessEchoReq(PppContext *context,
00746    const PppEchoPacket *echoReqPacket)
00747 {
00748    //Debug message
00749    TRACE_INFO("\r\nLCP Receive-Echo-Request event\r\n");
00750 
00751    //An Echo-Reply packet is transmitted to acknowledge the
00752    //reception of the Echo-Request packet
00753    pppRcvEchoReqEvent(context, &context->lcpFsm,
00754       &lcpCallbacks, echoReqPacket);
00755 
00756    //Successful processing
00757    return NO_ERROR;
00758 }
00759 
00760 
00761 /**
00762  * @brief Process Echo-Reply packet
00763  * @param[in] context PPP context
00764  * @param[in] echoRepPacket Packet received from the peer
00765  * @return Error code
00766  **/
00767 
00768 error_t lcpProcessEchoRep(PppContext *context,
00769    const PppEchoPacket *echoRepPacket)
00770 {
00771    //Debug message
00772    TRACE_INFO("\r\nLCP Receive-Echo-Reply event\r\n");
00773 
00774    //Successful processing
00775    return NO_ERROR;
00776 }
00777 
00778 
00779 /**
00780  * @brief Process Discard-Request packet
00781  * @param[in] context PPP context
00782  * @param[in] discardReqPacket Packet received from the peer
00783  * @return Error code
00784  **/
00785 
00786 error_t lcpProcessDiscardReq(PppContext *context,
00787    const PppDiscardReqPacket *discardReqPacket)
00788 {
00789    //Debug message
00790    TRACE_INFO("\r\nLCP Receive-Discard-Request event\r\n");
00791 
00792    //The receiver must silently discard any Discard-Request that it receives
00793    return NO_ERROR;
00794 }
00795 
00796 
00797 /**
00798  * @brief Process packet with unknown code
00799  * @param[in] context PPP context
00800  * @param[in] packet Un-interpretable packet received from the peer
00801  * @return Error code
00802  **/
00803 
00804 error_t lcpProcessUnknownCode(PppContext *context,
00805    const PppPacket *packet)
00806 {
00807    //Debug message
00808    TRACE_INFO("\r\nLCP Receive-Unknown-Code event\r\n");
00809 
00810    //This event occurs when an un-interpretable packet is received from
00811    //the peer. A Code-Reject packet is sent in response
00812    pppRcvUnknownCodeEvent(context, &context->lcpFsm, &lcpCallbacks, packet);
00813 
00814    //Successful processing
00815    return NO_ERROR;
00816 }
00817 
00818 
00819 /**
00820  * @brief Process PPP frame with unknown protocol
00821  * @param[in] context PPP context
00822  * @param[in] protocol Rejected protocol
00823  * @param[in] information Rejected information
00824  * @param[in] length Length of the rejected information
00825  * @return Error code
00826  **/
00827 
00828 error_t lcpProcessUnknownProtocol(PppContext *context,
00829    uint16_t protocol, const uint8_t *information, size_t length)
00830 {
00831    //Debug message
00832    TRACE_INFO("\r\nLCP Receive-Unknown-Protocol event\r\n");
00833 
00834    //The peer is attempting to use a protocol which is unsupported
00835    if(context->lcpFsm.state == PPP_STATE_9_OPENED)
00836    {
00837       //The Identifier field must be changed for each Protocol-Reject sent
00838       context->lcpFsm.identifier++;
00839 
00840       //If the LCP automaton is in the Opened state, then this must be
00841       //reported back to the peer by transmitting a Protocol-Reject
00842       pppSendProtocolRej(context, context->lcpFsm.identifier,
00843          protocol, information, length);
00844    }
00845 
00846    //Successful processing
00847    return NO_ERROR;
00848 }
00849 
00850 
00851 /**
00852  * @brief This-Layer-Up callback function
00853  * @param[in] context PPP context
00854  **/
00855 
00856 void lcpThisLayerUp(PppContext *context)
00857 {
00858    //Debug message
00859    TRACE_INFO("LCP This-Layer-Up callback\r\n");
00860 
00861    //Check whether the other end of the PPP link is being authenticated
00862    if(context->localConfig.authProtocol != 0)
00863       context->localAuthDone = FALSE;
00864    else
00865       context->localAuthDone = TRUE;
00866 
00867    //Check whether the other end of the PPP link is the authenticator
00868    if(context->peerConfig.authProtocol != 0)
00869       context->peerAuthDone = FALSE;
00870    else
00871       context->peerAuthDone = TRUE;
00872 
00873 #if (PAP_SUPPORT == ENABLED)
00874    //PAP authentication required?
00875    if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP ||
00876       context->peerConfig.authProtocol == PPP_PROTOCOL_PAP)
00877    {
00878       //Advance to the Authentication phase
00879       context->pppPhase = PPP_PHASE_AUTHENTICATE;
00880       //Start PAP authentication process
00881       papStartAuth(context);
00882    }
00883 #endif
00884 #if (CHAP_SUPPORT == ENABLED)
00885    //CHAP authentication required?
00886    if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP ||
00887       context->peerConfig.authProtocol == PPP_PROTOCOL_CHAP)
00888    {
00889       //Advance to the Authentication phase
00890       context->pppPhase = PPP_PHASE_AUTHENTICATE;
00891       //Start CHAP authentication process
00892       chapStartAuth(context);
00893    }
00894 #endif
00895 
00896    //Check whether PPP authentication is complete
00897    if(context->localAuthDone && context->peerAuthDone)
00898    {
00899       //Advance to the Network phase
00900       context->pppPhase = PPP_PHASE_NETWORK;
00901 
00902 #if (IPV4_SUPPORT == ENABLED)
00903       //IPCP Open event
00904       ipcpOpen(context);
00905 #endif
00906 #if (IPV6_SUPPORT == ENABLED)
00907       //IPV6CP Open event
00908       ipv6cpOpen(context);
00909 #endif
00910    }
00911 }
00912 
00913 
00914 /**
00915  * @brief This-Layer-Down callback function
00916  * @param[in] context PPP context
00917  **/
00918 
00919 void lcpThisLayerDown(PppContext *context)
00920 {
00921    //Debug message
00922    TRACE_INFO("LCP This-Layer-Down callback\r\n");
00923 
00924    //Advance to the Terminate phase
00925    context->pppPhase = PPP_PHASE_TERMINATE;
00926 
00927 #if (IPV4_SUPPORT == ENABLED)
00928    //IPCP Close event
00929    ipcpClose(context);
00930 #endif
00931 #if (IPV6_SUPPORT == ENABLED)
00932    //IPV6CP Close event
00933    ipv6cpClose(context);
00934 #endif
00935 
00936 #if (PAP_SUPPORT == ENABLED)
00937    //Abort PAP authentication process
00938    papAbortAuth(context);
00939 #endif
00940 
00941 #if (CHAP_SUPPORT == ENABLED)
00942    //Abort CHAP authentication process
00943    chapAbortAuth(context);
00944 #endif
00945 }
00946 
00947 
00948 /**
00949  * @brief This-Layer-Started callback function
00950  * @param[in] context PPP context
00951  **/
00952 
00953 void lcpThisLayerStarted(PppContext *context)
00954 {
00955    //Debug message
00956    TRACE_INFO("LCP This-Layer-Started callback\r\n");
00957 }
00958 
00959 
00960 /**
00961  * @brief This-Layer-Finished callback function
00962  * @param[in] context PPP context
00963  **/
00964 
00965 void lcpThisLayerFinished(PppContext *context)
00966 {
00967    //Debug message
00968    TRACE_INFO("LCP This-Layer-Finished callback\r\n");
00969 
00970    //The link is no longer available for traffic
00971    pppCloseEvent(context, &context->lcpFsm, &lcpCallbacks);
00972    //The lower layer is no longer ready to carry packets
00973    pppDownEvent(context, &context->lcpFsm, &lcpCallbacks);
00974 
00975    //Advance to the Link Dead phase
00976    context->pppPhase = PPP_PHASE_DEAD;
00977 }
00978 
00979 
00980 /**
00981  * @brief Initialize-Restart-Count callback function
00982  * @param[in] context PPP context
00983  * @param[in] value Restart counter value
00984  **/
00985 
00986 void lcpInitRestartCount(PppContext *context, uint_t value)
00987 {
00988    //Debug message
00989    TRACE_INFO("LCP Initialize-Restart-Count callback\r\n");
00990 
00991    //Initialize restart counter
00992    context->lcpFsm.restartCounter = value;
00993 }
00994 
00995 
00996 /**
00997  * @brief Zero-Restart-Count callback function
00998  * @param[in] context PPP context
00999  **/
01000 
01001 void lcpZeroRestartCount(PppContext *context)
01002 {
01003    //Debug message
01004    TRACE_INFO("LCP Zero-Restart-Count callback\r\n");
01005 
01006    //Zero restart counter
01007    context->lcpFsm.restartCounter = 0;
01008 
01009    //The receiver of a Terminate-Request should wait for the peer to
01010    //disconnect, and must not disconnect until at least one Restart
01011    //time has passed after sending a Terminate-Ack
01012    context->lcpFsm.timestamp = osGetSystemTime();
01013 }
01014 
01015 
01016 /**
01017  * @brief Send-Configure-Request callback function
01018  * @param[in] context PPP context
01019  * @return Error code
01020  **/
01021 
01022 error_t lcpSendConfigureReq(PppContext *context)
01023 {
01024    error_t error;
01025    size_t length;
01026    size_t offset;
01027    NetBuffer *buffer;
01028    PppConfigurePacket *configureReqPacket;
01029 
01030    //Debug message
01031    TRACE_INFO("LCP Send-Configure-Request callback\r\n");
01032 
01033    //Allocate a buffer memory to hold the Configure-Request packet
01034    buffer = pppAllocBuffer(PPP_MAX_CONF_REQ_SIZE, &offset);
01035    //Failed to allocate memory?
01036    if(buffer == NULL)
01037       return ERROR_OUT_OF_MEMORY;
01038 
01039    //Point to the Configure-Request packet
01040    configureReqPacket = netBufferAt(buffer, offset);
01041 
01042    //Format packet header
01043    configureReqPacket->code = PPP_CODE_CONFIGURE_REQ;
01044    configureReqPacket->identifier = ++context->lcpFsm.identifier;
01045    configureReqPacket->length = sizeof(PppConfigurePacket);
01046 
01047    //Make sure the Maximum-Receive-Unit option has not been
01048    //previously rejected
01049    if(!context->localConfig.mruRejected)
01050    {
01051       //Convert MRU to network byte order
01052       uint16_t value = htons(context->localConfig.mru);
01053       //Add option
01054       pppAddOption(configureReqPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t));
01055    }
01056 
01057    //Make sure the Async-Control-Character-Map option has not been
01058    //previously rejected
01059    if(!context->localConfig.accmRejected)
01060    {
01061       //Convert ACCM to network byte order
01062       uint32_t value = htonl(context->localConfig.accm);
01063       //Add option
01064       pppAddOption(configureReqPacket, LCP_OPTION_ACCM, &value, sizeof(uint32_t));
01065    }
01066 
01067    //Make sure the Authentication-Protocol option has not been
01068    //previously rejected
01069    if(!context->localConfig.authProtocolRejected)
01070    {
01071       uint8_t value[3];
01072 
01073       //PAP authentication protocol?
01074       if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP)
01075       {
01076          //Format Authentication-Protocol option
01077          value[0] = MSB(PPP_PROTOCOL_PAP);
01078          value[1] = LSB(PPP_PROTOCOL_PAP);
01079 
01080          //Add option
01081          pppAddOption(configureReqPacket, LCP_OPTION_AUTH_PROTOCOL, &value, 2);
01082       }
01083       //CHAP authentication protocol?
01084       else if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP)
01085       {
01086          //Format Authentication-Protocol option
01087          value[0] = MSB(PPP_PROTOCOL_CHAP);
01088          value[1] = LSB(PPP_PROTOCOL_CHAP);
01089          value[2] = context->localConfig.authAlgo;
01090 
01091          //Add option
01092          pppAddOption(configureReqPacket, LCP_OPTION_AUTH_PROTOCOL, &value, 3);
01093       }
01094    }
01095 
01096    //Make sure the Protocol-Field-Compression option has not been
01097    //previously rejected
01098    if(!context->localConfig.pfcRejected)
01099    {
01100       //Check whether compression of the Protocol field is supported
01101       if(context->localConfig.pfc)
01102       {
01103          //Add option
01104          pppAddOption(configureReqPacket, LCP_OPTION_PFC, NULL, 0);
01105       }
01106    }
01107 
01108    //Make sure the Address-and-Control-Field-Compression option has not been
01109    //previously rejected
01110    if(!context->localConfig.acfcRejected)
01111    {
01112       //Check whether compression of the Address and Control fields is supported
01113       if(context->localConfig.acfc)
01114       {
01115          //Add option
01116          pppAddOption(configureReqPacket, LCP_OPTION_ACFC, NULL, 0);
01117       }
01118    }
01119 
01120    //Save packet length
01121    length = configureReqPacket->length;
01122    //Convert length field to network byte order
01123    configureReqPacket->length = htons(length);
01124 
01125    //Adjust the length of the multi-part buffer
01126    netBufferSetLength(buffer, offset + length);
01127 
01128    //Debug message
01129    TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
01130    //Dump packet contents for debugging purpose
01131    pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_LCP);
01132 
01133    //Send PPP frame
01134    error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
01135 
01136    //The restart counter is decremented each time a Configure-Request is sent
01137    if(context->lcpFsm.restartCounter > 0)
01138       context->lcpFsm.restartCounter--;
01139 
01140    //Save the time at which the packet was sent
01141    context->lcpFsm.timestamp = osGetSystemTime();
01142 
01143    //Free previously allocated memory block
01144    netBufferFree(buffer);
01145    //Return status code
01146    return error;
01147 }
01148 
01149 
01150 /**
01151  * @brief Send-Configure-Ack callback function
01152  * @param[in] context PPP context
01153  * @param[in] configureReqPacket Configure-Request packet received from the peer
01154  * @return Error code
01155  **/
01156 
01157 error_t lcpSendConfigureAck(PppContext *context,
01158    const PppConfigurePacket *configureReqPacket)
01159 {
01160    //Debug message
01161    TRACE_INFO("LCP Send-Configure-Ack callback\r\n");
01162 
01163    //Send Configure-Ack packet
01164    return pppSendConfigureAckNak(context, configureReqPacket,
01165       PPP_PROTOCOL_LCP, PPP_CODE_CONFIGURE_ACK);
01166 }
01167 
01168 
01169 /**
01170  * @brief Send-Configure-Nak callback function
01171  * @param[in] context PPP context
01172  * @param[in] configureReqPacket Configure-Request packet received from the peer
01173  * @return Error code
01174  **/
01175 
01176 error_t lcpSendConfigureNak(PppContext *context,
01177    const PppConfigurePacket *configureReqPacket)
01178 {
01179    //Debug message
01180    TRACE_INFO("LCP Send-Configure-Nak callback\r\n");
01181 
01182    //Send Configure-Nak packet
01183    return pppSendConfigureAckNak(context, configureReqPacket,
01184       PPP_PROTOCOL_LCP, PPP_CODE_CONFIGURE_NAK);
01185 }
01186 
01187 
01188 /**
01189  * @brief Send-Configure-Reject callback function
01190  * @param[in] context PPP context
01191  * @param[in] configureReqPacket Configure-Request packet received from the peer
01192  * @return Error code
01193  **/
01194 
01195 error_t lcpSendConfigureRej(PppContext *context,
01196    const PppConfigurePacket *configureReqPacket)
01197 {
01198    //Debug message
01199    TRACE_INFO("LCP Send-Configure-Reject callback\r\n");
01200 
01201    //Send Configure-Reject packet
01202    return pppSendConfigureAckNak(context, configureReqPacket,
01203       PPP_PROTOCOL_LCP, PPP_CODE_CONFIGURE_REJ);
01204 }
01205 
01206 
01207 /**
01208  * @brief Send-Terminate-Request callback function
01209  * @param[in] context PPP context
01210  * @return Error code
01211  **/
01212 
01213 error_t lcpSendTerminateReq(PppContext *context)
01214 {
01215    error_t error;
01216 
01217    //Debug message
01218    TRACE_INFO("LCP Send-Terminate-Request callback\r\n");
01219 
01220    //On transmission, the Identifier field must be changed
01221    context->lcpFsm.identifier++;
01222 
01223    //Send Terminate-Request packet
01224    error = pppSendTerminateReq(context, context->lcpFsm.identifier, PPP_PROTOCOL_LCP);
01225 
01226    //The restart counter is decremented each time a Terminate-Request is sent
01227    if(context->lcpFsm.restartCounter > 0)
01228       context->lcpFsm.restartCounter--;
01229 
01230    //Save the time at which the packet was sent
01231    context->lcpFsm.timestamp = osGetSystemTime();
01232 
01233    //Return status code
01234    return error;
01235 }
01236 
01237 
01238 /**
01239  * @brief Send-Terminate-Ack callback function
01240  * @param[in] context PPP context
01241  * @param[in] terminateReqPacket Terminate-Request packet received from the peer
01242  * @return Error code
01243  **/
01244 
01245 error_t lcpSendTerminateAck(PppContext *context,
01246    const PppTerminatePacket *terminateReqPacket)
01247 {
01248    uint8_t identifier;
01249 
01250    //Debug message
01251    TRACE_INFO("LCP Send-Terminate-Ack callback\r\n");
01252 
01253    //Check whether this Terminate-Ack acknowledges the reception of a
01254    //Terminate-Request packet
01255    if(terminateReqPacket != NULL)
01256    {
01257       //The Identifier field of the Terminate-Request is copied into the
01258       //Identifier field of the Terminate-Ack packet
01259       identifier = terminateReqPacket->identifier;
01260    }
01261    else
01262    {
01263       //This Terminate-Ack packet serves to synchronize the automatons
01264       identifier = ++context->lcpFsm.identifier;
01265    }
01266 
01267    //Send Terminate-Ack packet
01268    return pppSendTerminateAck(context, identifier, PPP_PROTOCOL_LCP);
01269 }
01270 
01271 
01272 /**
01273  * @brief Send-Code-Reject callback function
01274  * @param[in] context PPP context
01275  * @param[in] packet Un-interpretable packet received from the peer
01276  * @return Error code
01277  **/
01278 
01279 error_t lcpSendCodeRej(PppContext *context, const PppPacket *packet)
01280 {
01281    //Debug message
01282    TRACE_INFO("LCP Send-Code-Reject callback\r\n");
01283 
01284    //The Identifier field must be changed for each Code-Reject sent
01285    context->lcpFsm.identifier++;
01286 
01287    //Send Code-Reject packet
01288    return pppSendCodeRej(context, packet, context->lcpFsm.identifier, PPP_PROTOCOL_LCP);
01289 }
01290 
01291 
01292 /**
01293  * @brief Send-Echo-Reply callback function
01294  * @param[in] context PPP context
01295  * @param[in] echoReqPacket Echo-Request packet received from the peer
01296  * @return Error code
01297  **/
01298 
01299 error_t lcpSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket)
01300 {
01301    //Debug message
01302    TRACE_INFO("LCP Send-Echo-Reply callback\r\n");
01303 
01304    //Send Echo-Reply packet
01305    return pppSendEchoRep(context, echoReqPacket, PPP_PROTOCOL_LCP);
01306 }
01307 
01308 
01309 /**
01310  * @brief Parse LCP configuration option
01311  * @param[in] context PPP context
01312  * @param[in] option Option to be checked
01313  * @param[in] inPacketLen Remaining bytes to process in the incoming packet
01314  * @param[out] outPacket Pointer to the Configure-Ack, Nak or Reject packet
01315  * @return Error code
01316  **/
01317 
01318 error_t lcpParseOption(PppContext *context, PppOption *option,
01319    size_t inPacketLen, PppConfigurePacket *outPacket)
01320 {
01321    error_t error;
01322 
01323    //Malformed LCP packet?
01324    if(inPacketLen < sizeof(PppOption))
01325       return ERROR_INVALID_LENGTH;
01326 
01327    //Check option length
01328    if(option->length < sizeof(PppOption))
01329       return ERROR_INVALID_LENGTH;
01330    if(option->length > inPacketLen)
01331       return ERROR_INVALID_LENGTH;
01332 
01333    //Check option type
01334    switch(option->type)
01335    {
01336    case LCP_OPTION_MRU:
01337       //Check Maximum-Receive-Unit option
01338       error = lcpParseMruOption(context, (LcpMruOption *) option, outPacket);
01339       break;
01340    case LCP_OPTION_ACCM:
01341       //Check Async-Control-Character-Map option
01342       error = lcpParseAccmOption(context, (LcpAccmOption *) option, outPacket);
01343       break;
01344    case LCP_OPTION_AUTH_PROTOCOL:
01345       //Check Authentication-Protocol option
01346       error = lcpParseAuthProtocolOption(context, (LcpAuthProtocolOption *) option, outPacket);
01347       break;
01348    case LCP_OPTION_MAGIC_NUMBER:
01349       //Check Magic-Number option
01350       error = lcpParseMagicNumberOption(context, (LcpMagicNumberOption *) option, outPacket);
01351       break;
01352    case LCP_OPTION_PFC:
01353       //Check Protocol-Field-Compression option
01354       error = lcpParsePfcOption(context, (LcpPfcOption *) option, outPacket);
01355       break;
01356    case LCP_OPTION_ACFC:
01357       //Check Address-and-Control-Field-Compression option
01358       error = lcpParseAcfcOption(context, (LcpAcfcOption *) option, outPacket);
01359       break;
01360    default:
01361       //If some configuration options received in the Configure-Request are not
01362       //recognizable or not acceptable for negotiation, then the implementation
01363       //must transmit a Configure-Reject
01364       if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_REJ)
01365       {
01366          //The options field of the Configure-Reject packet is filled
01367          //with the unrecognized options from the Configure-Request
01368          pppAddOption(outPacket, option->type, option->data,
01369             option->length - sizeof(PppOption));
01370       }
01371 
01372       //The option is not acceptable for negotiation
01373       error = ERROR_INVALID_TYPE;
01374       break;
01375    }
01376 
01377    //Return status code
01378    return error;
01379 }
01380 
01381 
01382 /**
01383  * @brief Parse Maximum-Receive-Unit option
01384  * @param[in] context PPP context
01385  * @param[in] option Option to be checked
01386  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01387  * @return Error code
01388  **/
01389 
01390 error_t lcpParseMruOption(PppContext *context,
01391    LcpMruOption *option, PppConfigurePacket *outPacket)
01392 {
01393    error_t error;
01394    uint16_t value;
01395 
01396    //Check length field
01397    if(option->length == sizeof(LcpMruOption))
01398    {
01399       //Check whether the option value is acceptable
01400       if(ntohs(option->mru) >= PPP_MIN_MRU)
01401       {
01402          //If every configuration option received in the Configure-Request is
01403          //recognizable and all values are acceptable, then the implementation
01404          //must transmit a Configure-Ack
01405          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01406          {
01407             //Save Maximum-Receive-Unit option
01408             context->peerConfig.mru = ntohl(option->mru);
01409 
01410             //The options field of the Configure-Ack packet contains the
01411             //configuration options that the sender is acknowledging
01412             pppAddOption(outPacket, LCP_OPTION_MRU, (void *) &option->mru,
01413                option->length - sizeof(PppOption));
01414          }
01415 
01416          //The value is acceptable
01417          error = NO_ERROR;
01418       }
01419       else
01420       {
01421          //If all configuration options are recognizable, but some values are not
01422          //acceptable, then the implementation must transmit a Configure-Nak
01423          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
01424          {
01425             //Use default value
01426             value = htons(PPP_DEFAULT_MRU);
01427 
01428             //The option must be modified to a value acceptable to the
01429             //Configure-Nak sender
01430             pppAddOption(outPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t));
01431          }
01432 
01433          //The value is not acceptable
01434          error = ERROR_INVALID_VALUE;
01435       }
01436    }
01437    else
01438    {
01439       //Invalid length field
01440       error = ERROR_INVALID_LENGTH;
01441    }
01442 
01443    //Return status code
01444    return error;
01445 }
01446 
01447 
01448 /**
01449  * @brief Parse Async-Control-Character-Map option
01450  * @param[in] context PPP context
01451  * @param[in] option Option to be checked
01452  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01453  * @return Error code
01454  **/
01455 
01456 error_t lcpParseAccmOption(PppContext *context,
01457    LcpAccmOption *option, PppConfigurePacket *outPacket)
01458 {
01459    error_t error;
01460 
01461    //Check length field
01462    if(option->length == sizeof(LcpAccmOption))
01463    {
01464       //If every configuration option received in the Configure-Request is
01465       //recognizable and all values are acceptable, then the implementation
01466       //must transmit a Configure-Ack
01467       if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01468       {
01469          //Save Async-Control-Character-Map option
01470          context->peerConfig.accm = ntohl(option->accm);
01471 
01472          //The options field of the Configure-Ack packet contains the
01473          //configuration options that the sender is acknowledging
01474          pppAddOption(outPacket, LCP_OPTION_ACCM, (void *) &option->accm,
01475             option->length - sizeof(PppOption));
01476       }
01477 
01478       //The value is acceptable
01479       error = NO_ERROR;
01480    }
01481    else
01482    {
01483       //Invalid length field
01484       error = ERROR_INVALID_LENGTH;
01485    }
01486 
01487    //Return status code
01488    return error;
01489 }
01490 
01491 
01492 /**
01493  * @brief Parse Authentication-Protocol option
01494  * @param[in] context PPP context
01495  * @param[in] option Option to be checked
01496  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01497  * @return Error code
01498  **/
01499 
01500 error_t lcpParseAuthProtocolOption(PppContext *context,
01501    LcpAuthProtocolOption *option, PppConfigurePacket *outPacket)
01502 {
01503    error_t error;
01504    uint8_t value[3];
01505 
01506    //Assume an error condition...
01507    error = ERROR_INVALID_LENGTH;
01508 
01509    //Check the length of the option
01510    if(option->length >= sizeof(LcpAuthProtocolOption))
01511    {
01512       //The Authentication-Protocol option for PAP must be exactly 4 bytes
01513       if(ntohs(option->protocol) == PPP_PROTOCOL_PAP)
01514       {
01515          if(option->length == 4)
01516             error = NO_ERROR;
01517       }
01518       //The Authentication-Protocol option for CHAP must be exactly 5 bytes
01519       else if(ntohs(option->protocol) == PPP_PROTOCOL_CHAP)
01520       {
01521          if(option->length == 5)
01522             error = NO_ERROR;
01523       }
01524    }
01525 
01526    //Make sure the length field is valid
01527    if(!error)
01528    {
01529       //PAP authentication protocol?
01530       if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP &&
01531          ntohs(option->protocol) == PPP_PROTOCOL_PAP)
01532       {
01533          //If every configuration option received in the Configure-Request is
01534          //recognizable and all values are acceptable, then the implementation
01535          //must transmit a Configure-Ack
01536          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01537          {
01538             //Save the authentication protocol to be used
01539             context->peerConfig.authProtocol = PPP_PROTOCOL_PAP;
01540 
01541             //The options field of the Configure-Ack packet contains the
01542             //configuration options that the sender is acknowledging
01543             pppAddOption(outPacket, option->type, (void *) &option->protocol,
01544                option->length - sizeof(PppOption));
01545          }
01546 
01547          //The value is acceptable
01548          error = NO_ERROR;
01549       }
01550       //CHAP with MD5 authentication protocol?
01551       else if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5 &&
01552          ntohs(option->protocol) == PPP_PROTOCOL_CHAP &&
01553          option->data[0] == CHAP_ALGO_ID_CHAP_MD5)
01554       {
01555          //If every configuration option received in the Configure-Request is
01556          //recognizable and all values are acceptable, then the implementation
01557          //must transmit a Configure-Ack
01558          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01559          {
01560             //Save the authentication protocol to be used
01561             context->peerConfig.authProtocol = PPP_PROTOCOL_CHAP;
01562             context->peerConfig.authAlgo = CHAP_ALGO_ID_CHAP_MD5;
01563 
01564             //The options field of the Configure-Ack packet contains the
01565             //configuration options that the sender is acknowledging
01566             pppAddOption(outPacket, option->type, (void *) &option->protocol,
01567                option->length - sizeof(PppOption));
01568          }
01569 
01570          //The value is acceptable
01571          error = NO_ERROR;
01572       }
01573       else
01574       {
01575          //PAP authentication protocol allowed?
01576          if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP)
01577          {
01578             //If all configuration options are recognizable, but some values are not
01579             //acceptable, then the implementation must transmit a Configure-Nak
01580             if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
01581             {
01582                //Format Authentication-Protocol option
01583                value[0] = MSB(PPP_PROTOCOL_PAP);
01584                value[1] = LSB(PPP_PROTOCOL_PAP);
01585 
01586                //The option must be modified to a value acceptable to the
01587                //Configure-Nak sender
01588                pppAddOption(outPacket, LCP_OPTION_AUTH_PROTOCOL, value, 2);
01589             }
01590 
01591             //The value is not acceptable
01592             error = ERROR_INVALID_VALUE;
01593          }
01594          //CHAP with MD5 authentication protocol allowed?
01595          else if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5)
01596          {
01597             //If all configuration options are recognizable, but some values are not
01598             //acceptable, then the implementation must transmit a Configure-Nak
01599             if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
01600             {
01601                //Format Authentication-Protocol option
01602                value[0] = MSB(PPP_PROTOCOL_CHAP);
01603                value[1] = LSB(PPP_PROTOCOL_CHAP);
01604                value[2] = CHAP_ALGO_ID_CHAP_MD5;
01605 
01606                //The option must be modified to a value acceptable to the
01607                //Configure-Nak sender
01608                pppAddOption(outPacket, LCP_OPTION_AUTH_PROTOCOL, value, 3);
01609             }
01610 
01611             //The value is not acceptable
01612             error = ERROR_INVALID_VALUE;
01613          }
01614          else
01615          {
01616             //If some configuration options received in the Configure-Request are not
01617             //recognizable or not acceptable for negotiation, then the implementation
01618             //must transmit a Configure-Reject
01619             if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_REJ)
01620             {
01621                //The options field of the Configure-Reject packet is filled
01622                //with the unrecognized options from the Configure-Request
01623                pppAddOption(outPacket, option->type, (void *) &option->protocol,
01624                   option->length - sizeof(PppOption));
01625             }
01626 
01627             //The option is not acceptable for negotiation
01628             error = ERROR_INVALID_TYPE;
01629          }
01630       }
01631    }
01632 
01633    //Return status code
01634    return error;
01635 }
01636 
01637 
01638 /**
01639  * @brief Parse Magic-Number option
01640  * @param[in] context PPP context
01641  * @param[in] option Option to be checked
01642  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01643  * @return Error code
01644  **/
01645 
01646 error_t lcpParseMagicNumberOption(PppContext *context,
01647    LcpMagicNumberOption *option, PppConfigurePacket *outPacket)
01648 {
01649    error_t error;
01650 
01651    //Check length field
01652    if(option->length == sizeof(LcpMagicNumberOption))
01653    {
01654       //If every configuration option received in the Configure-Request is
01655       //recognizable and all values are acceptable, then the implementation
01656       //must transmit a Configure-Ack
01657       if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01658       {
01659          //Save Magic-Number option
01660          context->peerConfig.magicNumber = ntohl(option->magicNumber);
01661 
01662          //The options field of the Configure-Ack packet contains the
01663          //configuration options that the sender is acknowledging
01664          pppAddOption(outPacket, LCP_OPTION_MAGIC_NUMBER, (void *) &option->magicNumber,
01665             option->length - sizeof(PppOption));
01666       }
01667 
01668       //The value is acceptable
01669       error = NO_ERROR;
01670    }
01671    else
01672    {
01673       //Invalid length field
01674       error = ERROR_INVALID_LENGTH;
01675    }
01676 
01677    //Return status code
01678    return error;
01679 }
01680 
01681 
01682 /**
01683  * @brief Parse Protocol-Field-Compression option
01684  * @param[in] context PPP context
01685  * @param[in] option Option to be checked
01686  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01687  * @return Error code
01688  **/
01689 
01690 error_t lcpParsePfcOption(PppContext *context,
01691    LcpPfcOption *option, PppConfigurePacket *outPacket)
01692 {
01693    error_t error;
01694 
01695    //Check length field
01696    if(option->length == sizeof(LcpPfcOption))
01697    {
01698       //If every configuration option received in the Configure-Request is
01699       //recognizable and all values are acceptable, then the implementation
01700       //must transmit a Configure-Ack
01701       if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01702       {
01703          //Save Protocol-Field-Compression option
01704          context->peerConfig.pfc = TRUE;
01705 
01706          //The options field of the Configure-Ack packet contains the
01707          //configuration options that the sender is acknowledging
01708          pppAddOption(outPacket, LCP_OPTION_PFC, NULL, 0);
01709       }
01710 
01711       //The value is acceptable
01712       error = NO_ERROR;
01713    }
01714    else
01715    {
01716       //Invalid length field
01717       error = ERROR_INVALID_LENGTH;
01718    }
01719 
01720    //Return status code
01721    return error;
01722 }
01723 
01724 
01725 /**
01726  * @brief Parse Address-and-Control-Field-Compression option
01727  * @param[in] context PPP context
01728  * @param[in] option Option to be checked
01729  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01730  * @return Error code
01731  **/
01732 
01733 error_t lcpParseAcfcOption(PppContext *context,
01734    LcpAcfcOption *option, PppConfigurePacket *outPacket)
01735 {
01736    error_t error;
01737 
01738    //Check length field
01739    if(option->length == sizeof(LcpAcfcOption))
01740    {
01741       //If every configuration option received in the Configure-Request is
01742       //recognizable and all values are acceptable, then the implementation
01743       //must transmit a Configure-Ack
01744       if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01745       {
01746          //Save Address-and-Control-Field-Compression option
01747          context->peerConfig.acfc = TRUE;
01748 
01749          //The options field of the Configure-Ack packet contains the
01750          //configuration options that the sender is acknowledging
01751          pppAddOption(outPacket, LCP_OPTION_ACFC, NULL, 0);
01752       }
01753 
01754       //The value is acceptable
01755       error = NO_ERROR;
01756    }
01757    else
01758    {
01759       //Invalid length field
01760       error = ERROR_INVALID_LENGTH;
01761    }
01762 
01763    //Return status code
01764    return error;
01765 }
01766 
01767 #endif
01768