ipv6cp.c
Go to the documentation of this file.
1 /**
2  * @file ipv6cp.c
3  * @brief IPV6CP (PPP IPv6 Control Protocol)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL PPP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "ipv6/ipv6.h"
35 #include "ipv6/ipv6_misc.h"
36 #include "ppp/ppp_fsm.h"
37 #include "ppp/ppp_misc.h"
38 #include "ppp/ppp_debug.h"
39 #include "ppp/ipv6cp.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (PPP_SUPPORT == ENABLED && IPV6_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief IPV6CP FSM callbacks
48  **/
49 
51 {
65  NULL
66 };
67 
68 
69 /**
70  * @brief IPV6CP Open event
71  * @param[in] context PPP context
72  * @return Error code
73  **/
74 
76 {
77  //Debug message
78  TRACE_INFO("\r\nIPV6CP Open event\r\n");
79 
80  //The link is administratively available for traffic
81  pppOpenEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
82  //The lower layer is ready to carry packets
83  pppUpEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
84 
85  //Successful processing
86  return NO_ERROR;
87 }
88 
89 
90 /**
91  * @brief IPV6CP Close event
92  * @param[in] context PPP context
93  * @return Error code
94  **/
95 
97 {
98  //Debug message
99  TRACE_INFO("\r\nIPV6CP Close event\r\n");
100 
101  //The lower layer is no longer ready to carry packets
102  pppDownEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
103  //The link is no longer available for traffic
104  pppCloseEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
105 
106  //Successful processing
107  return NO_ERROR;
108 }
109 
110 
111 /**
112  * @brief IPV6CP timer handler
113  *
114  * This routine must be periodically called by the TCP/IP stack to
115  * manage retransmissions
116  *
117  * @param[in] context PPP context
118  **/
119 
120 void ipv6cpTick(PppContext *context)
121 {
122  //Check whether the restart timer is running
123  if(context->ipv6cpFsm.state >= PPP_STATE_4_CLOSING &&
124  context->ipv6cpFsm.state <= PPP_STATE_8_ACK_SENT)
125  {
126  //Get current time
128 
129  //Check restart timer
130  if((time - context->ipv6cpFsm.timestamp) >= PPP_RESTART_TIMER)
131  {
132  //Debug message
133  TRACE_INFO("\r\nIPV6CP Timeout event\r\n");
134 
135  //The restart timer is used to retransmit Configure-Request
136  //and Terminate-Request packets
137  pppTimeoutEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
138  }
139  }
140 }
141 
142 
143 /**
144  * @brief Process an incoming IPV6CP packet
145  * @param[in] context PPP context
146  * @param[in] packet IPV6CP packet received from the peer
147  * @param[in] length Length of the packet, in bytes
148  **/
149 
150 void ipv6cpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
151 {
152  //Ensure the length of the incoming IPV6CP packet is valid
153  if(length < sizeof(PppPacket))
154  return;
155 
156  //Check the length field
157  if(ntohs(packet->length) > length)
158  return;
159  if(ntohs(packet->length) < sizeof(PppPacket))
160  return;
161 
162  //Save the length of the IPV6CP packet
163  length = ntohs(packet->length);
164 
165  //Debug message
166  TRACE_INFO("IPV6CP packet received (%" PRIuSIZE " bytes)...\r\n", length);
167  //Dump IPV6CP packet contents for debugging purpose
169 
170  //Check IPV6CP code field
171  switch(packet->code)
172  {
173  //Configure-Request packet?
175  //Process Configure-Request packet
176  ipv6cpProcessConfigureReq(context, (PppConfigurePacket *) packet);
177  break;
178  //Configure-Ack packet?
180  //Process Configure-Ack packet
181  ipv6cpProcessConfigureAck(context, (PppConfigurePacket *) packet);
182  break;
183  //Configure-Nak packet?
185  //Process Configure-Nak packet
186  ipv6cpProcessConfigureNak(context, (PppConfigurePacket *) packet);
187  break;
188  //Configure-Reject packet?
190  //Process Configure-Reject packet
192  break;
193  //Terminate-Request packet?
195  //Process Terminate-Request packet
196  ipv6cpProcessTerminateReq(context, (PppTerminatePacket *) packet);
197  break;
198  //Terminate-Ack packet?
200  //Process Terminate-Ack packet
201  ipv6cpProcessTerminateAck(context, (PppTerminatePacket *) packet);
202  break;
203  //Code-Reject packet?
204  case PPP_CODE_CODE_REJ:
205  //Process Code-Reject packet
206  ipv6cpProcessCodeRej(context, (PppCodeRejPacket *) packet);
207  break;
208  //Unknown code field
209  default:
210  //The packet is un-interpretable
211  ipv6cpProcessUnknownCode(context, packet);
212  break;
213  }
214 }
215 
216 
217 /**
218  * @brief Process Configure-Request packet
219  * @param[in] context PPP context
220  * @param[in] configureReqPacket Packet received from the peer
221  * @return Error code
222  **/
223 
225  const PppConfigurePacket *configureReqPacket)
226 {
227  error_t error;
228  size_t length;
229  bool_t notRecognizable;
230  bool_t notAcceptable;
231  PppOption *option;
232 
233  //Debug message
234  TRACE_INFO("\r\nIPV6CP Receive-Configure-Request event\r\n");
235 
236  //Initialize variables
237  error = NO_ERROR;
238  notRecognizable = FALSE;
239  notAcceptable = FALSE;
240 
241  //Retrieve the length of the option list
242  length = ntohs(configureReqPacket->length) - sizeof(PppConfigurePacket);
243  //Point to the first option
244  option = (PppOption *) configureReqPacket->options;
245 
246  //Parse configuration options
247  while(length > 0)
248  {
249  //Parse current option
250  error = ipv6cpParseOption(context, option, length, NULL);
251 
252  //Any error to report?
253  if(error == ERROR_INVALID_TYPE)
254  {
255  //Option not recognizable
256  notRecognizable = TRUE;
257  //Catch error
258  error = NO_ERROR;
259  }
260  else if(error == ERROR_INVALID_VALUE)
261  {
262  //Option not acceptable for configuration
263  notAcceptable = TRUE;
264  //Catch error
265  error = NO_ERROR;
266  }
267  else if(error)
268  {
269  //Malformed Configure-Request packet
270  break;
271  }
272 
273  //Remaining bytes to process
274  length -= option->length;
275  //Jump to the next option
276  option = (PppOption *) ((uint8_t *) option + option->length);
277  }
278 
279  //Valid Configure-Request packet received from the peer?
280  if(!error)
281  {
282  //Check flags
283  if(notRecognizable)
284  {
285  //If some configuration options received in the Configure-Request are not
286  //recognizable or not acceptable for negotiation, then the implementation
287  //must transmit a Configure-Reject
288  pppRcvConfigureReqEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks,
289  configureReqPacket, PPP_CODE_CONFIGURE_REJ);
290  }
291  else if(notAcceptable)
292  {
293  //If all configuration options are recognizable, but some values are not
294  //acceptable, then the implementation must transmit a Configure-Nak
295  pppRcvConfigureReqEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks,
296  configureReqPacket, PPP_CODE_CONFIGURE_NAK);
297  }
298  else
299  {
300  //If every configuration option received in the Configure-Request is
301  //recognizable and all values are acceptable, then the implementation
302  //must transmit a Configure-Ack
303  pppRcvConfigureReqEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks,
304  configureReqPacket, PPP_CODE_CONFIGURE_ACK);
305  }
306  }
307 
308  //Return status code
309  return error;
310 }
311 
312 
313 /**
314  * @brief Process Configure-Ack packet
315  * @param[in] context PPP context
316  * @param[in] configureAckPacket Packet received from the peer
317  * @return Error code
318  **/
319 
321  const PppConfigurePacket *configureAckPacket)
322 {
323  //Debug message
324  TRACE_INFO("\r\nIPV6CP Receive-Configure-Ack event\r\n");
325 
326  //When a packet is received with an invalid Identifier field, the
327  //packet is silently discarded without affecting the automaton
328  if(configureAckPacket->identifier != context->ipv6cpFsm.identifier)
329  return ERROR_WRONG_IDENTIFIER;
330 
331  //A valid Configure-Ack packet has been received from the peer
332  pppRcvConfigureAckEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
333 
334  //Successful processing
335  return NO_ERROR;
336 }
337 
338 
339 /**
340  * @brief Process Configure-Nak packet
341  * @param[in] context PPP context
342  * @param[in] configureNakPacket Packet received from the peer
343  * @return Error code
344  **/
345 
347  const PppConfigurePacket *configureNakPacket)
348 {
349  size_t length;
350  PppOption *option;
351 
352  //Debug message
353  TRACE_INFO("IPV6CP Receive-Configure-Nak event\r\n");
354 
355  //When a packet is received with an invalid Identifier field, the
356  //packet is silently discarded without affecting the automaton
357  if(configureNakPacket->identifier != context->ipv6cpFsm.identifier)
358  return ERROR_WRONG_IDENTIFIER;
359 
360  //Retrieve the length of the option list
361  length = ntohs(configureNakPacket->length) - sizeof(PppConfigurePacket);
362  //Point to the first option
363  option = (PppOption *) configureNakPacket->options;
364 
365  //Parse configuration options
366  while(length > 0)
367  {
368  //Check option length
369  if(option->length < sizeof(PppOption))
370  return ERROR_INVALID_LENGTH;
371  if(option->length > length)
372  return ERROR_INVALID_LENGTH;
373 
374  //Interface-Identifier option?
375  if(option->type == IPV6CP_OPTION_INTERFACE_ID)
376  {
377  //Cast option
378  Ipv6cpInterfaceIdOption *interfaceIdOption = (Ipv6cpInterfaceIdOption *) option;
379 
380  //Check option length
381  if(interfaceIdOption->length != sizeof(Ipv6cpInterfaceIdOption))
382  return ERROR_INVALID_LENGTH;
383 
384  //Save interface identifier
385  context->localConfig.interfaceId = interfaceIdOption->interfaceId;
386  }
387 
388  //Remaining bytes to process
389  length -= option->length;
390  //Jump to the next option
391  option = (PppOption *) ((uint8_t *) option + option->length);
392  }
393 
394  //A valid Configure-Nak or Configure-Reject packet has been received from the peer
395  pppRcvConfigureNakEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
396 
397  //Successful processing
398  return NO_ERROR;
399 }
400 
401 
402 /**
403  * @brief Process Configure-Reject packet
404  * @param[in] context PPP context
405  * @param[in] configureRejPacket Packet received from the peer
406  * @return Error code
407  **/
408 
410  const PppConfigurePacket *configureRejPacket)
411 {
412  size_t length;
413  PppOption *option;
414 
415  //Debug message
416  TRACE_INFO("\r\nIPV6CP Receive-Configure-Reject event\r\n");
417 
418  //When a packet is received with an invalid Identifier field, the
419  //packet is silently discarded without affecting the automaton
420  if(configureRejPacket->identifier != context->ipv6cpFsm.identifier)
421  return ERROR_WRONG_IDENTIFIER;
422 
423  //Retrieve the length of the option list
424  length = ntohs(configureRejPacket->length) - sizeof(PppConfigurePacket);
425  //Point to the first option
426  option = (PppOption *) configureRejPacket->options;
427 
428  //Parse configuration options
429  while(length > 0)
430  {
431  //Check option length
432  if(option->length < sizeof(PppOption))
433  return ERROR_INVALID_LENGTH;
434  if(option->length > length)
435  return ERROR_INVALID_LENGTH;
436 
437  //Interface-Identifier option?
438  if(option->type == IPV6CP_OPTION_INTERFACE_ID)
439  {
440  //The option is not recognized by the peer
441  context->localConfig.interfaceIdRejected = TRUE;
442  }
443 
444  //Remaining bytes to process
445  length -= option->length;
446  //Jump to the next option
447  option = (PppOption *) ((uint8_t *) option + option->length);
448  }
449 
450  //A valid Configure-Nak or Configure-Reject packet has been received from the peer
451  pppRcvConfigureNakEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
452 
453  //Successful processing
454  return NO_ERROR;
455 }
456 
457 
458 /**
459  * @brief Process Terminate-Request packet
460  * @param[in] context PPP context
461  * @param[in] terminateReqPacket Packet received from the peer
462  * @return Error code
463  **/
464 
466  const PppTerminatePacket *terminateReqPacket)
467 {
468  //Debug message
469  TRACE_INFO("\r\nIPV6CP Receive-Terminate-Request event\r\n");
470 
471  //The Terminate-Request indicates the desire of the peer to close the connection
472  pppRcvTerminateReqEvent(context, &context->ipv6cpFsm,
473  &ipv6cpCallbacks, terminateReqPacket);
474 
475  //Successful processing
476  return NO_ERROR;
477 }
478 
479 
480 /**
481  * @brief Process Terminate-Ack packet
482  * @param[in] context PPP context
483  * @param[in] terminateAckPacket Packet received from the peer
484  * @return Error code
485  **/
486 
488  const PppTerminatePacket *terminateAckPacket)
489 {
490  //Debug message
491  TRACE_INFO("\r\nIPV6CP Receive-Terminate-Ack event\r\n");
492 
493  //The Terminate-Ack packet is usually a response to a Terminate-Request
494  //packet. This packet may also indicate that the peer is in Closed or
495  //Stopped states, and serves to re-synchronize the link configuration
496  pppRcvTerminateAckEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks);
497 
498  //Successful processing
499  return NO_ERROR;
500 }
501 
502 
503 /**
504  * @brief Process Code-Reject packet
505  * @param[in] context PPP context
506  * @param[in] codeRejPacket Packet received from the peer
507  * @return Error code
508  **/
509 
511  const PppCodeRejPacket *codeRejPacket)
512 {
513  size_t length;
514  PppPacket *packet;
515 
516  //Debug message
517  TRACE_INFO("\r\nIPV6CP Receive-Code-Reject event\r\n");
518 
519  //Point to the rejected packet
520  packet = (PppPacket *) codeRejPacket->rejectedPacket;
521  //Retrieve the length of the rejected packet
522  length = ntohs(codeRejPacket->length) - sizeof(PppCodeRejPacket);
523 
524  //Make sure the length of the rejected packet is valid
525  if(length < sizeof(PppPacket))
526  return ERROR_INVALID_LENGTH;
527 
528  //Check whether the rejected value is acceptable or catastrophic
529  if(packet->code < PPP_CODE_CONFIGURE_REQ ||
530  packet->code > PPP_CODE_CODE_REJ)
531  {
532  //The RXJ+ event arises when the rejected value is acceptable, such
533  //as a Code-Reject of an extended code, or a Protocol-Reject of a
534  //NCP. These are within the scope of normal operation
535  pppRcvCodeRejEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks, TRUE);
536  }
537  else
538  {
539  //The RXJ- event arises when the rejected value is catastrophic, such
540  //as a Code-Reject of Configure-Request! This event communicates an
541  //unrecoverable error that terminates the connection
542  pppRcvCodeRejEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks, FALSE);
543  }
544 
545  //Successful processing
546  return NO_ERROR;
547 }
548 
549 
550 /**
551  * @brief Process packet with unknown code
552  * @param[in] context PPP context
553  * @param[in] packet Un-interpretable packet received from the peer
554  * @return Error code
555  **/
556 
558  const PppPacket *packet)
559 {
560  //Debug message
561  TRACE_INFO("\r\nIPV6CP Receive-Unknown-Code event\r\n");
562 
563  //This event occurs when an un-interpretable packet is received from
564  //the peer. A Code-Reject packet is sent in response
565  pppRcvUnknownCodeEvent(context, &context->ipv6cpFsm, &ipv6cpCallbacks, packet);
566 
567  //Successful processing
568  return NO_ERROR;
569 }
570 
571 
572 /**
573  * @brief This-Layer-Up callback function
574  * @param[in] context PPP context
575  **/
576 
578 {
579  NetInterface *interface;
581 
582  //Debug message
583  TRACE_INFO("IPV6CP This-Layer-Up callback\r\n");
584 
585  //Debug message
586  TRACE_INFO(" Local Interface Id = %s\r\n",
587  eui64AddrToString(&context->localConfig.interfaceId, NULL));
588  TRACE_INFO(" Peer Interface Id = %s\r\n",
589  eui64AddrToString(&context->peerConfig.interfaceId, NULL));
590 
591  //Point to the underlying interface
592  interface = context->interface;
593 
594  //Generate an IPv6 address from the local interface identifier
595  ipv6GenerateLinkLocalAddr(&context->localConfig.interfaceId, &ipAddr);
596 
597  //Update IPv6 configuration
600 
601  //Generate an IPv6 address from the remote interface identifier
602  ipv6GenerateLinkLocalAddr(&context->peerConfig.interfaceId, &ipAddr);
603 
604  //Update IPv6 configuration
605  interface->ipv6Context.routerList[0].addr = ipAddr;
606  interface->ipv6Context.routerList[0].permanent = TRUE;
607 
608  //Link is up
609  interface->linkState = TRUE;
610 
611  //Disable interrupts
612  interface->nicDriver->disableIrq(interface);
613  //Process link state change event
614  nicNotifyLinkChange(interface);
615  //Re-enable interrupts
616  interface->nicDriver->enableIrq(interface);
617 }
618 
619 
620 /**
621  * @brief This-Layer-Down callback function
622  * @param[in] context PPP context
623  **/
624 
626 {
627  NetInterface *interface;
628 
629  //Debug message
630  TRACE_INFO("IPV6CP This-Layer-Down callback\r\n");
631 
632  //Point to the underlying interface
633  interface = context->interface;
634 
635  //Link is up
636  interface->linkState = FALSE;
637 
638  //Disable interrupts
639  interface->nicDriver->disableIrq(interface);
640  //Process link state change event
641  nicNotifyLinkChange(interface);
642  //Re-enable interrupts
643  interface->nicDriver->enableIrq(interface);
644 }
645 
646 
647 /**
648  * @brief This-Layer-Started callback function
649  * @param[in] context PPP context
650  **/
651 
653 {
654  //Debug message
655  TRACE_INFO("IPV6CP This-Layer-Started callback\r\n");
656 }
657 
658 
659 /**
660  * @brief This-Layer-Finished callback function
661  * @param[in] context PPP context
662  **/
663 
665 {
666  //Debug message
667  TRACE_INFO("IPV6CP This-Layer-Finished callback\r\n");
668 }
669 
670 
671 /**
672  * @brief Initialize-Restart-Count callback function
673  * @param[in] context PPP context
674  * @param[in] value Restart counter value
675  **/
676 
678 {
679  //Debug message
680  TRACE_INFO("IPV6CP Initialize-Restart-Count callback\r\n");
681 
682  //Initialize restart counter
683  context->ipv6cpFsm.restartCounter = value;
684 }
685 
686 
687 /**
688  * @brief Zero-Restart-Count callback function
689  * @param[in] context PPP context
690  **/
691 
693 {
694  //Debug message
695  TRACE_INFO("IPV6CP Zero-Restart-Count callback\r\n");
696 
697  //Zero restart counter
698  context->ipv6cpFsm.restartCounter = 0;
699 
700  //The receiver of a Terminate-Request should wait for the peer to
701  //disconnect, and must not disconnect until at least one Restart
702  //time has passed after sending a Terminate-Ack
703  context->ipv6cpFsm.timestamp = osGetSystemTime();
704 }
705 
706 
707 /**
708  * @brief Send-Configure-Request callback function
709  * @param[in] context PPP context
710  * @return Error code
711  **/
712 
714 {
715  error_t error;
716  size_t length;
717  size_t offset;
718  NetBuffer *buffer;
719  PppConfigurePacket *configureReqPacket;
720 
721  //Debug message
722  TRACE_INFO("IPV6CP Send-Configure-Request callback\r\n");
723 
724  //Allocate a buffer memory to hold the Configure-Request packet
725  buffer = pppAllocBuffer(PPP_MAX_CONF_REQ_SIZE, &offset);
726  //Failed to allocate memory?
727  if(buffer == NULL)
728  return ERROR_OUT_OF_MEMORY;
729 
730  //Point to the Configure-Request packet
731  configureReqPacket = netBufferAt(buffer, offset);
732 
733  //Format packet header
734  configureReqPacket->code = PPP_CODE_CONFIGURE_REQ;
735  configureReqPacket->identifier = ++context->ipv6cpFsm.identifier;
736  configureReqPacket->length = sizeof(PppConfigurePacket);
737 
738  //Make sure the Interface-Identifier option has not been previously rejected
739  if(!context->localConfig.interfaceIdRejected)
740  {
741  //Add option
742  pppAddOption(configureReqPacket, IPV6CP_OPTION_INTERFACE_ID,
743  &context->localConfig.interfaceId, sizeof(Eui64));
744  }
745 
746  //Save packet length
747  length = configureReqPacket->length;
748  //Convert length field to network byte order
749  configureReqPacket->length = htons(length);
750 
751  //Adjust the length of the multi-part buffer
752  netBufferSetLength(buffer, offset + length);
753 
754  //Debug message
755  TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
756  //Dump packet contents for debugging purpose
757  pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_IPV6CP);
758 
759  //Send PPP frame
760  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_IPV6CP);
761 
762  //The restart counter is decremented each time a Configure-Request is sent
763  if(context->ipv6cpFsm.restartCounter > 0)
764  context->ipv6cpFsm.restartCounter--;
765 
766  //Save the time at which the packet was sent
767  context->ipv6cpFsm.timestamp = osGetSystemTime();
768 
769  //Free previously allocated memory block
770  netBufferFree(buffer);
771  //Return status code
772  return error;
773 }
774 
775 
776 /**
777  * @brief Send-Configure-Ack callback function
778  * @param[in] context PPP context
779  * @param[in] configureReqPacket Configure-Request packet received from the peer
780  * @return Error code
781  **/
782 
784  const PppConfigurePacket *configureReqPacket)
785 {
786  //Debug message
787  TRACE_INFO("IPV6CP Send-Configure-Ack callback\r\n");
788 
789  //Send Configure-Ack packet
790  return pppSendConfigureAckNak(context, configureReqPacket,
792 }
793 
794 
795 /**
796  * @brief Send-Configure-Nak callback function
797  * @param[in] context PPP context
798  * @param[in] configureReqPacket Configure-Request packet received from the peer
799  * @return Error code
800  **/
801 
803  const PppConfigurePacket *configureReqPacket)
804 {
805  //Debug message
806  TRACE_INFO("IPV6CP Send-Configure-Nak callback\r\n");
807 
808  //Send Configure-Nak packet
809  return pppSendConfigureAckNak(context, configureReqPacket,
811 }
812 
813 
814 /**
815  * @brief Send-Configure-Reject callback function
816  * @param[in] context PPP context
817  * @param[in] configureReqPacket Configure-Request packet received from the peer
818  * @return Error code
819  **/
820 
822  const PppConfigurePacket *configureReqPacket)
823 {
824  //Debug message
825  TRACE_INFO("IPV6CP Send-Configure-Reject callback\r\n");
826 
827  //Send Configure-Reject packet
828  return pppSendConfigureAckNak(context, configureReqPacket,
830 }
831 
832 
833 /**
834  * @brief Send-Terminate-Request callback function
835  * @param[in] context PPP context
836  * @return Error code
837  **/
838 
840 {
841  error_t error;
842 
843  //Debug message
844  TRACE_INFO("IPV6CP Send-Terminate-Request callback\r\n");
845 
846  //On transmission, the Identifier field must be changed
847  context->ipv6cpFsm.identifier++;
848 
849  //Send Terminate-Request packet
850  error = pppSendTerminateReq(context, context->ipv6cpFsm.identifier, PPP_PROTOCOL_IPV6CP);
851 
852  //The restart counter is decremented each time a Terminate-Request is sent
853  if(context->ipv6cpFsm.restartCounter > 0)
854  context->ipv6cpFsm.restartCounter--;
855 
856  //Save the time at which the packet was sent
857  context->ipv6cpFsm.timestamp = osGetSystemTime();
858 
859  //Return status code
860  return error;
861 }
862 
863 
864 /**
865  * @brief Send-Terminate-Ack callback function
866  * @param[in] context PPP context
867  * @param[in] terminateReqPacket Terminate-Request packet received from the peer
868  * @return Error code
869  **/
870 
872  const PppTerminatePacket *terminateReqPacket)
873 {
874  uint8_t identifier;
875 
876  //Debug message
877  TRACE_INFO("IPV6CP Send-Terminate-Ack callback\r\n");
878 
879  //Check whether this Terminate-Ack acknowledges the reception of a
880  //Terminate-Request packet
881  if(terminateReqPacket != NULL)
882  {
883  //The Identifier field of the Terminate-Request is copied into the
884  //Identifier field of the Terminate-Ack packet
885  identifier = terminateReqPacket->identifier;
886  }
887  else
888  {
889  //This Terminate-Ack packet serves to synchronize the automatons
890  identifier = ++context->ipv6cpFsm.identifier;
891  }
892 
893  //Send Terminate-Ack packet
895 }
896 
897 
898 /**
899  * @brief Send-Code-Reject callback function
900  * @param[in] context PPP context
901  * @param[in] packet Un-interpretable packet received from the peer
902  * @return Error code
903  **/
904 
906 {
907  //Debug message
908  TRACE_INFO("IPV6CP Send-Code-Reject callback\r\n");
909 
910  //The Identifier field must be changed for each Code-Reject sent
911  context->ipv6cpFsm.identifier++;
912 
913  //Send Code-Reject packet
914  return pppSendCodeRej(context, packet, context->ipv6cpFsm.identifier, PPP_PROTOCOL_IPV6CP);
915 }
916 
917 
918 /**
919  * @brief Parse IPV6CP configuration option
920  * @param[in] context PPP context
921  * @param[in] option Option to be checked
922  * @param[in] inPacketLen Remaining bytes to process in the incoming packet
923  * @param[out] outPacket Pointer to the Configure-Ack, Nak or Reject packet
924  * @return Error code
925  **/
926 
928  size_t inPacketLen, PppConfigurePacket *outPacket)
929 {
930  error_t error;
931 
932  //Malformed IPV6CP packet?
933  if(inPacketLen < sizeof(PppOption))
934  return ERROR_INVALID_LENGTH;
935 
936  //Check option length
937  if(option->length < sizeof(PppOption))
938  return ERROR_INVALID_LENGTH;
939  if(option->length > inPacketLen)
940  return ERROR_INVALID_LENGTH;
941 
942  //Check option type
943  switch(option->type)
944  {
946  //Check Interface-Identifier option
947  error = ipv6cpParseInterfaceIdOption(context, (Ipv6cpInterfaceIdOption *) option, outPacket);
948  break;
949  default:
950  //If some configuration options received in the Configure-Request are not
951  //recognizable or not acceptable for negotiation, then the implementation
952  //must transmit a Configure-Reject
953  if(outPacket->code == PPP_CODE_CONFIGURE_REJ)
954  {
955  //The options field of the Configure-Reject packet is filled
956  //with the unrecognized options from the Configure-Request
957  pppAddOption(outPacket, option->type, option->data,
958  option->length - sizeof(PppOption));
959  }
960 
961  //The option is not acceptable for negotiation
962  error = ERROR_INVALID_TYPE;
963  break;
964  }
965 
966  //Return status code
967  return error;
968 }
969 
970 
971 /**
972  * @brief Parse Interface-Identifier option
973  * @param[in] context PPP context
974  * @param[in] option Option to be checked
975  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
976  * @return Error code
977  **/
978 
980  Ipv6cpInterfaceIdOption *option, PppConfigurePacket *outPacket)
981 {
982  error_t error;
983 
984  //Check length field
985  if(option->length == sizeof(Ipv6cpInterfaceIdOption))
986  {
987  //Check whether the option value is acceptable
988  if(!eui64CompAddr(&option->interfaceId, &EUI64_UNSPECIFIED_ADDR))
989  {
990  //If every configuration option received in the Configure-Request is
991  //recognizable and all values are acceptable, then the implementation
992  //must transmit a Configure-Ack
993  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
994  {
995  //Save interface identifier
996  context->peerConfig.interfaceId = option->interfaceId;
997 
998  //The options field of the Configure-Ack packet contains the
999  //configuration options that the sender is acknowledging
1001  &option->interfaceId, option->length - sizeof(PppOption));
1002  }
1003 
1004  //The value is acceptable
1005  error = NO_ERROR;
1006  }
1007  else
1008  {
1009  //If all configuration options are recognizable, but some values are not
1010  //acceptable, then the implementation must transmit a Configure-Nak
1011  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
1012  {
1013  //The option must be modified to a value acceptable to the
1014  //Configure-Nak sender
1016  &context->peerConfig.interfaceId, sizeof(Eui64));
1017  }
1018 
1019  //The value is not acceptable
1020  error = ERROR_INVALID_VALUE;
1021  }
1022  }
1023  else
1024  {
1025  //Invalid length field
1026  error = ERROR_INVALID_LENGTH;
1027  }
1028 
1029  //Return status code
1030  return error;
1031 }
1032 
1033 #endif
__start_packed struct @289 PppTerminatePacket
Terminate-Request and Terminate-Ack packet.
uint32_t systime_t
Definition: compiler_port.h:44
void pppOpenEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Open event.
Definition: ppp_fsm.c:133
error_t ipv6cpSendConfigureRej(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Reject callback function.
Definition: ipv6cp.c:821
Terminate-Request.
Definition: ppp.h:218
void nicNotifyLinkChange(NetInterface *interface)
Process link state change event.
Definition: nic.c:298
#define PPP_MAX_CONF_REQ_SIZE
Definition: ppp.h:138
void pppRcvTerminateAckEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Terminate-Ack event.
Definition: ppp_fsm.c:695
char_t * eui64AddrToString(const Eui64 *eui64, char_t *str)
Convert an EUI-64 address to a dash delimited string.
Definition: ethernet.c:1407
systime_t osGetSystemTime(void)
Retrieve system time.
Code-Reject.
Definition: ppp.h:220
uint32_t time
IPV6CP (PPP IPv6 Control Protocol)
error_t ipv6cpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse IPV6CP configuration option.
Definition: ipv6cp.c:927
Data logging functions for debugging purpose (PPP)
TCP/IP stack core.
PPP miscellaneous functions.
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:280
error_t ipv6cpClose(PppContext *context)
IPV6CP Close event.
Definition: ipv6cp.c:96
Debugging facilities.
void ipv6cpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming IPV6CP packet.
Definition: ipv6cp.c:150
error_t ipv6cpSendConfigureAck(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Ack callback function.
Definition: ipv6cp.c:783
void ipv6cpThisLayerUp(PppContext *context)
This-Layer-Up callback function.
Definition: ipv6cp.c:577
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:318
error_t ipv6cpSendCodeRej(PppContext *context, const PppPacket *packet)
Send-Code-Reject callback function.
Definition: ipv6cp.c:905
error_t ipv6cpSendConfigureReq(PppContext *context)
Send-Configure-Request callback function.
Definition: ipv6cp.c:713
__start_packed struct @290 PppCodeRejPacket
Code-Reject packet.
IPv6 Control Protocol.
Definition: ppp.h:200
__start_packed struct @183 Ipv6Addr
IPv6 network address.
error_t ipv6cpParseInterfaceIdOption(PppContext *context, Ipv6cpInterfaceIdOption *option, PppConfigurePacket *outPacket)
Parse Interface-Identifier option.
Definition: ipv6cp.c:979
Terminate-Ack.
Definition: ppp.h:219
error_t pppSendCodeRej(PppContext *context, const PppPacket *packet, uint8_t identifier, PppProtocol protocol)
Send Code-Reject packet.
Definition: ppp_misc.c:263
Interface-Identifier.
Definition: ipv6cp.h:48
#define htons(value)
Definition: cpu_endian.h:390
PPP FSM actions.
Definition: ppp_fsm.h:150
error_t ipv6cpProcessConfigureNak(PppContext *context, const PppConfigurePacket *configureNakPacket)
Process Configure-Nak packet.
Definition: ipv6cp.c:346
void pppRcvTerminateReqEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, const PppTerminatePacket *terminateReqPacket)
Process Receive-Terminate-Req event.
Definition: ppp_fsm.c:646
void ipv6cpInitRestartCount(PppContext *context, uint_t value)
Initialize-Restart-Count callback function.
Definition: ipv6cp.c:677
error_t ipv6SetAddr(NetInterface *interface, uint_t index, const Ipv6Addr *addr, Ipv6AddrState state, systime_t validLifetime, systime_t preferredLifetime, bool_t permanent)
Set IPv6 address and address state.
Definition: ipv6_misc.c:92
#define PppPacket
Definition: ppp.h:35
error_t ipv6cpSendConfigureNak(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Nak callback function.
Definition: ipv6cp.c:802
error_t ipv6cpProcessConfigureAck(PppContext *context, const PppConfigurePacket *configureAckPacket)
Process Configure-Ack packet.
Definition: ipv6cp.c:320
__start_packed struct @276 Ipv6cpInterfaceIdOption
Interface-Identifier option.
#define TRUE
Definition: os_port.h:48
__start_packed struct @294 PppOption
LCP/NCP option.
Configure-Request.
Definition: ppp.h:214
uint8_t ipAddr[4]
Definition: mib_common.h:185
void pppUpEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Up event.
Definition: ppp_fsm.c:48
__start_packed struct @113 Eui64
EUI-64 identifier.
error_t ipv6cpSendTerminateReq(PppContext *context)
Send-Terminate-Request callback function.
Definition: ipv6cp.c:839
#define ntohs(value)
Definition: cpu_endian.h:396
void ipv6cpZeroRestartCount(PppContext *context)
Zero-Restart-Count callback function.
Definition: ipv6cp.c:692
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
void ipv6cpTick(PppContext *context)
IPV6CP timer handler.
Definition: ipv6cp.c:120
void pppRcvConfigureAckEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Configure-Ack event.
Definition: ppp_fsm.c:522
#define eui64CompAddr(eui64Addr1, eui64Addr2)
Definition: ethernet.h:104
void ipv6cpThisLayerDown(PppContext *context)
This-Layer-Down callback function.
Definition: ipv6cp.c:625
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
void pppDownEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Down event.
Definition: ppp_fsm.c:82
error_t pppSendTerminateAck(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Ack packet.
Definition: ppp_misc.c:213
error_t ipv6cpProcessTerminateAck(PppContext *context, const PppTerminatePacket *terminateAckPacket)
Process Terminate-Ack packet.
Definition: ipv6cp.c:487
void pppRcvConfigureReqEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, const PppConfigurePacket *configureReqPacket, PppCode code)
Process Receive-Configure-Request event.
Definition: ppp_fsm.c:333
uint8_t identifier[]
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:171
#define PppContext
Definition: ppp.h:36
Helper functions for IPv6.
#define TRACE_INFO(...)
Definition: debug.h:86
IPv6 (Internet Protocol Version 6)
Success.
Definition: error.h:42
const Eui64 EUI64_UNSPECIFIED_ADDR
Definition: ethernet.c:1305
PPP finite state machine.
Configure-Ack.
Definition: ppp.h:215
error_t
Error codes.
Definition: error.h:40
error_t ipv6cpProcessTerminateReq(PppContext *context, const PppTerminatePacket *terminateReqPacket)
Process Terminate-Request packet.
Definition: ipv6cp.c:465
void ipv6GenerateLinkLocalAddr(const Eui64 *interfaceId, Ipv6Addr *ipAddr)
Generate a IPv6 link-local address from an interface identifier.
Definition: ipv6_misc.c:1356
error_t ipv6cpSendTerminateAck(PppContext *context, const PppTerminatePacket *terminateReqPacket)
Send-Terminate-Ack callback function.
Definition: ipv6cp.c:871
unsigned int uint_t
Definition: compiler_port.h:43
error_t ipv6cpProcessConfigureReq(PppContext *context, const PppConfigurePacket *configureReqPacket)
Process Configure-Request packet.
Definition: ipv6cp.c:224
#define PRIuSIZE
Definition: compiler_port.h:72
#define NetInterface
Definition: net.h:34
error_t pppDumpPacket(const PppPacket *packet, size_t length, PppProtocol protocol)
Dump LCP/NCP packet for debugging purpose.
Definition: ppp_debug.c:141
void pppRcvUnknownCodeEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, const PppPacket *packet)
Process Receive-Unknown-Code event.
Definition: ppp_fsm.c:755
uint8_t value[]
Definition: dtls_misc.h:141
void pppRcvConfigureNakEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Configure-Nak event.
Definition: ppp_fsm.c:584
const PppCallbacks ipv6cpCallbacks
IPV6CP FSM callbacks.
Definition: ipv6cp.c:50
#define NDP_INFINITE_LIFETIME
Definition: ndp.h:200
void ipv6cpThisLayerStarted(PppContext *context)
This-Layer-Started callback function.
Definition: ipv6cp.c:652
error_t ipv6cpProcessConfigureReject(PppContext *context, const PppConfigurePacket *configureRejPacket)
Process Configure-Reject packet.
Definition: ipv6cp.c:409
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1004
error_t ipv6cpOpen(PppContext *context)
IPV6CP Open event.
Definition: ipv6cp.c:75
void pppTimeoutEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Timeout event.
Definition: ppp_fsm.c:255
error_t pppSendConfigureAckNak(PppContext *context, const PppConfigurePacket *configureReqPacket, PppProtocol protocol, PppCode code)
Send Configure-Ack, Nak or Reject packet.
Definition: ppp_misc.c:54
error_t pppSendTerminateReq(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Request packet.
Definition: ppp_misc.c:164
uint8_t length
Definition: dtls_misc.h:140
void pppRcvCodeRejEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, bool_t acceptable)
Process Receive-Code-Reject or Receive-Protocol-Reject event.
Definition: ppp_fsm.c:790
Configure-Nak.
Definition: ppp.h:216
error_t ipv6cpProcessCodeRej(PppContext *context, const PppCodeRejPacket *codeRejPacket)
Process Code-Reject packet.
Definition: ipv6cp.c:510
Configure-Reject.
Definition: ppp.h:217
#define PPP_RESTART_TIMER
Definition: ppp.h:94
__start_packed struct @288 PppConfigurePacket
Configure-Request, Configure-Ack, Configure-Nak and Configure-Reject packets.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
void pppCloseEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Close event.
Definition: ppp_fsm.c:187
error_t ipv6cpProcessUnknownCode(PppContext *context, const PppPacket *packet)
Process packet with unknown code.
Definition: ipv6cp.c:557
error_t pppAddOption(PppConfigurePacket *packet, uint8_t optionType, const void *optionValue, uint8_t optionLen)
Add an option to a Configure packet.
Definition: ppp_misc.c:446
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1263
void ipv6cpThisLayerFinished(PppContext *context)
This-Layer-Finished callback function.
Definition: ipv6cp.c:664