Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:10:14 by
