Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ipcp.c
Go to the documentation of this file.
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
