Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lcp.c
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
Generated on Tue Jul 12 2022 17:10:14 by
1.7.2