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.
ipcp.c
00001 /** 00002 * @file ipcp.c 00003 * @brief IPCP (PPP Internet Protocol 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 "ipv4/ipv4.h" 00035 #include "ppp/ppp_fsm.h" 00036 #include "ppp/ppp_misc.h" 00037 #include "ppp/ppp_debug.h" 00038 #include "ppp/ipcp.h" 00039 #include "debug.h" 00040 00041 //Check TCP/IP stack configuration 00042 #if (PPP_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) 00043 00044 00045 /** 00046 * @brief IPCP FSM callbacks 00047 **/ 00048 00049 const PppCallbacks ipcpCallbacks = 00050 { 00051 ipcpThisLayerUp, 00052 ipcpThisLayerDown, 00053 ipcpThisLayerStarted, 00054 ipcpThisLayerFinished, 00055 ipcpInitRestartCount, 00056 ipcpZeroRestartCount, 00057 ipcpSendConfigureReq, 00058 ipcpSendConfigureAck, 00059 ipcpSendConfigureNak, 00060 ipcpSendConfigureRej, 00061 ipcpSendTerminateReq, 00062 ipcpSendTerminateAck, 00063 ipcpSendCodeRej, 00064 NULL 00065 }; 00066 00067 00068 /** 00069 * @brief IPCP Open event 00070 * @param[in] context PPP context 00071 * @return Error code 00072 **/ 00073 00074 error_t ipcpOpen(PppContext *context) 00075 { 00076 //Debug message 00077 TRACE_INFO("\r\nIPCP Open event\r\n"); 00078 00079 //The link is administratively available for traffic 00080 pppOpenEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00081 //The lower layer is ready to carry packets 00082 pppUpEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00083 00084 //Successful processing 00085 return NO_ERROR; 00086 } 00087 00088 00089 /** 00090 * @brief IPCP Close event 00091 * @param[in] context PPP context 00092 * @return Error code 00093 **/ 00094 00095 error_t ipcpClose(PppContext *context) 00096 { 00097 //Debug message 00098 TRACE_INFO("\r\nIPCP Close event\r\n"); 00099 00100 //The lower layer is no longer ready to carry packets 00101 pppDownEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00102 //The link is no longer available for traffic 00103 pppCloseEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00104 00105 //Successful processing 00106 return NO_ERROR; 00107 } 00108 00109 00110 /** 00111 * @brief IPCP timer handler 00112 * 00113 * This routine must be periodically called by the TCP/IP stack to 00114 * manage retransmissions 00115 * 00116 * @param[in] context PPP context 00117 **/ 00118 00119 void ipcpTick(PppContext *context) 00120 { 00121 //Check whether the restart timer is running 00122 if(context->ipcpFsm.state >= PPP_STATE_4_CLOSING && 00123 context->ipcpFsm.state <= PPP_STATE_8_ACK_SENT) 00124 { 00125 //Get current time 00126 systime_t time = osGetSystemTime(); 00127 00128 //Check restart timer 00129 if((time - context->ipcpFsm.timestamp) >= PPP_RESTART_TIMER) 00130 { 00131 //Debug message 00132 TRACE_INFO("\r\nIPCP Timeout event\r\n"); 00133 00134 //The restart timer is used to retransmit Configure-Request 00135 //and Terminate-Request packets 00136 pppTimeoutEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00137 } 00138 } 00139 } 00140 00141 00142 /** 00143 * @brief Process an incoming IPCP packet 00144 * @param[in] context PPP context 00145 * @param[in] packet IPCP packet received from the peer 00146 * @param[in] length Length of the packet, in bytes 00147 **/ 00148 00149 void ipcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length) 00150 { 00151 //Ensure the length of the incoming IPCP packet is valid 00152 if(length < sizeof(PppPacket)) 00153 return; 00154 00155 //Check the length field 00156 if(ntohs(packet->length) > length) 00157 return; 00158 if(ntohs(packet->length) < sizeof(PppPacket)) 00159 return; 00160 00161 //Save the length of the IPCP packet 00162 length = ntohs(packet->length); 00163 00164 //Debug message 00165 TRACE_INFO("IPCP packet received (%" PRIuSIZE " bytes)...\r\n", length); 00166 //Dump IPCP packet contents for debugging purpose 00167 pppDumpPacket(packet, length, PPP_PROTOCOL_IPCP); 00168 00169 //Check IPCP code field 00170 switch(packet->code) 00171 { 00172 //Configure-Request packet? 00173 case PPP_CODE_CONFIGURE_REQ: 00174 //Process Configure-Request packet 00175 ipcpProcessConfigureReq(context, (PppConfigurePacket *) packet); 00176 break; 00177 //Configure-Ack packet? 00178 case PPP_CODE_CONFIGURE_ACK: 00179 //Process Configure-Ack packet 00180 ipcpProcessConfigureAck(context, (PppConfigurePacket *) packet); 00181 break; 00182 //Configure-Nak packet? 00183 case PPP_CODE_CONFIGURE_NAK: 00184 //Process Configure-Nak packet 00185 ipcpProcessConfigureNak(context, (PppConfigurePacket *) packet); 00186 break; 00187 //Configure-Reject packet? 00188 case PPP_CODE_CONFIGURE_REJ: 00189 //Process Configure-Reject packet 00190 ipcpProcessConfigureReject(context, (PppConfigurePacket *) packet); 00191 break; 00192 //Terminate-Request packet? 00193 case PPP_CODE_TERMINATE_REQ: 00194 //Process Terminate-Request packet 00195 ipcpProcessTerminateReq(context, (PppTerminatePacket *) packet); 00196 break; 00197 //Terminate-Ack packet? 00198 case PPP_CODE_TERMINATE_ACK: 00199 //Process Terminate-Ack packet 00200 ipcpProcessTerminateAck(context, (PppTerminatePacket *) packet); 00201 break; 00202 //Code-Reject packet? 00203 case PPP_CODE_CODE_REJ: 00204 //Process Code-Reject packet 00205 ipcpProcessCodeRej(context, (PppCodeRejPacket *) packet); 00206 break; 00207 //Unknown code field 00208 default: 00209 //The packet is un-interpretable 00210 ipcpProcessUnknownCode(context, packet); 00211 break; 00212 } 00213 } 00214 00215 00216 /** 00217 * @brief Process Configure-Request packet 00218 * @param[in] context PPP context 00219 * @param[in] configureReqPacket Packet received from the peer 00220 * @return Error code 00221 **/ 00222 00223 error_t ipcpProcessConfigureReq(PppContext *context, 00224 const PppConfigurePacket *configureReqPacket) 00225 { 00226 error_t error; 00227 size_t length; 00228 bool_t notRecognizable; 00229 bool_t notAcceptable; 00230 PppOption *option; 00231 00232 //Debug message 00233 TRACE_INFO("\r\nIPCP Receive-Configure-Request event\r\n"); 00234 00235 //Initialize variables 00236 error = NO_ERROR; 00237 notRecognizable = FALSE; 00238 notAcceptable = FALSE; 00239 00240 //Retrieve the length of the option list 00241 length = ntohs(configureReqPacket->length) - sizeof(PppConfigurePacket); 00242 //Point to the first option 00243 option = (PppOption *) configureReqPacket->options; 00244 00245 //Parse configuration options 00246 while(length > 0) 00247 { 00248 //Parse current option 00249 error = ipcpParseOption(context, option, length, NULL); 00250 00251 //Any error to report? 00252 if(error == ERROR_INVALID_TYPE) 00253 { 00254 //Option not recognizable 00255 notRecognizable = TRUE; 00256 //Catch error 00257 error = NO_ERROR; 00258 } 00259 else if(error == ERROR_INVALID_VALUE) 00260 { 00261 //Option not acceptable for configuration 00262 notAcceptable = TRUE; 00263 //Catch error 00264 error = NO_ERROR; 00265 } 00266 else if(error) 00267 { 00268 //Malformed Configure-Request packet 00269 break; 00270 } 00271 00272 //Remaining bytes to process 00273 length -= option->length; 00274 //Jump to the next option 00275 option = (PppOption *) ((uint8_t *) option + option->length); 00276 } 00277 00278 //Valid Configure-Request packet received from the peer? 00279 if(!error) 00280 { 00281 //Check flags 00282 if(notRecognizable) 00283 { 00284 //If some configuration options received in the Configure-Request are not 00285 //recognizable or not acceptable for negotiation, then the implementation 00286 //must transmit a Configure-Reject 00287 pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks, 00288 configureReqPacket, PPP_CODE_CONFIGURE_REJ); 00289 } 00290 else if(notAcceptable) 00291 { 00292 //If all configuration options are recognizable, but some values are not 00293 //acceptable, then the implementation must transmit a Configure-Nak 00294 pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks, 00295 configureReqPacket, PPP_CODE_CONFIGURE_NAK); 00296 } 00297 else 00298 { 00299 //If every configuration option received in the Configure-Request is 00300 //recognizable and all values are acceptable, then the implementation 00301 //must transmit a Configure-Ack 00302 pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks, 00303 configureReqPacket, PPP_CODE_CONFIGURE_ACK); 00304 } 00305 } 00306 00307 //Return status code 00308 return error; 00309 } 00310 00311 00312 /** 00313 * @brief Process Configure-Ack packet 00314 * @param[in] context PPP context 00315 * @param[in] configureAckPacket Packet received from the peer 00316 * @return Error code 00317 **/ 00318 00319 error_t ipcpProcessConfigureAck(PppContext *context, 00320 const PppConfigurePacket *configureAckPacket) 00321 { 00322 //Debug message 00323 TRACE_INFO("\r\nIPCP Receive-Configure-Ack event\r\n"); 00324 00325 //When a packet is received with an invalid Identifier field, the 00326 //packet is silently discarded without affecting the automaton 00327 if(configureAckPacket->identifier != context->ipcpFsm.identifier) 00328 return ERROR_WRONG_IDENTIFIER; 00329 00330 //A valid Configure-Ack packet has been received from the peer 00331 pppRcvConfigureAckEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00332 00333 //Successful processing 00334 return NO_ERROR; 00335 } 00336 00337 00338 /** 00339 * @brief Process Configure-Nak packet 00340 * @param[in] context PPP context 00341 * @param[in] configureNakPacket Packet received from the peer 00342 * @return Error code 00343 **/ 00344 00345 error_t ipcpProcessConfigureNak(PppContext *context, 00346 const PppConfigurePacket *configureNakPacket) 00347 { 00348 size_t length; 00349 PppOption *option; 00350 00351 //Debug message 00352 TRACE_INFO("IPCP Receive-Configure-Nak event\r\n"); 00353 00354 //When a packet is received with an invalid Identifier field, the 00355 //packet is silently discarded without affecting the automaton 00356 if(configureNakPacket->identifier != context->ipcpFsm.identifier) 00357 return ERROR_WRONG_IDENTIFIER; 00358 00359 //Retrieve the length of the option list 00360 length = ntohs(configureNakPacket->length) - sizeof(PppConfigurePacket); 00361 //Point to the first option 00362 option = (PppOption *) configureNakPacket->options; 00363 00364 //Parse configuration options 00365 while(length > 0) 00366 { 00367 //Check option length 00368 if(option->length < sizeof(PppOption)) 00369 return ERROR_INVALID_LENGTH; 00370 if(option->length > length) 00371 return ERROR_INVALID_LENGTH; 00372 00373 //IP-Address option? 00374 if(option->type == IPCP_OPTION_IP_ADDRESS) 00375 { 00376 //Cast option 00377 IpcpIpAddressOption *ipAddressOption = (IpcpIpAddressOption *) option; 00378 00379 //Check option length 00380 if(ipAddressOption->length != sizeof(IpcpIpAddressOption)) 00381 return ERROR_INVALID_LENGTH; 00382 00383 //Save IP address 00384 context->localConfig.ipAddr = ipAddressOption->ipAddr; 00385 } 00386 //Primary-DNS-Server-Address option? 00387 else if(option->type == IPCP_OPTION_PRIMARY_DNS) 00388 { 00389 //Cast option 00390 IpcpPrimaryDnsOption *primaryDns = (IpcpPrimaryDnsOption *) option; 00391 00392 //Check option length 00393 if(primaryDns->length != sizeof(IpcpPrimaryDnsOption)) 00394 return ERROR_INVALID_LENGTH; 00395 00396 //Save primary DNS server address 00397 context->localConfig.primaryDns = primaryDns->ipAddr; 00398 } 00399 //Secondary-DNS-Server-Address option? 00400 else if(option->type == IPCP_OPTION_SECONDARY_DNS) 00401 { 00402 //Cast option 00403 IpcpSecondaryDnsOption *secondaryDns = (IpcpSecondaryDnsOption *) option; 00404 00405 //Check option length 00406 if(secondaryDns->length != sizeof(IpcpSecondaryDnsOption)) 00407 return ERROR_INVALID_LENGTH; 00408 00409 //Save secondary DNS server address 00410 context->localConfig.secondaryDns = secondaryDns->ipAddr; 00411 } 00412 00413 //Remaining bytes to process 00414 length -= option->length; 00415 //Jump to the next option 00416 option = (PppOption *) ((uint8_t *) option + option->length); 00417 } 00418 00419 //A valid Configure-Nak or Configure-Reject packet has been received from the peer 00420 pppRcvConfigureNakEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00421 00422 //Successful processing 00423 return NO_ERROR; 00424 } 00425 00426 00427 /** 00428 * @brief Process Configure-Reject packet 00429 * @param[in] context PPP context 00430 * @param[in] configureRejPacket Packet received from the peer 00431 * @return Error code 00432 **/ 00433 00434 error_t ipcpProcessConfigureReject(PppContext *context, 00435 const PppConfigurePacket *configureRejPacket) 00436 { 00437 size_t length; 00438 PppOption *option; 00439 00440 //Debug message 00441 TRACE_INFO("\r\nIPCP Receive-Configure-Reject event\r\n"); 00442 00443 //When a packet is received with an invalid Identifier field, the 00444 //packet is silently discarded without affecting the automaton 00445 if(configureRejPacket->identifier != context->ipcpFsm.identifier) 00446 return ERROR_WRONG_IDENTIFIER; 00447 00448 //Retrieve the length of the option list 00449 length = ntohs(configureRejPacket->length) - sizeof(PppConfigurePacket); 00450 //Point to the first option 00451 option = (PppOption *) configureRejPacket->options; 00452 00453 //Parse configuration options 00454 while(length > 0) 00455 { 00456 //Check option length 00457 if(option->length < sizeof(PppOption)) 00458 return ERROR_INVALID_LENGTH; 00459 if(option->length > length) 00460 return ERROR_INVALID_LENGTH; 00461 00462 //IP-Address option? 00463 if(option->type == IPCP_OPTION_IP_ADDRESS) 00464 { 00465 //The option is not recognized by the peer 00466 context->localConfig.ipAddrRejected = TRUE; 00467 } 00468 //Primary-DNS-Server-Address option? 00469 else if(option->type == IPCP_OPTION_PRIMARY_DNS) 00470 { 00471 //The option is not recognized by the peer 00472 context->localConfig.primaryDnsRejected = TRUE; 00473 } 00474 //Secondary-DNS-Server-Address option? 00475 else if(option->type == IPCP_OPTION_SECONDARY_DNS) 00476 { 00477 //The option is not recognized by the peer 00478 context->localConfig.secondaryDnsRejected = TRUE; 00479 } 00480 00481 //Remaining bytes to process 00482 length -= option->length; 00483 //Jump to the next option 00484 option = (PppOption *) ((uint8_t *) option + option->length); 00485 } 00486 00487 //A valid Configure-Nak or Configure-Reject packet has been received from the peer 00488 pppRcvConfigureNakEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00489 00490 //Successful processing 00491 return NO_ERROR; 00492 } 00493 00494 00495 /** 00496 * @brief Process Terminate-Request packet 00497 * @param[in] context PPP context 00498 * @param[in] terminateReqPacket Packet received from the peer 00499 * @return Error code 00500 **/ 00501 00502 error_t ipcpProcessTerminateReq(PppContext *context, 00503 const PppTerminatePacket *terminateReqPacket) 00504 { 00505 //Debug message 00506 TRACE_INFO("\r\nIPCP Receive-Terminate-Request event\r\n"); 00507 00508 //The Terminate-Request indicates the desire of the peer to close the connection 00509 pppRcvTerminateReqEvent(context, &context->ipcpFsm, 00510 &ipcpCallbacks, terminateReqPacket); 00511 00512 //Successful processing 00513 return NO_ERROR; 00514 } 00515 00516 00517 /** 00518 * @brief Process Terminate-Ack packet 00519 * @param[in] context PPP context 00520 * @param[in] terminateAckPacket Packet received from the peer 00521 * @return Error code 00522 **/ 00523 00524 error_t ipcpProcessTerminateAck(PppContext *context, 00525 const PppTerminatePacket *terminateAckPacket) 00526 { 00527 //Debug message 00528 TRACE_INFO("\r\nIPCP Receive-Terminate-Ack event\r\n"); 00529 00530 //The Terminate-Ack packet is usually a response to a Terminate-Request 00531 //packet. This packet may also indicate that the peer is in Closed or 00532 //Stopped states, and serves to re-synchronize the link configuration 00533 pppRcvTerminateAckEvent(context, &context->ipcpFsm, &ipcpCallbacks); 00534 00535 //Successful processing 00536 return NO_ERROR; 00537 } 00538 00539 00540 /** 00541 * @brief Process Code-Reject packet 00542 * @param[in] context PPP context 00543 * @param[in] codeRejPacket Packet received from the peer 00544 * @return Error code 00545 **/ 00546 00547 error_t ipcpProcessCodeRej(PppContext *context, 00548 const PppCodeRejPacket *codeRejPacket) 00549 { 00550 size_t length; 00551 PppPacket *packet; 00552 00553 //Debug message 00554 TRACE_INFO("\r\nIPCP Receive-Code-Reject event\r\n"); 00555 00556 //Point to the rejected packet 00557 packet = (PppPacket *) codeRejPacket->rejectedPacket; 00558 //Retrieve the length of the rejected packet 00559 length = ntohs(codeRejPacket->length) - sizeof(PppCodeRejPacket); 00560 00561 //Make sure the length of the rejected packet is valid 00562 if(length < sizeof(PppPacket)) 00563 return ERROR_INVALID_LENGTH; 00564 00565 //Check whether the rejected value is acceptable or catastrophic 00566 if(packet->code < PPP_CODE_CONFIGURE_REQ || 00567 packet->code > PPP_CODE_CODE_REJ) 00568 { 00569 //The RXJ+ event arises when the rejected value is acceptable, such 00570 //as a Code-Reject of an extended code, or a Protocol-Reject of a 00571 //NCP. These are within the scope of normal operation 00572 pppRcvCodeRejEvent(context, &context->ipcpFsm, &ipcpCallbacks, TRUE); 00573 } 00574 else 00575 { 00576 //The RXJ- event arises when the rejected value is catastrophic, such 00577 //as a Code-Reject of Configure-Request! This event communicates an 00578 //unrecoverable error that terminates the connection 00579 pppRcvCodeRejEvent(context, &context->ipcpFsm, &ipcpCallbacks, FALSE); 00580 } 00581 00582 //Successful processing 00583 return NO_ERROR; 00584 } 00585 00586 00587 /** 00588 * @brief Process packet with unknown code 00589 * @param[in] context PPP context 00590 * @param[in] packet Un-interpretable packet received from the peer 00591 * @return Error code 00592 **/ 00593 00594 error_t ipcpProcessUnknownCode(PppContext *context, 00595 const PppPacket *packet) 00596 { 00597 //Debug message 00598 TRACE_INFO("\r\nIPCP Receive-Unknown-Code event\r\n"); 00599 00600 //This event occurs when an un-interpretable packet is received from 00601 //the peer. A Code-Reject packet is sent in response 00602 pppRcvUnknownCodeEvent(context, &context->ipcpFsm, &ipcpCallbacks, packet); 00603 00604 //Successful processing 00605 return NO_ERROR; 00606 } 00607 00608 00609 /** 00610 * @brief This-Layer-Up callback function 00611 * @param[in] context PPP context 00612 **/ 00613 00614 void ipcpThisLayerUp(PppContext *context) 00615 { 00616 NetInterface *interface; 00617 00618 //Debug message 00619 TRACE_INFO("IPCP This-Layer-Up callback\r\n"); 00620 00621 //Debug message 00622 TRACE_INFO(" Local IP Addr = %s\r\n", ipv4AddrToString(context->localConfig.ipAddr, NULL)); 00623 TRACE_INFO(" Peer IP Addr = %s\r\n", ipv4AddrToString(context->peerConfig.ipAddr, NULL)); 00624 TRACE_INFO(" Primary DNS = %s\r\n", ipv4AddrToString(context->localConfig.primaryDns, NULL)); 00625 TRACE_INFO(" Secondary DNS = %s\r\n", ipv4AddrToString(context->localConfig.secondaryDns, NULL)); 00626 00627 //Point to the underlying interface 00628 interface = context->interface; 00629 00630 //Update IPv4 configuration 00631 interface->ipv4Context.addr = context->localConfig.ipAddr; 00632 interface->ipv4Context.addrState = IPV4_ADDR_STATE_VALID; 00633 interface->ipv4Context.defaultGateway = context->peerConfig.ipAddr; 00634 00635 //Update the list of DNS servers 00636 interface->ipv4Context.dnsServerList[0] = context->localConfig.primaryDns; 00637 #if (IPV4_DNS_SERVER_LIST_SIZE >= 2) 00638 interface->ipv4Context.dnsServerList[1] = context->localConfig.secondaryDns; 00639 #endif 00640 00641 //All the outgoing traffic will be routed to the other end of the link 00642 interface->ipv4Context.subnetMask = IPCP_DEFAULT_SUBNET_MASK; 00643 00644 //Link is up 00645 interface->linkState = TRUE; 00646 00647 //Disable interrupts 00648 interface->nicDriver->disableIrq(interface); 00649 //Process link state change event 00650 nicNotifyLinkChange(interface); 00651 //Re-enable interrupts 00652 interface->nicDriver->enableIrq(interface); 00653 } 00654 00655 00656 /** 00657 * @brief This-Layer-Down callback function 00658 * @param[in] context PPP context 00659 **/ 00660 00661 void ipcpThisLayerDown(PppContext *context) 00662 { 00663 NetInterface *interface; 00664 00665 //Debug message 00666 TRACE_INFO("IPCP This-Layer-Down callback\r\n"); 00667 00668 //Point to the underlying interface 00669 interface = context->interface; 00670 00671 //Link is up 00672 interface->linkState = FALSE; 00673 00674 //Disable interrupts 00675 interface->nicDriver->disableIrq(interface); 00676 //Process link state change event 00677 nicNotifyLinkChange(interface); 00678 //Re-enable interrupts 00679 interface->nicDriver->enableIrq(interface); 00680 } 00681 00682 00683 /** 00684 * @brief This-Layer-Started callback function 00685 * @param[in] context PPP context 00686 **/ 00687 00688 void ipcpThisLayerStarted(PppContext *context) 00689 { 00690 //Debug message 00691 TRACE_INFO("IPCP This-Layer-Started callback\r\n"); 00692 } 00693 00694 00695 /** 00696 * @brief This-Layer-Finished callback function 00697 * @param[in] context PPP context 00698 **/ 00699 00700 void ipcpThisLayerFinished(PppContext *context) 00701 { 00702 //Debug message 00703 TRACE_INFO("IPCP This-Layer-Finished callback\r\n"); 00704 } 00705 00706 00707 /** 00708 * @brief Initialize-Restart-Count callback function 00709 * @param[in] context PPP context 00710 * @param[in] value Restart counter value 00711 **/ 00712 00713 void ipcpInitRestartCount(PppContext *context, uint_t value) 00714 { 00715 //Debug message 00716 TRACE_INFO("IPCP Initialize-Restart-Count callback\r\n"); 00717 00718 //Initialize restart counter 00719 context->ipcpFsm.restartCounter = value; 00720 } 00721 00722 00723 /** 00724 * @brief Zero-Restart-Count callback function 00725 * @param[in] context PPP context 00726 **/ 00727 00728 void ipcpZeroRestartCount(PppContext *context) 00729 { 00730 //Debug message 00731 TRACE_INFO("IPCP Zero-Restart-Count callback\r\n"); 00732 00733 //Zero restart counter 00734 context->ipcpFsm.restartCounter = 0; 00735 00736 //The receiver of a Terminate-Request should wait for the peer to 00737 //disconnect, and must not disconnect until at least one Restart 00738 //time has passed after sending a Terminate-Ack 00739 context->ipcpFsm.timestamp = osGetSystemTime(); 00740 } 00741 00742 00743 /** 00744 * @brief Send-Configure-Request callback function 00745 * @param[in] context PPP context 00746 * @return Error code 00747 **/ 00748 00749 error_t ipcpSendConfigureReq(PppContext *context) 00750 { 00751 error_t error; 00752 size_t length; 00753 size_t offset; 00754 NetBuffer *buffer; 00755 PppConfigurePacket *configureReqPacket; 00756 00757 //Debug message 00758 TRACE_INFO("IPCP Send-Configure-Request callback\r\n"); 00759 00760 //Allocate a buffer memory to hold the Configure-Request packet 00761 buffer = pppAllocBuffer(PPP_MAX_CONF_REQ_SIZE, &offset); 00762 //Failed to allocate memory? 00763 if(buffer == NULL) 00764 return ERROR_OUT_OF_MEMORY; 00765 00766 //Point to the Configure-Request packet 00767 configureReqPacket = netBufferAt(buffer, offset); 00768 00769 //Format packet header 00770 configureReqPacket->code = PPP_CODE_CONFIGURE_REQ; 00771 configureReqPacket->identifier = ++context->ipcpFsm.identifier; 00772 configureReqPacket->length = sizeof(PppConfigurePacket); 00773 00774 //Make sure the IP-Address option has not been previously rejected 00775 if(!context->localConfig.ipAddrRejected) 00776 { 00777 //Add option 00778 pppAddOption(configureReqPacket, IPCP_OPTION_IP_ADDRESS, 00779 &context->localConfig.ipAddr, sizeof(Ipv4Addr)); 00780 } 00781 00782 //Make sure the Primary-DNS-Server-Address option has not been 00783 //previously rejected 00784 if(!context->localConfig.primaryDnsRejected) 00785 { 00786 //Add option 00787 pppAddOption(configureReqPacket, IPCP_OPTION_PRIMARY_DNS, 00788 &context->localConfig.primaryDns, sizeof(Ipv4Addr)); 00789 } 00790 00791 //Make sure the Secondary-DNS-Server-Address option has not been 00792 //previously rejected 00793 if(!context->localConfig.secondaryDnsRejected) 00794 { 00795 //Add option 00796 pppAddOption(configureReqPacket, IPCP_OPTION_SECONDARY_DNS, 00797 &context->localConfig.secondaryDns, sizeof(Ipv4Addr)); 00798 } 00799 00800 //Save packet length 00801 length = configureReqPacket->length; 00802 //Convert length field to network byte order 00803 configureReqPacket->length = htons(length); 00804 00805 //Adjust the length of the multi-part buffer 00806 netBufferSetLength(buffer, offset + length); 00807 00808 //Debug message 00809 TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length); 00810 //Dump packet contents for debugging purpose 00811 pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_IPCP); 00812 00813 //Send PPP frame 00814 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_IPCP); 00815 00816 //The restart counter is decremented each time a Configure-Request is sent 00817 if(context->ipcpFsm.restartCounter > 0) 00818 context->ipcpFsm.restartCounter--; 00819 00820 //Save the time at which the packet was sent 00821 context->ipcpFsm.timestamp = osGetSystemTime(); 00822 00823 //Free previously allocated memory block 00824 netBufferFree(buffer); 00825 //Return status code 00826 return error; 00827 } 00828 00829 00830 /** 00831 * @brief Send-Configure-Ack callback function 00832 * @param[in] context PPP context 00833 * @param[in] configureReqPacket Configure-Request packet received from the peer 00834 * @return Error code 00835 **/ 00836 00837 error_t ipcpSendConfigureAck(PppContext *context, 00838 const PppConfigurePacket *configureReqPacket) 00839 { 00840 //Debug message 00841 TRACE_INFO("IPCP Send-Configure-Ack callback\r\n"); 00842 00843 //Send Configure-Ack packet 00844 return pppSendConfigureAckNak(context, configureReqPacket, 00845 PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_ACK); 00846 } 00847 00848 00849 /** 00850 * @brief Send-Configure-Nak callback function 00851 * @param[in] context PPP context 00852 * @param[in] configureReqPacket Configure-Request packet received from the peer 00853 * @return Error code 00854 **/ 00855 00856 error_t ipcpSendConfigureNak(PppContext *context, 00857 const PppConfigurePacket *configureReqPacket) 00858 { 00859 //Debug message 00860 TRACE_INFO("IPCP Send-Configure-Nak callback\r\n"); 00861 00862 //Send Configure-Nak packet 00863 return pppSendConfigureAckNak(context, configureReqPacket, 00864 PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_NAK); 00865 } 00866 00867 00868 /** 00869 * @brief Send-Configure-Reject callback function 00870 * @param[in] context PPP context 00871 * @param[in] configureReqPacket Configure-Request packet received from the peer 00872 * @return Error code 00873 **/ 00874 00875 error_t ipcpSendConfigureRej(PppContext *context, 00876 const PppConfigurePacket *configureReqPacket) 00877 { 00878 //Debug message 00879 TRACE_INFO("IPCP Send-Configure-Reject callback\r\n"); 00880 00881 //Send Configure-Reject packet 00882 return pppSendConfigureAckNak(context, configureReqPacket, 00883 PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_REJ); 00884 } 00885 00886 00887 /** 00888 * @brief Send-Terminate-Request callback function 00889 * @param[in] context PPP context 00890 * @return Error code 00891 **/ 00892 00893 error_t ipcpSendTerminateReq(PppContext *context) 00894 { 00895 error_t error; 00896 00897 //Debug message 00898 TRACE_INFO("IPCP Send-Terminate-Request callback\r\n"); 00899 00900 //On transmission, the Identifier field must be changed 00901 context->ipcpFsm.identifier++; 00902 00903 //Send Terminate-Request packet 00904 error = pppSendTerminateReq(context, context->ipcpFsm.identifier, PPP_PROTOCOL_IPCP); 00905 00906 //The restart counter is decremented each time a Terminate-Request is sent 00907 if(context->ipcpFsm.restartCounter > 0) 00908 context->ipcpFsm.restartCounter--; 00909 00910 //Save the time at which the packet was sent 00911 context->ipcpFsm.timestamp = osGetSystemTime(); 00912 00913 //Return status code 00914 return error; 00915 } 00916 00917 00918 /** 00919 * @brief Send-Terminate-Ack callback function 00920 * @param[in] context PPP context 00921 * @param[in] terminateReqPacket Terminate-Request packet received from the peer 00922 * @return Error code 00923 **/ 00924 00925 error_t ipcpSendTerminateAck(PppContext *context, 00926 const PppTerminatePacket *terminateReqPacket) 00927 { 00928 uint8_t identifier; 00929 00930 //Debug message 00931 TRACE_INFO("IPCP Send-Terminate-Ack callback\r\n"); 00932 00933 //Check whether this Terminate-Ack acknowledges the reception of a 00934 //Terminate-Request packet 00935 if(terminateReqPacket != NULL) 00936 { 00937 //The Identifier field of the Terminate-Request is copied into the 00938 //Identifier field of the Terminate-Ack packet 00939 identifier = terminateReqPacket->identifier; 00940 } 00941 else 00942 { 00943 //This Terminate-Ack packet serves to synchronize the automatons 00944 identifier = ++context->ipcpFsm.identifier; 00945 } 00946 00947 //Send Terminate-Ack packet 00948 return pppSendTerminateAck(context, identifier, PPP_PROTOCOL_IPCP); 00949 } 00950 00951 00952 /** 00953 * @brief Send-Code-Reject callback function 00954 * @param[in] context PPP context 00955 * @param[in] packet Un-interpretable packet received from the peer 00956 * @return Error code 00957 **/ 00958 00959 error_t ipcpSendCodeRej(PppContext *context, const PppPacket *packet) 00960 { 00961 //Debug message 00962 TRACE_INFO("IPCP Send-Code-Reject callback\r\n"); 00963 00964 //The Identifier field must be changed for each Code-Reject sent 00965 context->ipcpFsm.identifier++; 00966 00967 //Send Code-Reject packet 00968 return pppSendCodeRej(context, packet, context->ipcpFsm.identifier, PPP_PROTOCOL_IPCP); 00969 } 00970 00971 00972 /** 00973 * @brief Parse IPCP configuration option 00974 * @param[in] context PPP context 00975 * @param[in] option Option to be checked 00976 * @param[in] inPacketLen Remaining bytes to process in the incoming packet 00977 * @param[out] outPacket Pointer to the Configure-Ack, Nak or Reject packet 00978 * @return Error code 00979 **/ 00980 00981 error_t ipcpParseOption(PppContext *context, PppOption *option, 00982 size_t inPacketLen, PppConfigurePacket *outPacket) 00983 { 00984 error_t error; 00985 00986 //Malformed IPCP packet? 00987 if(inPacketLen < sizeof(PppOption)) 00988 return ERROR_INVALID_LENGTH; 00989 00990 //Check option length 00991 if(option->length < sizeof(PppOption)) 00992 return ERROR_INVALID_LENGTH; 00993 if(option->length > inPacketLen) 00994 return ERROR_INVALID_LENGTH; 00995 00996 //Check option type 00997 switch(option->type) 00998 { 00999 case IPCP_OPTION_IP_ADDRESS: 01000 //Check IP-Address option 01001 error = ipcpParseIpAddressOption(context, (IpcpIpAddressOption *) option, outPacket); 01002 break; 01003 default: 01004 //If some configuration options received in the Configure-Request are not 01005 //recognizable or not acceptable for negotiation, then the implementation 01006 //must transmit a Configure-Reject 01007 if(outPacket->code == PPP_CODE_CONFIGURE_REJ) 01008 { 01009 //The options field of the Configure-Reject packet is filled 01010 //with the unrecognized options from the Configure-Request 01011 pppAddOption(outPacket, option->type, option->data, 01012 option->length - sizeof(PppOption)); 01013 } 01014 01015 //The option is not acceptable for negotiation 01016 error = ERROR_INVALID_TYPE; 01017 break; 01018 } 01019 01020 //Return status code 01021 return error; 01022 } 01023 01024 01025 /** 01026 * @brief Parse IP-Address option 01027 * @param[in] context PPP context 01028 * @param[in] option Option to be checked 01029 * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet 01030 * @return Error code 01031 **/ 01032 01033 error_t ipcpParseIpAddressOption(PppContext *context, 01034 IpcpIpAddressOption *option, PppConfigurePacket *outPacket) 01035 { 01036 error_t error; 01037 01038 //Check length field 01039 if(option->length == sizeof(IpcpIpAddressOption)) 01040 { 01041 //Check whether the option value is acceptable 01042 if(option->ipAddr != IPV4_UNSPECIFIED_ADDR) 01043 { 01044 //If every configuration option received in the Configure-Request is 01045 //recognizable and all values are acceptable, then the implementation 01046 //must transmit a Configure-Ack 01047 if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK) 01048 { 01049 //Save IP address 01050 context->peerConfig.ipAddr = option->ipAddr; 01051 01052 //The options field of the Configure-Ack packet contains the 01053 //configuration options that the sender is acknowledging 01054 pppAddOption(outPacket, IPCP_OPTION_IP_ADDRESS, 01055 (void *) &option->ipAddr, option->length - sizeof(PppOption)); 01056 } 01057 01058 //The value is acceptable 01059 error = NO_ERROR; 01060 } 01061 else 01062 { 01063 //If all configuration options are recognizable, but some values are not 01064 //acceptable, then the implementation must transmit a Configure-Nak 01065 if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK) 01066 { 01067 //The option must be modified to a value acceptable to the 01068 //Configure-Nak sender 01069 pppAddOption(outPacket, IPCP_OPTION_IP_ADDRESS, 01070 &context->peerConfig.ipAddr, sizeof(Ipv4Addr)); 01071 } 01072 01073 //The value is not acceptable 01074 error = ERROR_INVALID_VALUE; 01075 } 01076 } 01077 else 01078 { 01079 //Invalid length field 01080 error = ERROR_INVALID_LENGTH; 01081 } 01082 01083 //Return status code 01084 return error; 01085 } 01086 01087 #endif 01088
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2