lcp.c
Go to the documentation of this file.
1 /**
2  * @file lcp.c
3  * @brief LCP (PPP Link 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 "ppp/ppp_fsm.h"
35 #include "ppp/ppp_misc.h"
36 #include "ppp/ppp_debug.h"
37 #include "ppp/lcp.h"
38 #include "ppp/ipcp.h"
39 #include "ppp/ipv6cp.h"
40 #include "ppp/pap.h"
41 #include "ppp/chap.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (PPP_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief LCP FSM callbacks
50  **/
51 
53 {
68 };
69 
70 
71 /**
72  * @brief LCP Open event
73  * @param[in] context PPP context
74  * @return Error code
75  **/
76 
78 {
79  //Debug message
80  TRACE_INFO("\r\nLCP Open event\r\n");
81 
82  //Advance to the Establish phase
83  context->pppPhase = PPP_PHASE_ESTABLISH;
84 
85  //The link is administratively available for traffic
86  pppOpenEvent(context, &context->lcpFsm, &lcpCallbacks);
87  //The lower layer is ready to carry packets
88  pppUpEvent(context, &context->lcpFsm, &lcpCallbacks);
89 
90  //Successful processing
91  return NO_ERROR;
92 }
93 
94 
95 /**
96  * @brief LCP Close event
97  * @param[in] context PPP context
98  * @return Error code
99  **/
100 
102 {
103  //Debug message
104  TRACE_INFO("\r\nLCP Close event\r\n");
105 
106  //The link is no longer available for traffic
107  pppCloseEvent(context, &context->lcpFsm, &lcpCallbacks);
108 
109  //Successful processing
110  return NO_ERROR;
111 }
112 
113 
114 /**
115  * @brief LCP timer handler
116  *
117  * This routine must be periodically called by the TCP/IP stack to
118  * manage retransmissions
119  *
120  * @param[in] context PPP context
121  **/
122 
123 void lcpTick(PppContext *context)
124 {
125  //Check whether the restart timer is running
126  if(context->lcpFsm.state >= PPP_STATE_4_CLOSING &&
127  context->lcpFsm.state <= PPP_STATE_8_ACK_SENT)
128  {
129  //Get current time
131 
132  //Check restart timer
133  if((time - context->lcpFsm.timestamp) >= PPP_RESTART_TIMER)
134  {
135  //Debug message
136  TRACE_INFO("\r\nLCP Timeout event\r\n");
137 
138  //The restart timer is used to retransmit Configure-Request
139  //and Terminate-Request packets
140  pppTimeoutEvent(context, &context->lcpFsm, &lcpCallbacks);
141  }
142  }
143 }
144 
145 
146 /**
147  * @brief Process an incoming LCP packet
148  * @param[in] context PPP context
149  * @param[in] packet LCP packet received from the peer
150  * @param[in] length Length of the packet, in bytes
151  **/
152 
153 void lcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
154 {
155  //Ensure the length of the incoming LCP packet is valid
156  if(length < sizeof(PppPacket))
157  return;
158 
159  //Check the length field
160  if(ntohs(packet->length) > length)
161  return;
162  if(ntohs(packet->length) < sizeof(PppPacket))
163  return;
164 
165  //Save the length of the LCP packet
166  length = ntohs(packet->length);
167 
168  //Debug message
169  TRACE_INFO("LCP packet received (%" PRIuSIZE " bytes)...\r\n", length);
170  //Dump LCP packet contents for debugging purpose
172 
173  //Check LCP code field
174  switch(packet->code)
175  {
176  //Configure-Request packet?
178  //Process Configure-Request packet
179  lcpProcessConfigureReq(context, (PppConfigurePacket *) packet);
180  break;
181  //Configure-Ack packet?
183  //Process Configure-Ack packet
184  lcpProcessConfigureAck(context, (PppConfigurePacket *) packet);
185  break;
186  //Configure-Nak packet?
188  //Process Configure-Nak packet
189  lcpProcessConfigureNak(context, (PppConfigurePacket *) packet);
190  break;
191  //Configure-Reject packet?
193  //Process Configure-Reject packet
194  lcpProcessConfigureReject(context, (PppConfigurePacket *) packet);
195  break;
196  //Terminate-Request packet?
198  //Process Terminate-Request packet
199  lcpProcessTerminateReq(context, (PppTerminatePacket *) packet);
200  break;
201  //Terminate-Ack packet?
203  //Process Terminate-Ack packet
204  lcpProcessTerminateAck(context, (PppTerminatePacket *) packet);
205  break;
206  //Code-Reject packet?
207  case PPP_CODE_CODE_REJ:
208  //Process Code-Reject packet
209  lcpProcessCodeRej(context, (PppCodeRejPacket *) packet);
210  break;
211  //Protocol-Reject packet?
213  //Process Protocol-Reject packet
214  lcpProcessProtocolRej(context, (PppProtocolRejPacket *) packet);
215  break;
216  //Echo-Request packet?
217  case PPP_CODE_ECHO_REQ:
218  //Process Echo-Request packet
219  lcpProcessEchoReq(context, (PppEchoPacket *) packet);
220  break;
221  //Echo-Reply packet?
222  case PPP_CODE_ECHO_REP:
223  //Process Echo-Reply packet
224  lcpProcessEchoRep(context, (PppEchoPacket *) packet);
225  break;
226  //Discard-Request packet?
228  //Process Discard-Request packet
229  lcpProcessDiscardReq(context, (PppDiscardReqPacket *) packet);
230  break;
231  //Unknown code field
232  default:
233  //The packet is un-interpretable
234  lcpProcessUnknownCode(context, packet);
235  break;
236  }
237 }
238 
239 
240 /**
241  * @brief Process Configure-Request packet
242  * @param[in] context PPP context
243  * @param[in] configureReqPacket Packet received from the peer
244  * @return Error code
245  **/
246 
248  const PppConfigurePacket *configureReqPacket)
249 {
250  error_t error;
251  size_t length;
252  bool_t notRecognizable;
253  bool_t notAcceptable;
254  PppOption *option;
255 
256  //Debug message
257  TRACE_INFO("\r\nLCP Receive-Configure-Request event\r\n");
258 
259  //Initialize variables
260  error = NO_ERROR;
261  notRecognizable = FALSE;
262  notAcceptable = FALSE;
263 
264  //Retrieve the length of the option list
265  length = ntohs(configureReqPacket->length) - sizeof(PppConfigurePacket);
266  //Point to the first option
267  option = (PppOption *) configureReqPacket->options;
268 
269  //Parse configuration options
270  while(length > 0)
271  {
272  //Parse current option
273  error = lcpParseOption(context, option, length, NULL);
274 
275  //Any error to report?
276  if(error == ERROR_INVALID_TYPE)
277  {
278  //Option not recognizable
279  notRecognizable = TRUE;
280  //Catch error
281  error = NO_ERROR;
282  }
283  else if(error == ERROR_INVALID_VALUE)
284  {
285  //Option not acceptable for configuration
286  notAcceptable = TRUE;
287  //Catch error
288  error = NO_ERROR;
289  }
290  else if(error)
291  {
292  //Malformed Configure-Request packet
293  break;
294  }
295 
296  //Remaining bytes to process
297  length -= option->length;
298  //Jump to the next option
299  option = (PppOption *) ((uint8_t *) option + option->length);
300  }
301 
302  //Valid Configure-Request packet received from the peer?
303  if(!error)
304  {
305  //Check flags
306  if(notRecognizable)
307  {
308  //If some configuration options received in the Configure-Request are not
309  //recognizable or not acceptable for negotiation, then the implementation
310  //must transmit a Configure-Reject
311  pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
312  configureReqPacket, PPP_CODE_CONFIGURE_REJ);
313  }
314  else if(notAcceptable)
315  {
316  //If all configuration options are recognizable, but some values are not
317  //acceptable, then the implementation must transmit a Configure-Nak
318  pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
319  configureReqPacket, PPP_CODE_CONFIGURE_NAK);
320  }
321  else
322  {
323  //If every configuration option received in the Configure-Request is
324  //recognizable and all values are acceptable, then the implementation
325  //must transmit a Configure-Ack
326  pppRcvConfigureReqEvent(context, &context->lcpFsm, &lcpCallbacks,
327  configureReqPacket, PPP_CODE_CONFIGURE_ACK);
328  }
329  }
330 
331  //Return status code
332  return error;
333 }
334 
335 
336 /**
337  * @brief Process Configure-Ack packet
338  * @param[in] context PPP context
339  * @param[in] configureAckPacket Packet received from the peer
340  * @return Error code
341  **/
342 
344  const PppConfigurePacket *configureAckPacket)
345 {
346  //Debug message
347  TRACE_INFO("\r\nLCP Receive-Configure-Ack event\r\n");
348 
349  //When a packet is received with an invalid Identifier field, the
350  //packet is silently discarded without affecting the automaton
351  if(configureAckPacket->identifier != context->lcpFsm.identifier)
352  return ERROR_WRONG_IDENTIFIER;
353 
354  //A valid Configure-Ack packet has been received from the peer
355  pppRcvConfigureAckEvent(context, &context->lcpFsm, &lcpCallbacks);
356 
357  //Successful processing
358  return NO_ERROR;
359 }
360 
361 
362 /**
363  * @brief Process Configure-Nak packet
364  * @param[in] context PPP context
365  * @param[in] configureNakPacket Packet received from the peer
366  * @return Error code
367  **/
368 
370  const PppConfigurePacket *configureNakPacket)
371 {
372  size_t length;
373  PppOption *option;
374 
375  //Debug message
376  TRACE_INFO("LCP Receive-Configure-Nak event\r\n");
377 
378  //When a packet is received with an invalid Identifier field, the
379  //packet is silently discarded without affecting the automaton
380  if(configureNakPacket->identifier != context->lcpFsm.identifier)
381  return ERROR_WRONG_IDENTIFIER;
382 
383  //Retrieve the length of the option list
384  length = ntohs(configureNakPacket->length) - sizeof(PppConfigurePacket);
385  //Point to the first option
386  option = (PppOption *) configureNakPacket->options;
387 
388  //Parse configuration options
389  while(length > 0)
390  {
391  //Check option length
392  if(option->length < sizeof(PppOption))
393  return ERROR_INVALID_LENGTH;
394  if(option->length > length)
395  return ERROR_INVALID_LENGTH;
396 
397  //Maximum-Receive-Unit option?
398  if(option->type == LCP_OPTION_MRU)
399  {
400  //Cast option
401  LcpMruOption *mruOption = (LcpMruOption *) option;
402 
403  //Check option length
404  if(mruOption->length != sizeof(LcpMruOption))
405  return ERROR_INVALID_LENGTH;
406 
407  //Save value
408  context->localConfig.mru = ntohs(mruOption->mru);
409  //Make sure the MRU is acceptable
410  context->localConfig.mru = MAX(context->localConfig.mru, PPP_MIN_MRU);
411  context->localConfig.mru = MIN(context->localConfig.mru, PPP_MAX_MRU);
412  }
413  else if(option->type == LCP_OPTION_ACCM)
414  {
415  //Cast option
416  LcpAccmOption *accmOption = (LcpAccmOption *) option;
417 
418  //Check option length
419  if(accmOption->length != sizeof(LcpAccmOption))
420  return ERROR_INVALID_LENGTH;
421 
422  //Save value
423  context->localConfig.accm = ntohl(accmOption->accm);
424  }
425  //Authentication-Protocol option?
426  else if(option->type == LCP_OPTION_AUTH_PROTOCOL)
427  {
428  //Cast option
429  LcpAuthProtocolOption *authProtocolOption = (LcpAuthProtocolOption *) option;
430 
431  //Check option length
432  if(authProtocolOption->length < sizeof(LcpAuthProtocolOption))
433  return ERROR_INVALID_LENGTH;
434 
435  //Check the value provided by the peer
436  if(ntohs(authProtocolOption->protocol) == PPP_PROTOCOL_PAP)
437  {
438 #if (PAP_SUPPORT == ENABLED)
439  //Manage authentication policy
440  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP)
441  {
442  //Select PAP authentication protocol
443  context->localConfig.authProtocol = PPP_PROTOCOL_PAP;
444  }
445 #endif
446  }
447  else if(ntohs(authProtocolOption->protocol) == PPP_PROTOCOL_CHAP)
448  {
449 #if (CHAP_SUPPORT == ENABLED)
450  //Make sure that the length of the option is correct
451  if(authProtocolOption->length > sizeof(LcpAuthProtocolOption))
452  {
453  //Check the algorithm identifier
454  if(authProtocolOption->data[0] == CHAP_ALGO_ID_CHAP_MD5)
455  {
456  //Manage authentication policy
457  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5)
458  {
459  //Select CHAP with MD5 authentication protocol
460  context->localConfig.authProtocol = PPP_PROTOCOL_CHAP;
461  context->localConfig.authAlgo = CHAP_ALGO_ID_CHAP_MD5;
462  }
463  }
464  }
465 #endif
466  }
467  }
468 
469  //Remaining bytes to process
470  length -= option->length;
471  //Jump to the next option
472  option = (PppOption *) ((uint8_t *) option + option->length);
473  }
474 
475  //A valid Configure-Nak or Configure-Reject packet has been received from the peer
476  pppRcvConfigureNakEvent(context, &context->lcpFsm, &lcpCallbacks);
477 
478  //Successful processing
479  return NO_ERROR;
480 }
481 
482 
483 /**
484  * @brief Process Configure-Reject packet
485  * @param[in] context PPP context
486  * @param[in] configureRejPacket Packet received from the peer
487  * @return Error code
488  **/
489 
491  const PppConfigurePacket *configureRejPacket)
492 {
493  size_t length;
494  PppOption *option;
495 
496  //Debug message
497  TRACE_INFO("\r\nLCP Receive-Configure-Reject event\r\n");
498 
499  //When a packet is received with an invalid Identifier field, the
500  //packet is silently discarded without affecting the automaton
501  if(configureRejPacket->identifier != context->lcpFsm.identifier)
502  return ERROR_WRONG_IDENTIFIER;
503 
504  //Retrieve the length of the option list
505  length = ntohs(configureRejPacket->length) - sizeof(PppConfigurePacket);
506  //Point to the first option
507  option = (PppOption *) configureRejPacket->options;
508 
509  //Parse configuration options
510  while(length > 0)
511  {
512  //Check option length
513  if(option->length < sizeof(PppOption))
514  return ERROR_INVALID_LENGTH;
515  if(option->length > length)
516  return ERROR_INVALID_LENGTH;
517 
518  //Maximum-Receive-Unit option?
519  if(option->type == LCP_OPTION_MRU)
520  {
521  //The option is not recognized by the peer
522  context->localConfig.mruRejected = TRUE;
523  //Restore default value
524  context->localConfig.mru = PPP_DEFAULT_MRU;
525  }
526  //Async-Control-Character-Map option?
527  else if(option->type == LCP_OPTION_ACCM)
528  {
529  //The option is not recognized by the peer
530  context->localConfig.accmRejected = TRUE;
531  //Restore default value
532  context->localConfig.accm = PPP_DEFAULT_ACCM;
533  }
534  //Authentication-Protocol option?
535  else if(option->type == LCP_OPTION_AUTH_PROTOCOL)
536  {
537  //This is an unrecoverable error that terminates the connection
538  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
539  //Exit immediately
540  return ERROR_FAILURE;
541  }
542  //Magic-Number option?
543  else if(option->type == LCP_OPTION_MAGIC_NUMBER)
544  {
545  //The option is not recognized by the peer
546  context->localConfig.magicNumberRejected = TRUE;
547  //Restore default value
548  context->localConfig.magicNumber = PPP_DEFAULT_MAGIC_NUMBER;
549  }
550  //Protocol-Field-Compression option?
551  else if(option->type == LCP_OPTION_PFC)
552  {
553  //The option is not recognized by the peer
554  context->localConfig.pfcRejected = TRUE;
555  //Restore default value
556  context->localConfig.pfc = FALSE;
557  }
558  //Address-and-Control-Field-Compression option?
559  else if(option->type == LCP_OPTION_ACFC)
560  {
561  //The option is not recognized by the peer
562  context->localConfig.acfcRejected = TRUE;
563  //Restore default value
564  context->localConfig.acfc = FALSE;
565  }
566 
567  //Remaining bytes to process
568  length -= option->length;
569  //Jump to the next option
570  option = (PppOption *) ((uint8_t *) option + option->length);
571  }
572 
573  //A valid Configure-Nak or Configure-Reject packet has been received from the peer
574  pppRcvConfigureNakEvent(context, &context->lcpFsm, &lcpCallbacks);
575 
576  //Successful processing
577  return NO_ERROR;
578 }
579 
580 
581 /**
582  * @brief Process Terminate-Request packet
583  * @param[in] context PPP context
584  * @param[in] terminateReqPacket Packet received from the peer
585  * @return Error code
586  **/
587 
589  const PppTerminatePacket *terminateReqPacket)
590 {
591  //Debug message
592  TRACE_INFO("\r\nLCP Receive-Terminate-Request event\r\n");
593 
594  //The Terminate-Request indicates the desire of the peer to close the connection
595  pppRcvTerminateReqEvent(context, &context->lcpFsm,
596  &lcpCallbacks, terminateReqPacket);
597 
598  //Successful processing
599  return NO_ERROR;
600 }
601 
602 
603 /**
604  * @brief Process Terminate-Ack packet
605  * @param[in] context PPP context
606  * @param[in] terminateAckPacket Packet received from the peer
607  * @return Error code
608  **/
609 
611  const PppTerminatePacket *terminateAckPacket)
612 {
613  //Debug message
614  TRACE_INFO("\r\nLCP Receive-Terminate-Ack event\r\n");
615 
616  //The Terminate-Ack packet is usually a response to a Terminate-Request
617  //packet. This packet may also indicate that the peer is in Closed or
618  //Stopped states, and serves to re-synchronize the link configuration
619  pppRcvTerminateAckEvent(context, &context->lcpFsm, &lcpCallbacks);
620 
621  //Successful processing
622  return NO_ERROR;
623 }
624 
625 
626 /**
627  * @brief Process Code-Reject packet
628  * @param[in] context PPP context
629  * @param[in] codeRejPacket Packet received from the peer
630  * @return Error code
631  **/
632 
634  const PppCodeRejPacket *codeRejPacket)
635 {
636  size_t length;
637  PppPacket *packet;
638 
639  //Debug message
640  TRACE_INFO("\r\nLCP Receive-Code-Reject event\r\n");
641 
642  //Point to the rejected packet
643  packet = (PppPacket *) codeRejPacket->rejectedPacket;
644  //Retrieve the length of the rejected packet
645  length = ntohs(codeRejPacket->length) - sizeof(PppCodeRejPacket);
646 
647  //Make sure the length of the rejected packet is valid
648  if(length < sizeof(PppPacket))
649  return ERROR_INVALID_LENGTH;
650 
651  //Check whether the rejected value is acceptable or catastrophic
652  if(packet->code < PPP_CODE_CONFIGURE_REQ ||
653  packet->code > PPP_CODE_DISCARD_REQ)
654  {
655  //The RXJ+ event arises when the rejected value is acceptable, such
656  //as a Code-Reject of an extended code, or a Protocol-Reject of a
657  //NCP. These are within the scope of normal operation
658  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
659  }
660  else
661  {
662  //The RXJ- event arises when the rejected value is catastrophic, such
663  //as a Code-Reject of Configure-Request! This event communicates an
664  //unrecoverable error that terminates the connection
665  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
666  }
667 
668  //Successful processing
669  return NO_ERROR;
670 }
671 
672 
673 /**
674  * @brief Process Protocol-Reject packet
675  * @param[in] context PPP context
676  * @param[in] protocolRejPacket Packet received from the peer
677  * @return Error code
678  **/
679 
681  const PppProtocolRejPacket *protocolRejPacket)
682 {
683  size_t length;
684  uint16_t protocol;
685 
686  //Debug message
687  TRACE_INFO("\r\nLCP Receive-Protocol-Reject event\r\n");
688 
689  //Retrieve the length of the packet
690  length = ntohs(protocolRejPacket->length);
691 
692  //Make sure the length of the Protocol-Reject packet is valid
693  if(length < sizeof(PppProtocolRejPacket))
694  return ERROR_INVALID_LENGTH;
695 
696  //Convert the Rejected-Protocol field to host byte order
697  protocol = ntohs(protocolRejPacket->rejectedProtocol);
698 
699  //Check Rejected-Protocol field value
700  switch(protocol)
701  {
702  //LCP protocol?
703  case PPP_PROTOCOL_LCP:
704  //The rejected value is catastrophic. This event communicates
705  //an unrecoverable error that terminates the connection
706  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, FALSE);
707  break;
708 
709  //IPv4 or IPCP protocol?
710  case PPP_PROTOCOL_IP:
711  case PPP_PROTOCOL_IPCP:
712  //The implementation must stop sending the offending packet type
713  context->ipRejected = TRUE;
714  //This is within the scope of normal operation...
715  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
716  break;
717 
718  //IPv6 or IPV6CP protocol?
719  case PPP_PROTOCOL_IPV6:
720  case PPP_PROTOCOL_IPV6CP:
721  //The implementation must stop sending the offending packet type
722  context->ipv6Rejected = TRUE;
723  //This is within the scope of normal operation...
724  pppRcvCodeRejEvent(context, &context->lcpFsm, &lcpCallbacks, TRUE);
725  break;
726 
727  //Unknown protocol?
728  default:
729  //Just for sanity's sake...
730  break;
731  }
732 
733  //Successful processing
734  return NO_ERROR;
735 }
736 
737 
738 /**
739  * @brief Process Echo-Request packet
740  * @param[in] context PPP context
741  * @param[in] echoReqPacket Packet received from the peer
742  * @return Error code
743  **/
744 
746  const PppEchoPacket *echoReqPacket)
747 {
748  //Debug message
749  TRACE_INFO("\r\nLCP Receive-Echo-Request event\r\n");
750 
751  //An Echo-Reply packet is transmitted to acknowledge the
752  //reception of the Echo-Request packet
753  pppRcvEchoReqEvent(context, &context->lcpFsm,
754  &lcpCallbacks, echoReqPacket);
755 
756  //Successful processing
757  return NO_ERROR;
758 }
759 
760 
761 /**
762  * @brief Process Echo-Reply packet
763  * @param[in] context PPP context
764  * @param[in] echoRepPacket Packet received from the peer
765  * @return Error code
766  **/
767 
769  const PppEchoPacket *echoRepPacket)
770 {
771  //Debug message
772  TRACE_INFO("\r\nLCP Receive-Echo-Reply event\r\n");
773 
774  //Successful processing
775  return NO_ERROR;
776 }
777 
778 
779 /**
780  * @brief Process Discard-Request packet
781  * @param[in] context PPP context
782  * @param[in] discardReqPacket Packet received from the peer
783  * @return Error code
784  **/
785 
787  const PppDiscardReqPacket *discardReqPacket)
788 {
789  //Debug message
790  TRACE_INFO("\r\nLCP Receive-Discard-Request event\r\n");
791 
792  //The receiver must silently discard any Discard-Request that it receives
793  return NO_ERROR;
794 }
795 
796 
797 /**
798  * @brief Process packet with unknown code
799  * @param[in] context PPP context
800  * @param[in] packet Un-interpretable packet received from the peer
801  * @return Error code
802  **/
803 
805  const PppPacket *packet)
806 {
807  //Debug message
808  TRACE_INFO("\r\nLCP Receive-Unknown-Code event\r\n");
809 
810  //This event occurs when an un-interpretable packet is received from
811  //the peer. A Code-Reject packet is sent in response
812  pppRcvUnknownCodeEvent(context, &context->lcpFsm, &lcpCallbacks, packet);
813 
814  //Successful processing
815  return NO_ERROR;
816 }
817 
818 
819 /**
820  * @brief Process PPP frame with unknown protocol
821  * @param[in] context PPP context
822  * @param[in] protocol Rejected protocol
823  * @param[in] information Rejected information
824  * @param[in] length Length of the rejected information
825  * @return Error code
826  **/
827 
829  uint16_t protocol, const uint8_t *information, size_t length)
830 {
831  //Debug message
832  TRACE_INFO("\r\nLCP Receive-Unknown-Protocol event\r\n");
833 
834  //The peer is attempting to use a protocol which is unsupported
835  if(context->lcpFsm.state == PPP_STATE_9_OPENED)
836  {
837  //The Identifier field must be changed for each Protocol-Reject sent
838  context->lcpFsm.identifier++;
839 
840  //If the LCP automaton is in the Opened state, then this must be
841  //reported back to the peer by transmitting a Protocol-Reject
842  pppSendProtocolRej(context, context->lcpFsm.identifier,
843  protocol, information, length);
844  }
845 
846  //Successful processing
847  return NO_ERROR;
848 }
849 
850 
851 /**
852  * @brief This-Layer-Up callback function
853  * @param[in] context PPP context
854  **/
855 
857 {
858  //Debug message
859  TRACE_INFO("LCP This-Layer-Up callback\r\n");
860 
861  //Check whether the other end of the PPP link is being authenticated
862  if(context->localConfig.authProtocol != 0)
863  context->localAuthDone = FALSE;
864  else
865  context->localAuthDone = TRUE;
866 
867  //Check whether the other end of the PPP link is the authenticator
868  if(context->peerConfig.authProtocol != 0)
869  context->peerAuthDone = FALSE;
870  else
871  context->peerAuthDone = TRUE;
872 
873 #if (PAP_SUPPORT == ENABLED)
874  //PAP authentication required?
875  if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP ||
876  context->peerConfig.authProtocol == PPP_PROTOCOL_PAP)
877  {
878  //Advance to the Authentication phase
879  context->pppPhase = PPP_PHASE_AUTHENTICATE;
880  //Start PAP authentication process
881  papStartAuth(context);
882  }
883 #endif
884 #if (CHAP_SUPPORT == ENABLED)
885  //CHAP authentication required?
886  if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP ||
887  context->peerConfig.authProtocol == PPP_PROTOCOL_CHAP)
888  {
889  //Advance to the Authentication phase
890  context->pppPhase = PPP_PHASE_AUTHENTICATE;
891  //Start CHAP authentication process
892  chapStartAuth(context);
893  }
894 #endif
895 
896  //Check whether PPP authentication is complete
897  if(context->localAuthDone && context->peerAuthDone)
898  {
899  //Advance to the Network phase
900  context->pppPhase = PPP_PHASE_NETWORK;
901 
902 #if (IPV4_SUPPORT == ENABLED)
903  //IPCP Open event
904  ipcpOpen(context);
905 #endif
906 #if (IPV6_SUPPORT == ENABLED)
907  //IPV6CP Open event
908  ipv6cpOpen(context);
909 #endif
910  }
911 }
912 
913 
914 /**
915  * @brief This-Layer-Down callback function
916  * @param[in] context PPP context
917  **/
918 
920 {
921  //Debug message
922  TRACE_INFO("LCP This-Layer-Down callback\r\n");
923 
924  //Advance to the Terminate phase
925  context->pppPhase = PPP_PHASE_TERMINATE;
926 
927 #if (IPV4_SUPPORT == ENABLED)
928  //IPCP Close event
929  ipcpClose(context);
930 #endif
931 #if (IPV6_SUPPORT == ENABLED)
932  //IPV6CP Close event
933  ipv6cpClose(context);
934 #endif
935 
936 #if (PAP_SUPPORT == ENABLED)
937  //Abort PAP authentication process
938  papAbortAuth(context);
939 #endif
940 
941 #if (CHAP_SUPPORT == ENABLED)
942  //Abort CHAP authentication process
943  chapAbortAuth(context);
944 #endif
945 }
946 
947 
948 /**
949  * @brief This-Layer-Started callback function
950  * @param[in] context PPP context
951  **/
952 
954 {
955  //Debug message
956  TRACE_INFO("LCP This-Layer-Started callback\r\n");
957 }
958 
959 
960 /**
961  * @brief This-Layer-Finished callback function
962  * @param[in] context PPP context
963  **/
964 
966 {
967  //Debug message
968  TRACE_INFO("LCP This-Layer-Finished callback\r\n");
969 
970  //The link is no longer available for traffic
971  pppCloseEvent(context, &context->lcpFsm, &lcpCallbacks);
972  //The lower layer is no longer ready to carry packets
973  pppDownEvent(context, &context->lcpFsm, &lcpCallbacks);
974 
975  //Advance to the Link Dead phase
976  context->pppPhase = PPP_PHASE_DEAD;
977 }
978 
979 
980 /**
981  * @brief Initialize-Restart-Count callback function
982  * @param[in] context PPP context
983  * @param[in] value Restart counter value
984  **/
985 
987 {
988  //Debug message
989  TRACE_INFO("LCP Initialize-Restart-Count callback\r\n");
990 
991  //Initialize restart counter
992  context->lcpFsm.restartCounter = value;
993 }
994 
995 
996 /**
997  * @brief Zero-Restart-Count callback function
998  * @param[in] context PPP context
999  **/
1000 
1002 {
1003  //Debug message
1004  TRACE_INFO("LCP Zero-Restart-Count callback\r\n");
1005 
1006  //Zero restart counter
1007  context->lcpFsm.restartCounter = 0;
1008 
1009  //The receiver of a Terminate-Request should wait for the peer to
1010  //disconnect, and must not disconnect until at least one Restart
1011  //time has passed after sending a Terminate-Ack
1012  context->lcpFsm.timestamp = osGetSystemTime();
1013 }
1014 
1015 
1016 /**
1017  * @brief Send-Configure-Request callback function
1018  * @param[in] context PPP context
1019  * @return Error code
1020  **/
1021 
1023 {
1024  error_t error;
1025  size_t length;
1026  size_t offset;
1027  NetBuffer *buffer;
1028  PppConfigurePacket *configureReqPacket;
1029 
1030  //Debug message
1031  TRACE_INFO("LCP Send-Configure-Request callback\r\n");
1032 
1033  //Allocate a buffer memory to hold the Configure-Request packet
1034  buffer = pppAllocBuffer(PPP_MAX_CONF_REQ_SIZE, &offset);
1035  //Failed to allocate memory?
1036  if(buffer == NULL)
1037  return ERROR_OUT_OF_MEMORY;
1038 
1039  //Point to the Configure-Request packet
1040  configureReqPacket = netBufferAt(buffer, offset);
1041 
1042  //Format packet header
1043  configureReqPacket->code = PPP_CODE_CONFIGURE_REQ;
1044  configureReqPacket->identifier = ++context->lcpFsm.identifier;
1045  configureReqPacket->length = sizeof(PppConfigurePacket);
1046 
1047  //Make sure the Maximum-Receive-Unit option has not been
1048  //previously rejected
1049  if(!context->localConfig.mruRejected)
1050  {
1051  //Convert MRU to network byte order
1052  uint16_t value = htons(context->localConfig.mru);
1053  //Add option
1054  pppAddOption(configureReqPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t));
1055  }
1056 
1057  //Make sure the Async-Control-Character-Map option has not been
1058  //previously rejected
1059  if(!context->localConfig.accmRejected)
1060  {
1061  //Convert ACCM to network byte order
1062  uint32_t value = htonl(context->localConfig.accm);
1063  //Add option
1064  pppAddOption(configureReqPacket, LCP_OPTION_ACCM, &value, sizeof(uint32_t));
1065  }
1066 
1067  //Make sure the Authentication-Protocol option has not been
1068  //previously rejected
1069  if(!context->localConfig.authProtocolRejected)
1070  {
1071  uint8_t value[3];
1072 
1073  //PAP authentication protocol?
1074  if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP)
1075  {
1076  //Format Authentication-Protocol option
1077  value[0] = MSB(PPP_PROTOCOL_PAP);
1078  value[1] = LSB(PPP_PROTOCOL_PAP);
1079 
1080  //Add option
1081  pppAddOption(configureReqPacket, LCP_OPTION_AUTH_PROTOCOL, &value, 2);
1082  }
1083  //CHAP authentication protocol?
1084  else if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP)
1085  {
1086  //Format Authentication-Protocol option
1087  value[0] = MSB(PPP_PROTOCOL_CHAP);
1088  value[1] = LSB(PPP_PROTOCOL_CHAP);
1089  value[2] = context->localConfig.authAlgo;
1090 
1091  //Add option
1092  pppAddOption(configureReqPacket, LCP_OPTION_AUTH_PROTOCOL, &value, 3);
1093  }
1094  }
1095 
1096  //Make sure the Protocol-Field-Compression option has not been
1097  //previously rejected
1098  if(!context->localConfig.pfcRejected)
1099  {
1100  //Check whether compression of the Protocol field is supported
1101  if(context->localConfig.pfc)
1102  {
1103  //Add option
1104  pppAddOption(configureReqPacket, LCP_OPTION_PFC, NULL, 0);
1105  }
1106  }
1107 
1108  //Make sure the Address-and-Control-Field-Compression option has not been
1109  //previously rejected
1110  if(!context->localConfig.acfcRejected)
1111  {
1112  //Check whether compression of the Address and Control fields is supported
1113  if(context->localConfig.acfc)
1114  {
1115  //Add option
1116  pppAddOption(configureReqPacket, LCP_OPTION_ACFC, NULL, 0);
1117  }
1118  }
1119 
1120  //Save packet length
1121  length = configureReqPacket->length;
1122  //Convert length field to network byte order
1123  configureReqPacket->length = htons(length);
1124 
1125  //Adjust the length of the multi-part buffer
1126  netBufferSetLength(buffer, offset + length);
1127 
1128  //Debug message
1129  TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
1130  //Dump packet contents for debugging purpose
1131  pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_LCP);
1132 
1133  //Send PPP frame
1134  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_LCP);
1135 
1136  //The restart counter is decremented each time a Configure-Request is sent
1137  if(context->lcpFsm.restartCounter > 0)
1138  context->lcpFsm.restartCounter--;
1139 
1140  //Save the time at which the packet was sent
1141  context->lcpFsm.timestamp = osGetSystemTime();
1142 
1143  //Free previously allocated memory block
1144  netBufferFree(buffer);
1145  //Return status code
1146  return error;
1147 }
1148 
1149 
1150 /**
1151  * @brief Send-Configure-Ack callback function
1152  * @param[in] context PPP context
1153  * @param[in] configureReqPacket Configure-Request packet received from the peer
1154  * @return Error code
1155  **/
1156 
1158  const PppConfigurePacket *configureReqPacket)
1159 {
1160  //Debug message
1161  TRACE_INFO("LCP Send-Configure-Ack callback\r\n");
1162 
1163  //Send Configure-Ack packet
1164  return pppSendConfigureAckNak(context, configureReqPacket,
1166 }
1167 
1168 
1169 /**
1170  * @brief Send-Configure-Nak callback function
1171  * @param[in] context PPP context
1172  * @param[in] configureReqPacket Configure-Request packet received from the peer
1173  * @return Error code
1174  **/
1175 
1177  const PppConfigurePacket *configureReqPacket)
1178 {
1179  //Debug message
1180  TRACE_INFO("LCP Send-Configure-Nak callback\r\n");
1181 
1182  //Send Configure-Nak packet
1183  return pppSendConfigureAckNak(context, configureReqPacket,
1185 }
1186 
1187 
1188 /**
1189  * @brief Send-Configure-Reject callback function
1190  * @param[in] context PPP context
1191  * @param[in] configureReqPacket Configure-Request packet received from the peer
1192  * @return Error code
1193  **/
1194 
1196  const PppConfigurePacket *configureReqPacket)
1197 {
1198  //Debug message
1199  TRACE_INFO("LCP Send-Configure-Reject callback\r\n");
1200 
1201  //Send Configure-Reject packet
1202  return pppSendConfigureAckNak(context, configureReqPacket,
1204 }
1205 
1206 
1207 /**
1208  * @brief Send-Terminate-Request callback function
1209  * @param[in] context PPP context
1210  * @return Error code
1211  **/
1212 
1214 {
1215  error_t error;
1216 
1217  //Debug message
1218  TRACE_INFO("LCP Send-Terminate-Request callback\r\n");
1219 
1220  //On transmission, the Identifier field must be changed
1221  context->lcpFsm.identifier++;
1222 
1223  //Send Terminate-Request packet
1224  error = pppSendTerminateReq(context, context->lcpFsm.identifier, PPP_PROTOCOL_LCP);
1225 
1226  //The restart counter is decremented each time a Terminate-Request is sent
1227  if(context->lcpFsm.restartCounter > 0)
1228  context->lcpFsm.restartCounter--;
1229 
1230  //Save the time at which the packet was sent
1231  context->lcpFsm.timestamp = osGetSystemTime();
1232 
1233  //Return status code
1234  return error;
1235 }
1236 
1237 
1238 /**
1239  * @brief Send-Terminate-Ack callback function
1240  * @param[in] context PPP context
1241  * @param[in] terminateReqPacket Terminate-Request packet received from the peer
1242  * @return Error code
1243  **/
1244 
1246  const PppTerminatePacket *terminateReqPacket)
1247 {
1248  uint8_t identifier;
1249 
1250  //Debug message
1251  TRACE_INFO("LCP Send-Terminate-Ack callback\r\n");
1252 
1253  //Check whether this Terminate-Ack acknowledges the reception of a
1254  //Terminate-Request packet
1255  if(terminateReqPacket != NULL)
1256  {
1257  //The Identifier field of the Terminate-Request is copied into the
1258  //Identifier field of the Terminate-Ack packet
1259  identifier = terminateReqPacket->identifier;
1260  }
1261  else
1262  {
1263  //This Terminate-Ack packet serves to synchronize the automatons
1264  identifier = ++context->lcpFsm.identifier;
1265  }
1266 
1267  //Send Terminate-Ack packet
1269 }
1270 
1271 
1272 /**
1273  * @brief Send-Code-Reject callback function
1274  * @param[in] context PPP context
1275  * @param[in] packet Un-interpretable packet received from the peer
1276  * @return Error code
1277  **/
1278 
1279 error_t lcpSendCodeRej(PppContext *context, const PppPacket *packet)
1280 {
1281  //Debug message
1282  TRACE_INFO("LCP Send-Code-Reject callback\r\n");
1283 
1284  //The Identifier field must be changed for each Code-Reject sent
1285  context->lcpFsm.identifier++;
1286 
1287  //Send Code-Reject packet
1288  return pppSendCodeRej(context, packet, context->lcpFsm.identifier, PPP_PROTOCOL_LCP);
1289 }
1290 
1291 
1292 /**
1293  * @brief Send-Echo-Reply callback function
1294  * @param[in] context PPP context
1295  * @param[in] echoReqPacket Echo-Request packet received from the peer
1296  * @return Error code
1297  **/
1298 
1299 error_t lcpSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket)
1300 {
1301  //Debug message
1302  TRACE_INFO("LCP Send-Echo-Reply callback\r\n");
1303 
1304  //Send Echo-Reply packet
1305  return pppSendEchoRep(context, echoReqPacket, PPP_PROTOCOL_LCP);
1306 }
1307 
1308 
1309 /**
1310  * @brief Parse LCP configuration option
1311  * @param[in] context PPP context
1312  * @param[in] option Option to be checked
1313  * @param[in] inPacketLen Remaining bytes to process in the incoming packet
1314  * @param[out] outPacket Pointer to the Configure-Ack, Nak or Reject packet
1315  * @return Error code
1316  **/
1317 
1319  size_t inPacketLen, PppConfigurePacket *outPacket)
1320 {
1321  error_t error;
1322 
1323  //Malformed LCP packet?
1324  if(inPacketLen < sizeof(PppOption))
1325  return ERROR_INVALID_LENGTH;
1326 
1327  //Check option length
1328  if(option->length < sizeof(PppOption))
1329  return ERROR_INVALID_LENGTH;
1330  if(option->length > inPacketLen)
1331  return ERROR_INVALID_LENGTH;
1332 
1333  //Check option type
1334  switch(option->type)
1335  {
1336  case LCP_OPTION_MRU:
1337  //Check Maximum-Receive-Unit option
1338  error = lcpParseMruOption(context, (LcpMruOption *) option, outPacket);
1339  break;
1340  case LCP_OPTION_ACCM:
1341  //Check Async-Control-Character-Map option
1342  error = lcpParseAccmOption(context, (LcpAccmOption *) option, outPacket);
1343  break;
1345  //Check Authentication-Protocol option
1346  error = lcpParseAuthProtocolOption(context, (LcpAuthProtocolOption *) option, outPacket);
1347  break;
1349  //Check Magic-Number option
1350  error = lcpParseMagicNumberOption(context, (LcpMagicNumberOption *) option, outPacket);
1351  break;
1352  case LCP_OPTION_PFC:
1353  //Check Protocol-Field-Compression option
1354  error = lcpParsePfcOption(context, (LcpPfcOption *) option, outPacket);
1355  break;
1356  case LCP_OPTION_ACFC:
1357  //Check Address-and-Control-Field-Compression option
1358  error = lcpParseAcfcOption(context, (LcpAcfcOption *) option, outPacket);
1359  break;
1360  default:
1361  //If some configuration options received in the Configure-Request are not
1362  //recognizable or not acceptable for negotiation, then the implementation
1363  //must transmit a Configure-Reject
1364  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_REJ)
1365  {
1366  //The options field of the Configure-Reject packet is filled
1367  //with the unrecognized options from the Configure-Request
1368  pppAddOption(outPacket, option->type, option->data,
1369  option->length - sizeof(PppOption));
1370  }
1371 
1372  //The option is not acceptable for negotiation
1373  error = ERROR_INVALID_TYPE;
1374  break;
1375  }
1376 
1377  //Return status code
1378  return error;
1379 }
1380 
1381 
1382 /**
1383  * @brief Parse Maximum-Receive-Unit option
1384  * @param[in] context PPP context
1385  * @param[in] option Option to be checked
1386  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1387  * @return Error code
1388  **/
1389 
1391  LcpMruOption *option, PppConfigurePacket *outPacket)
1392 {
1393  error_t error;
1394  uint16_t value;
1395 
1396  //Check length field
1397  if(option->length == sizeof(LcpMruOption))
1398  {
1399  //Check whether the option value is acceptable
1400  if(ntohs(option->mru) >= PPP_MIN_MRU)
1401  {
1402  //If every configuration option received in the Configure-Request is
1403  //recognizable and all values are acceptable, then the implementation
1404  //must transmit a Configure-Ack
1405  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1406  {
1407  //Save Maximum-Receive-Unit option
1408  context->peerConfig.mru = ntohl(option->mru);
1409 
1410  //The options field of the Configure-Ack packet contains the
1411  //configuration options that the sender is acknowledging
1412  pppAddOption(outPacket, LCP_OPTION_MRU, (void *) &option->mru,
1413  option->length - sizeof(PppOption));
1414  }
1415 
1416  //The value is acceptable
1417  error = NO_ERROR;
1418  }
1419  else
1420  {
1421  //If all configuration options are recognizable, but some values are not
1422  //acceptable, then the implementation must transmit a Configure-Nak
1423  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
1424  {
1425  //Use default value
1427 
1428  //The option must be modified to a value acceptable to the
1429  //Configure-Nak sender
1430  pppAddOption(outPacket, LCP_OPTION_MRU, &value, sizeof(uint16_t));
1431  }
1432 
1433  //The value is not acceptable
1434  error = ERROR_INVALID_VALUE;
1435  }
1436  }
1437  else
1438  {
1439  //Invalid length field
1440  error = ERROR_INVALID_LENGTH;
1441  }
1442 
1443  //Return status code
1444  return error;
1445 }
1446 
1447 
1448 /**
1449  * @brief Parse Async-Control-Character-Map option
1450  * @param[in] context PPP context
1451  * @param[in] option Option to be checked
1452  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1453  * @return Error code
1454  **/
1455 
1457  LcpAccmOption *option, PppConfigurePacket *outPacket)
1458 {
1459  error_t error;
1460 
1461  //Check length field
1462  if(option->length == sizeof(LcpAccmOption))
1463  {
1464  //If every configuration option received in the Configure-Request is
1465  //recognizable and all values are acceptable, then the implementation
1466  //must transmit a Configure-Ack
1467  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1468  {
1469  //Save Async-Control-Character-Map option
1470  context->peerConfig.accm = ntohl(option->accm);
1471 
1472  //The options field of the Configure-Ack packet contains the
1473  //configuration options that the sender is acknowledging
1474  pppAddOption(outPacket, LCP_OPTION_ACCM, (void *) &option->accm,
1475  option->length - sizeof(PppOption));
1476  }
1477 
1478  //The value is acceptable
1479  error = NO_ERROR;
1480  }
1481  else
1482  {
1483  //Invalid length field
1484  error = ERROR_INVALID_LENGTH;
1485  }
1486 
1487  //Return status code
1488  return error;
1489 }
1490 
1491 
1492 /**
1493  * @brief Parse Authentication-Protocol option
1494  * @param[in] context PPP context
1495  * @param[in] option Option to be checked
1496  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1497  * @return Error code
1498  **/
1499 
1501  LcpAuthProtocolOption *option, PppConfigurePacket *outPacket)
1502 {
1503  error_t error;
1504  uint8_t value[3];
1505 
1506  //Assume an error condition...
1507  error = ERROR_INVALID_LENGTH;
1508 
1509  //Check the length of the option
1510  if(option->length >= sizeof(LcpAuthProtocolOption))
1511  {
1512  //The Authentication-Protocol option for PAP must be exactly 4 bytes
1513  if(ntohs(option->protocol) == PPP_PROTOCOL_PAP)
1514  {
1515  if(option->length == 4)
1516  error = NO_ERROR;
1517  }
1518  //The Authentication-Protocol option for CHAP must be exactly 5 bytes
1519  else if(ntohs(option->protocol) == PPP_PROTOCOL_CHAP)
1520  {
1521  if(option->length == 5)
1522  error = NO_ERROR;
1523  }
1524  }
1525 
1526  //Make sure the length field is valid
1527  if(!error)
1528  {
1529  //PAP authentication protocol?
1530  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP &&
1531  ntohs(option->protocol) == PPP_PROTOCOL_PAP)
1532  {
1533  //If every configuration option received in the Configure-Request is
1534  //recognizable and all values are acceptable, then the implementation
1535  //must transmit a Configure-Ack
1536  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1537  {
1538  //Save the authentication protocol to be used
1539  context->peerConfig.authProtocol = PPP_PROTOCOL_PAP;
1540 
1541  //The options field of the Configure-Ack packet contains the
1542  //configuration options that the sender is acknowledging
1543  pppAddOption(outPacket, option->type, (void *) &option->protocol,
1544  option->length - sizeof(PppOption));
1545  }
1546 
1547  //The value is acceptable
1548  error = NO_ERROR;
1549  }
1550  //CHAP with MD5 authentication protocol?
1551  else if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5 &&
1552  ntohs(option->protocol) == PPP_PROTOCOL_CHAP &&
1553  option->data[0] == CHAP_ALGO_ID_CHAP_MD5)
1554  {
1555  //If every configuration option received in the Configure-Request is
1556  //recognizable and all values are acceptable, then the implementation
1557  //must transmit a Configure-Ack
1558  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1559  {
1560  //Save the authentication protocol to be used
1561  context->peerConfig.authProtocol = PPP_PROTOCOL_CHAP;
1562  context->peerConfig.authAlgo = CHAP_ALGO_ID_CHAP_MD5;
1563 
1564  //The options field of the Configure-Ack packet contains the
1565  //configuration options that the sender is acknowledging
1566  pppAddOption(outPacket, option->type, (void *) &option->protocol,
1567  option->length - sizeof(PppOption));
1568  }
1569 
1570  //The value is acceptable
1571  error = NO_ERROR;
1572  }
1573  else
1574  {
1575  //PAP authentication protocol allowed?
1576  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP)
1577  {
1578  //If all configuration options are recognizable, but some values are not
1579  //acceptable, then the implementation must transmit a Configure-Nak
1580  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
1581  {
1582  //Format Authentication-Protocol option
1583  value[0] = MSB(PPP_PROTOCOL_PAP);
1584  value[1] = LSB(PPP_PROTOCOL_PAP);
1585 
1586  //The option must be modified to a value acceptable to the
1587  //Configure-Nak sender
1589  }
1590 
1591  //The value is not acceptable
1592  error = ERROR_INVALID_VALUE;
1593  }
1594  //CHAP with MD5 authentication protocol allowed?
1595  else if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5)
1596  {
1597  //If all configuration options are recognizable, but some values are not
1598  //acceptable, then the implementation must transmit a Configure-Nak
1599  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
1600  {
1601  //Format Authentication-Protocol option
1602  value[0] = MSB(PPP_PROTOCOL_CHAP);
1603  value[1] = LSB(PPP_PROTOCOL_CHAP);
1605 
1606  //The option must be modified to a value acceptable to the
1607  //Configure-Nak sender
1609  }
1610 
1611  //The value is not acceptable
1612  error = ERROR_INVALID_VALUE;
1613  }
1614  else
1615  {
1616  //If some configuration options received in the Configure-Request are not
1617  //recognizable or not acceptable for negotiation, then the implementation
1618  //must transmit a Configure-Reject
1619  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_REJ)
1620  {
1621  //The options field of the Configure-Reject packet is filled
1622  //with the unrecognized options from the Configure-Request
1623  pppAddOption(outPacket, option->type, (void *) &option->protocol,
1624  option->length - sizeof(PppOption));
1625  }
1626 
1627  //The option is not acceptable for negotiation
1628  error = ERROR_INVALID_TYPE;
1629  }
1630  }
1631  }
1632 
1633  //Return status code
1634  return error;
1635 }
1636 
1637 
1638 /**
1639  * @brief Parse Magic-Number option
1640  * @param[in] context PPP context
1641  * @param[in] option Option to be checked
1642  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1643  * @return Error code
1644  **/
1645 
1647  LcpMagicNumberOption *option, PppConfigurePacket *outPacket)
1648 {
1649  error_t error;
1650 
1651  //Check length field
1652  if(option->length == sizeof(LcpMagicNumberOption))
1653  {
1654  //If every configuration option received in the Configure-Request is
1655  //recognizable and all values are acceptable, then the implementation
1656  //must transmit a Configure-Ack
1657  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1658  {
1659  //Save Magic-Number option
1660  context->peerConfig.magicNumber = ntohl(option->magicNumber);
1661 
1662  //The options field of the Configure-Ack packet contains the
1663  //configuration options that the sender is acknowledging
1664  pppAddOption(outPacket, LCP_OPTION_MAGIC_NUMBER, (void *) &option->magicNumber,
1665  option->length - sizeof(PppOption));
1666  }
1667 
1668  //The value is acceptable
1669  error = NO_ERROR;
1670  }
1671  else
1672  {
1673  //Invalid length field
1674  error = ERROR_INVALID_LENGTH;
1675  }
1676 
1677  //Return status code
1678  return error;
1679 }
1680 
1681 
1682 /**
1683  * @brief Parse Protocol-Field-Compression option
1684  * @param[in] context PPP context
1685  * @param[in] option Option to be checked
1686  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1687  * @return Error code
1688  **/
1689 
1691  LcpPfcOption *option, PppConfigurePacket *outPacket)
1692 {
1693  error_t error;
1694 
1695  //Check length field
1696  if(option->length == sizeof(LcpPfcOption))
1697  {
1698  //If every configuration option received in the Configure-Request is
1699  //recognizable and all values are acceptable, then the implementation
1700  //must transmit a Configure-Ack
1701  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1702  {
1703  //Save Protocol-Field-Compression option
1704  context->peerConfig.pfc = TRUE;
1705 
1706  //The options field of the Configure-Ack packet contains the
1707  //configuration options that the sender is acknowledging
1708  pppAddOption(outPacket, LCP_OPTION_PFC, NULL, 0);
1709  }
1710 
1711  //The value is acceptable
1712  error = NO_ERROR;
1713  }
1714  else
1715  {
1716  //Invalid length field
1717  error = ERROR_INVALID_LENGTH;
1718  }
1719 
1720  //Return status code
1721  return error;
1722 }
1723 
1724 
1725 /**
1726  * @brief Parse Address-and-Control-Field-Compression option
1727  * @param[in] context PPP context
1728  * @param[in] option Option to be checked
1729  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
1730  * @return Error code
1731  **/
1732 
1734  LcpAcfcOption *option, PppConfigurePacket *outPacket)
1735 {
1736  error_t error;
1737 
1738  //Check length field
1739  if(option->length == sizeof(LcpAcfcOption))
1740  {
1741  //If every configuration option received in the Configure-Request is
1742  //recognizable and all values are acceptable, then the implementation
1743  //must transmit a Configure-Ack
1744  if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
1745  {
1746  //Save Address-and-Control-Field-Compression option
1747  context->peerConfig.acfc = TRUE;
1748 
1749  //The options field of the Configure-Ack packet contains the
1750  //configuration options that the sender is acknowledging
1751  pppAddOption(outPacket, LCP_OPTION_ACFC, NULL, 0);
1752  }
1753 
1754  //The value is acceptable
1755  error = NO_ERROR;
1756  }
1757  else
1758  {
1759  //Invalid length field
1760  error = ERROR_INVALID_LENGTH;
1761  }
1762 
1763  //Return status code
1764  return error;
1765 }
1766 
1767 #endif
__start_packed struct @289 PppTerminatePacket
Terminate-Request and Terminate-Ack packet.
error_t pppSendProtocolRej(PppContext *context, uint8_t identifier, uint16_t protocol, const uint8_t *information, size_t length)
Send Protocol-Reject packet.
Definition: ppp_misc.c:323
Link termination phase.
Definition: ppp.h:168
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
Authentication phase.
Definition: ppp.h:166
Terminate-Request.
Definition: ppp.h:218
error_t lcpProcessConfigureNak(PppContext *context, const PppConfigurePacket *configureNakPacket)
Process Configure-Nak packet.
Definition: lcp.c:369
#define PPP_MAX_CONF_REQ_SIZE
Definition: ppp.h:138
error_t ipcpClose(PppContext *context)
IPCP Close event.
Definition: ipcp.c:95
error_t lcpSendTerminateReq(PppContext *context)
Send-Terminate-Request callback function.
Definition: lcp.c:1213
void pppRcvTerminateAckEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Terminate-Ack event.
Definition: ppp_fsm.c:695
systime_t osGetSystemTime(void)
Retrieve system time.
Code-Reject.
Definition: ppp.h:220
#define MSB(x)
Definition: os_port.h:56
uint32_t time
#define PPP_DEFAULT_MAGIC_NUMBER
Definition: ppp.h:130
IPV6CP (PPP IPv6 Control Protocol)
Data logging functions for debugging purpose (PPP)
TCP/IP stack core.
error_t lcpSendConfigureRej(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Reject callback function.
Definition: lcp.c:1195
Protocol-Reject.
Definition: ppp.h:221
PPP miscellaneous functions.
error_t papStartAuth(PppContext *context)
Start PAP authentication.
Definition: pap.c:51
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:280
error_t lcpProcessEchoRep(PppContext *context, const PppEchoPacket *echoRepPacket)
Process Echo-Reply packet.
Definition: lcp.c:768
error_t ipv6cpClose(PppContext *context)
IPV6CP Close event.
Definition: ipv6cp.c:96
Debugging facilities.
__start_packed struct @292 PppEchoPacket
Echo-Request and Echo-Reply packet.
PAP (Password Authentication Protocol)
Generic error code.
Definition: error.h:43
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:318
error_t lcpSendConfigureAck(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Ack callback function.
Definition: lcp.c:1157
error_t lcpSendConfigureNak(PppContext *context, const PppConfigurePacket *configureReqPacket)
Send-Configure-Nak callback function.
Definition: lcp.c:1176
__start_packed struct @290 PppCodeRejPacket
Code-Reject packet.
Network-layer protocol phase.
Definition: ppp.h:167
IPv6 Control Protocol.
Definition: ppp.h:200
error_t lcpClose(PppContext *context)
LCP Close event.
Definition: lcp.c:101
error_t chapAbortAuth(PppContext *context)
Abort CHAP authentication.
Definition: chap.c:89
Terminate-Ack.
Definition: ppp.h:219
__start_packed struct @280 LcpAuthProtocolOption
Authentication-Protocol option.
error_t lcpSendConfigureReq(PppContext *context)
Send-Configure-Request callback function.
Definition: lcp.c:1022
error_t lcpParseMagicNumberOption(PppContext *context, LcpMagicNumberOption *option, PppConfigurePacket *outPacket)
Parse Magic-Number option.
Definition: lcp.c:1646
error_t pppSendCodeRej(PppContext *context, const PppPacket *packet, uint8_t identifier, PppProtocol protocol)
Send Code-Reject packet.
Definition: ppp_misc.c:263
void lcpThisLayerUp(PppContext *context)
This-Layer-Up callback function.
Definition: lcp.c:856
#define htons(value)
Definition: cpu_endian.h:390
PPP FSM actions.
Definition: ppp_fsm.h:150
Discard-Request.
Definition: ppp.h:224
error_t lcpParsePfcOption(PppContext *context, LcpPfcOption *option, PppConfigurePacket *outPacket)
Parse Protocol-Field-Compression option.
Definition: lcp.c:1690
#define LSB(x)
Definition: os_port.h:52
void pppRcvTerminateReqEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, const PppTerminatePacket *terminateReqPacket)
Process Receive-Terminate-Req event.
Definition: ppp_fsm.c:646
error_t lcpProcessDiscardReq(PppContext *context, const PppDiscardReqPacket *discardReqPacket)
Process Discard-Request packet.
Definition: lcp.c:786
#define PppPacket
Definition: ppp.h:35
void lcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming LCP packet.
Definition: lcp.c:153
__start_packed struct @293 PppDiscardReqPacket
PPP Discard-Request packet.
error_t lcpSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket)
Send-Echo-Reply callback function.
Definition: lcp.c:1299
IP Control Protocol.
Definition: ppp.h:199
error_t ipcpOpen(PppContext *context)
IPCP Open event.
Definition: ipcp.c:74
error_t lcpOpen(PppContext *context)
LCP Open event.
Definition: lcp.c:77
#define MAX(a, b)
Definition: os_port.h:64
#define TRUE
Definition: os_port.h:48
__start_packed struct @294 PppOption
LCP/NCP option.
Configure-Request.
Definition: ppp.h:214
void pppUpEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Up event.
Definition: ppp_fsm.c:48
Async-Control-Character-Map.
Definition: lcp.h:49
error_t lcpProcessUnknownProtocol(PppContext *context, uint16_t protocol, const uint8_t *information, size_t length)
Process PPP frame with unknown protocol.
Definition: lcp.c:828
Password Authentication Protocol.
Definition: ppp.h:202
#define PPP_MAX_MRU
Definition: ppp.h:135
#define ntohl(value)
Definition: cpu_endian.h:397
Echo-Reply.
Definition: ppp.h:223
error_t lcpProcessTerminateReq(PppContext *context, const PppTerminatePacket *terminateReqPacket)
Process Terminate-Request packet.
Definition: lcp.c:588
void lcpTick(PppContext *context)
LCP timer handler.
Definition: lcp.c:123
error_t lcpSendTerminateAck(PppContext *context, const PppTerminatePacket *terminateReqPacket)
Send-Terminate-Ack callback function.
Definition: lcp.c:1245
#define ntohs(value)
Definition: cpu_endian.h:396
void lcpThisLayerFinished(PppContext *context)
This-Layer-Finished callback function.
Definition: lcp.c:965
Protocol-Field-Compression.
Definition: lcp.h:53
#define htonl(value)
Definition: cpu_endian.h:391
#define PPP_DEFAULT_MRU
Definition: ppp.h:126
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
error_t papAbortAuth(PppContext *context)
Abort PAP authentication.
Definition: pap.c:85
error_t lcpParseAcfcOption(PppContext *context, LcpAcfcOption *option, PppConfigurePacket *outPacket)
Parse Address-and-Control-Field-Compression option.
Definition: lcp.c:1733
LCP (PPP Link Control Protocol)
void pppRcvConfigureAckEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Configure-Ack event.
Definition: ppp_fsm.c:522
error_t lcpProcessConfigureReject(PppContext *context, const PppConfigurePacket *configureRejPacket)
Process Configure-Reject packet.
Definition: lcp.c:490
CHAP (Challenge Handshake Authentication Protocol)
Maximum-Receive-Unit.
Definition: lcp.h:48
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
Address-and-Control-Field-Compression.
Definition: lcp.h:54
#define MIN(a, b)
Definition: os_port.h:60
void pppDownEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Down event.
Definition: ppp_fsm.c:82
const PppCallbacks lcpCallbacks
LCP FSM callbacks.
Definition: lcp.c:52
error_t pppSendTerminateAck(PppContext *context, uint8_t identifier, PppProtocol protocol)
Send Terminate-Ack packet.
Definition: ppp_misc.c:213
error_t lcpParseMruOption(PppContext *context, LcpMruOption *option, PppConfigurePacket *outPacket)
Parse Maximum-Receive-Unit option.
Definition: lcp.c:1390
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[]
__start_packed struct @279 LcpAccmOption
Async-Control-Character-Map option.
void lcpThisLayerStarted(PppContext *context)
This-Layer-Started callback function.
Definition: lcp.c:953
error_t pppSendEchoRep(PppContext *context, const PppEchoPacket *echoReqPacket, PppProtocol protocol)
Send Echo-Reply packet.
Definition: ppp_misc.c:383
__start_packed struct @282 LcpMagicNumberOption
Magic-Number option.
#define PppContext
Definition: ppp.h:36
#define TRACE_INFO(...)
Definition: debug.h:86
error_t lcpProcessUnknownCode(PppContext *context, const PppPacket *packet)
Process packet with unknown code.
Definition: lcp.c:804
error_t lcpParseAccmOption(PppContext *context, LcpAccmOption *option, PppConfigurePacket *outPacket)
Parse Async-Control-Character-Map option.
Definition: lcp.c:1456
error_t lcpParseAuthProtocolOption(PppContext *context, LcpAuthProtocolOption *option, PppConfigurePacket *outPacket)
Parse Authentication-Protocol option.
Definition: lcp.c:1500
__start_packed struct @278 LcpMruOption
Maximum-Receive-Unit option.
Success.
Definition: error.h:42
#define PPP_MIN_MRU
Definition: ppp.h:133
Echo-Request.
Definition: ppp.h:222
PPP finite state machine.
Configure-Ack.
Definition: ppp.h:215
void lcpZeroRestartCount(PppContext *context)
Zero-Restart-Count callback function.
Definition: lcp.c:1001
Magic-Number.
Definition: lcp.h:52
Link establishment phase.
Definition: ppp.h:165
error_t
Error codes.
Definition: error.h:40
error_t lcpProcessEchoReq(PppContext *context, const PppEchoPacket *echoReqPacket)
Process Echo-Request packet.
Definition: lcp.c:745
unsigned int uint_t
Definition: compiler_port.h:43
#define PRIuSIZE
Definition: compiler_port.h:72
__start_packed struct @284 LcpAcfcOption
Address-and-Control-Field-Compression option.
Internet Protocol.
Definition: ppp.h:197
error_t chapStartAuth(PppContext *context)
Start CHAP authentication.
Definition: chap.c:55
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
Challenge Handshake Authentication Protocol.
Definition: ppp.h:204
error_t lcpProcessCodeRej(PppContext *context, const PppCodeRejPacket *codeRejPacket)
Process Code-Reject packet.
Definition: lcp.c:633
uint8_t value[]
Definition: dtls_misc.h:141
Link Control Protocol.
Definition: ppp.h:201
void pppRcvConfigureNakEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks)
Process Receive-Configure-Nak event.
Definition: ppp_fsm.c:584
error_t lcpProcessTerminateAck(PppContext *context, const PppTerminatePacket *terminateAckPacket)
Process Terminate-Ack packet.
Definition: lcp.c:610
__start_packed struct @283 LcpPfcOption
Protocol-Field-Compression option.
error_t lcpProcessProtocolRej(PppContext *context, const PppProtocolRejPacket *protocolRejPacket)
Process Protocol-Reject packet.
Definition: lcp.c:680
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1004
void pppRcvEchoReqEvent(PppContext *context, PppFsm *fsm, const PppCallbacks *callbacks, const PppEchoPacket *echoReqPacket)
Process Receive-Echo-Request event.
Definition: ppp_fsm.c:887
void lcpInitRestartCount(PppContext *context, uint_t value)
Initialize-Restart-Count callback function.
Definition: lcp.c:986
Internet Protocol version 6.
Definition: ppp.h:198
void lcpThisLayerDown(PppContext *context)
This-Layer-Down callback function.
Definition: lcp.c:919
Link dead.
Definition: ppp.h:164
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 lcpSendCodeRej(PppContext *context, const PppPacket *packet)
Send-Code-Reject callback function.
Definition: lcp.c:1279
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 lcpProcessConfigureAck(PppContext *context, const PppConfigurePacket *configureAckPacket)
Process Configure-Ack packet.
Definition: lcp.c:343
uint8_t protocol
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
#define PPP_DEFAULT_ACCM
Definition: ppp.h:128
error_t lcpProcessConfigureReq(PppContext *context, const PppConfigurePacket *configureReqPacket)
Process Configure-Request packet.
Definition: lcp.c:247
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
IPCP (PPP Internet Protocol Control Protocol)
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
__start_packed struct @291 PppProtocolRejPacket
Protocol-Reject packet.
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
error_t lcpParseOption(PppContext *context, PppOption *option, size_t inPacketLen, PppConfigurePacket *outPacket)
Parse LCP configuration option.
Definition: lcp.c:1318
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1263
Authentication-Protocol.
Definition: lcp.h:50