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