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