ppp.c
Go to the documentation of this file.
1 /**
2  * @file ppp.c
3  * @brief PPP (Point-to-Point Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2022 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.2.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL PPP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ppp/ppp.h"
37 #include "ppp/ppp_hdlc.h"
38 #include "ppp/ppp_debug.h"
39 #include "ppp/lcp.h"
40 #include "ppp/ipcp.h"
41 #include "ppp/ipv6cp.h"
42 #include "ppp/pap.h"
43 #include "ppp/chap.h"
44 #include "mibs/mib2_module.h"
45 #include "mibs/if_mib_module.h"
46 #include "str.h"
47 #include "debug.h"
48 
49 //Check TCP/IP stack configuration
50 #if (PPP_SUPPORT == ENABLED)
51 
52 //Tick counter to handle periodic operations
54 
55 //FCS lookup table
56 static const uint16_t fcsTable[256] =
57 {
58  0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
59  0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
60  0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
61  0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
62  0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
63  0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
64  0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
65  0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
66  0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
67  0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
68  0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
69  0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
70  0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
71  0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
72  0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
73  0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
74  0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
75  0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
76  0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
77  0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
78  0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
79  0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
80  0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
81  0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
82  0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
83  0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
84  0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
85  0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
86  0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
87  0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
88  0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
89  0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
90 };
91 
92 
93 /**
94  * @brief Initialize settings with default values
95  * @param[out] settings Structure that contains PPP settings
96  **/
97 
99 {
100  //Use default interface
101  settings->interface = netGetDefaultInterface();
102 
103  //Default MRU
104  settings->mru = PPP_DEFAULT_MRU;
105  //Default async control character map
106  settings->accm = PPP_DEFAULT_ACCM;
107  //Allowed authentication protocols
109 
110  //Random data generation callback function
111  settings->randCallback = NULL;
112  //PPP authentication callback function
113  settings->authCallback = NULL;
114 }
115 
116 
117 /**
118  * @brief PPP initialization
119  * @param[in] context Pointer to the PPP context
120  * @param[in] settings PPP specific settings
121  * @return Error code
122  **/
123 
124 error_t pppInit(PppContext *context, const PppSettings *settings)
125 {
126  error_t error;
127  NetInterface *interface;
128 
129  //Debug message
130  TRACE_INFO("PPP initialization\r\n");
131 
132  //Underlying network interface
133  interface = settings->interface;
134 
135  //Initialize PPP context
136  osMemset(context, 0, sizeof(PppContext));
137 
138  //Save user settings
139  context->settings = *settings;
140 
141 #if (PAP_SUPPORT == DISABLED)
142  //PAP authentication is not supported
143  context->settings.authProtocol &= ~PPP_AUTH_PROTOCOL_PAP;
144 #endif
145 
146 #if (PAP_SUPPORT == DISABLED)
147  //CHAP with MD5 authentication is not supported
148  context->settings.authProtocol &= ~PPP_AUTH_PROTOCOL_CHAP_MD5;
149 #endif
150 
151  //Attach the PPP context to the network interface
152  interface->pppContext = context;
153 
154  //Initialize structure
155  context->interface = interface;
156  context->timeout = INFINITE_DELAY;
157 
158  //Initialize PPP finite state machine
159  context->pppPhase = PPP_PHASE_DEAD;
160  context->lcpFsm.state = PPP_STATE_0_INITIAL;
161 
162 #if (IPV4_SUPPORT == ENABLED)
163  //Initialize IPCP finite state machine
164  context->ipcpFsm.state = PPP_STATE_0_INITIAL;
165 #endif
166 
167 #if (IPV6_SUPPORT == ENABLED)
168  //Initialize IPV6CP finite state machine
169  context->ipv6cpFsm.state = PPP_STATE_0_INITIAL;
170 #endif
171 
172 #if (PAP_SUPPORT == ENABLED)
173  //Initialize PAP finite state machine
174  context->papFsm.localState = PAP_STATE_0_INITIAL;
175  context->papFsm.peerState = PAP_STATE_0_INITIAL;
176 #endif
177 
178 #if (CHAP_SUPPORT == ENABLED)
179  //Initialize CHAP finite state machine
180  context->chapFsm.localState = CHAP_STATE_0_INITIAL;
181  context->chapFsm.peerState = CHAP_STATE_0_INITIAL;
182 #endif
183 
184  //Attach PPP HDLC driver
185  error = netSetDriver(interface, &pppHdlcDriver);
186 
187  //Return status code
188  return error;
189 }
190 
191 
192 /**
193  * @brief Set timeout value for blocking operations
194  * @param[in] interface Underlying network interface
195  * @param[in] timeout Maximum time to wait
196  * @return Error code
197  **/
198 
200 {
201  PppContext *context;
202 
203  //Check parameters
204  if(interface == NULL)
206  //Make sure PPP has been properly configured
207  if(interface->pppContext == NULL)
208  return ERROR_NOT_CONFIGURED;
209 
210  //Point to the PPP context
211  context = interface->pppContext;
212 
213  //Get exclusive access
215 
216  //Set timeout value
217  context->timeout = timeout;
218 
219  //Release exclusive access
221 
222  //No error to report
223  return NO_ERROR;
224 }
225 
226 
227 /**
228  * @brief Set PPP authentication information
229  * @param[in] interface Underlying network interface
230  * @param[in] username NULL-terminated string containing the user name to be used
231  * @param[in] password NULL-terminated string containing the password to be used
232  * @return Error code
233  **/
234 
236  const char_t *username, const char_t *password)
237 {
238  PppContext *context;
239 
240  //Check parameters
241  if(interface == NULL || username == NULL || password == NULL)
243  //Make sure PPP has been properly configured
244  if(interface->pppContext == NULL)
245  return ERROR_NOT_CONFIGURED;
246 
247  //Point to the PPP context
248  context = interface->pppContext;
249 
250  //Get exclusive access
252 
253  //Save user name
254  strSafeCopy(context->username, username, PPP_MAX_USERNAME_LEN);
255  //Save password
256  strSafeCopy(context->password, password, PPP_MAX_PASSWORD_LEN);
257 
258  //Release exclusive access
260 
261  //No error to report
262  return NO_ERROR;
263 }
264 
265 
266 /**
267  * @brief Password verification
268  * @param[in] interface Underlying network interface
269  * @param[in] password NULL-terminated string containing the password to be checked
270  * @return TRUE if the password is valid, else FALSE
271  **/
272 
273 bool_t pppCheckPassword(NetInterface *interface, const char_t *password)
274 {
275  bool_t status;
276  PppContext *context;
277 
278  //Debug message
279  TRACE_DEBUG("PPP password verification...\r\n");
280 
281  //The password has not been verified yet
282  status = FALSE;
283 
284  //Point to the PPP context
285  context = interface->pppContext;
286 
287  //Make sure PPP has been properly configured
288  if(context != NULL)
289  {
290  //Check authentication protocol
291  if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP)
292  {
293 #if (PAP_SUPPORT == ENABLED)
294  //PAP authentication protocol
295  status = papCheckPassword(context, password);
296 #endif
297  }
298  //CHAP authentication protocol?
299  else if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP)
300  {
301 #if (CHAP_SUPPORT == ENABLED)
302  //CHAP authentication protocol
303  status = chapCheckPassword(context, password);
304 #endif
305  }
306  }
307 
308  //Return TRUE is the password is valid, else FALSE
309  return status;
310 }
311 
312 
313 /**
314  * @brief Send AT command
315  * @param[in] interface Underlying network interface
316  * @param[in] data NULL-terminated string that contains the AT command to be sent
317  * @return Error code
318  **/
319 
321 {
322  error_t error;
323  bool_t status;
324  PppContext *context;
325 
326  //Check parameters
327  if(interface == NULL)
329  //Make sure PPP has been properly configured
330  if(interface->pppContext == NULL)
331  return ERROR_NOT_CONFIGURED;
332 
333  //Point to the PPP context
334  context = interface->pppContext;
335 
336  //Wait for the send buffer to be available for writing
337  status = osWaitForEvent(&interface->nicTxEvent, context->timeout);
338 
339  //Check status
340  if(status)
341  {
342  //Get exclusive access
344 
345  //Check current PPP state
346  if(context->pppPhase == PPP_PHASE_DEAD)
347  {
348  //Purge receive buffer
349  error = pppHdlcDriverPurgeRxBuffer(context);
350 
351  //Send AT command
352  if(!error)
353  error = pppHdlcDriverSendAtCommand(interface, data);
354  }
355  else
356  {
357  //Report an error
358  error = ERROR_ALREADY_CONNECTED;
359  }
360 
361  //Release exclusive access
363  }
364  else
365  {
366  //Timeout error
367  return ERROR_TIMEOUT;
368  }
369 
370  //Return status code
371  return error;
372 }
373 
374 
375 /**
376  * @brief Wait for an incoming AT command
377  * @param[in] interface Underlying network interface
378  * @param[out] data Buffer where to store the incoming AT command
379  * @param[in] size Size of the buffer, in bytes
380  * @return Error code
381  **/
382 
384 {
385  error_t error;
386  systime_t time;
387  systime_t start;
388  PppContext *context;
389 
390  //Check parameters
391  if(interface == NULL || data == NULL || size == 0)
393 
394  //Make sure PPP has been properly configured
395  if(interface->pppContext == NULL)
396  return ERROR_NOT_CONFIGURED;
397 
398  //Point to the PPP context
399  context = interface->pppContext;
400  //Properly terminate the string with a NULL character
401  data[0] = '\0';
402  //Save current time
403  start = osGetSystemTime();
404 
405  //Wait for an incoming AT command
406  while(1)
407  {
408  //Get exclusive access
410 
411  //Check current PPP state
412  if(context->pppPhase == PPP_PHASE_DEAD)
413  {
414  //Wait for an incoming AT command
415  error = pppHdlcDriverReceiveAtCommand(interface, data, size);
416  }
417  else
418  {
419  //Report an error
420  error = ERROR_ALREADY_CONNECTED;
421  }
422 
423  //Release exclusive access
425 
426  //Check status code
427  if(error == ERROR_BUFFER_EMPTY)
428  {
429  //Get current time
430  time = osGetSystemTime();
431 
432  //Check whether the timeout period has elapsed
433  if(timeCompare(time, start + context->timeout) >= 0)
434  {
435  //Timeout error
436  error = ERROR_TIMEOUT;
437  //Exit immediately
438  break;
439  }
440  else
441  {
442  //Wait for more data to be received
444  }
445  }
446  else
447  {
448  //We are done
449  break;
450  }
451  }
452 
453  //Return status code
454  return error;
455 }
456 
457 
458 /**
459  * @brief Establish a PPP connection
460  * @param[in] interface Underlying network interface
461  * @return Error code
462  **/
463 
465 {
466  error_t error;
467  PppContext *context;
468 #if (NET_RTOS_SUPPORT == ENABLED)
469  systime_t time;
470  systime_t start;
471 #endif
472 
473  //Check parameters
474  if(interface == NULL)
476  //Make sure PPP has been properly configured
477  if(interface->pppContext == NULL)
478  return ERROR_NOT_CONFIGURED;
479 
480  //Point to the PPP context
481  context = interface->pppContext;
482 
483  //Get exclusive access
485 
486  //Default PPP phase
487  context->pppPhase = PPP_PHASE_DEAD;
488 
489  //Initialize LCP FSM
490  context->lcpFsm.state = PPP_STATE_0_INITIAL;
491  context->lcpFsm.identifier = 0;
492  context->lcpFsm.restartCounter = 0;
493  context->lcpFsm.failureCounter = 0;
494 
495 #if (IPV4_SUPPORT == ENABLED)
496  //Initialize IPCP FSM
497  context->ipcpFsm.state = PPP_STATE_0_INITIAL;
498  context->ipcpFsm.identifier = 0;
499  context->ipcpFsm.restartCounter = 0;
500  context->ipcpFsm.failureCounter = 0;
501 #endif
502 
503 #if (IPV6_SUPPORT == ENABLED)
504  //Initialize IPV6CP FSM
505  context->ipv6cpFsm.state = PPP_STATE_0_INITIAL;
506  context->ipv6cpFsm.identifier = 0;
507  context->ipv6cpFsm.restartCounter = 0;
508  context->ipv6cpFsm.failureCounter = 0;
509 #endif
510 
511  //Authentication has not been completed
512  context->localAuthDone = FALSE;
513  context->peerAuthDone = FALSE;
514 
515 #if (PAP_SUPPORT == ENABLED)
516  //Initialize PAP FSM
517  context->papFsm.localState = PAP_STATE_0_INITIAL;
518  context->papFsm.peerState = PAP_STATE_0_INITIAL;
519  context->papFsm.identifier = 0;
520  context->papFsm.restartCounter = 0;
521 #endif
522 
523 #if (CHAP_SUPPORT == ENABLED)
524  //Initialize CHAP FSM
525  context->chapFsm.localState = CHAP_STATE_0_INITIAL;
526  context->chapFsm.localIdentifier = 0;
527  context->chapFsm.peerState = CHAP_STATE_0_INITIAL;
528  context->chapFsm.peerIdentifier = 0;
529 #endif
530 
531  //Default local configuration
532  context->localConfig.mru = context->settings.mru;
533  context->localConfig.mruRejected = FALSE;
534  context->localConfig.accm = context->settings.accm;
535  context->localConfig.accmRejected = FALSE;
536  context->localConfig.authProtocol = 0;
537  context->localConfig.authAlgo = 0;
538  context->localConfig.authProtocolRejected = FALSE;
539  context->localConfig.magicNumber = PPP_DEFAULT_MAGIC_NUMBER;
540  context->localConfig.magicNumberRejected = FALSE;
541  context->localConfig.pfc = TRUE;
542  context->localConfig.pfcRejected = FALSE;
543  context->localConfig.acfc = TRUE;
544  context->localConfig.acfcRejected = FALSE;
545 
546  //Check whether the other end of the PPP link must be authenticated
547  if(context->settings.authCallback != NULL)
548  {
549 #if (PAP_SUPPORT == ENABLED)
550  //PAP provides an easy implementation of peer authentication
551  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_PAP)
552  {
553  //Select PAP authentication protocol
554  context->localConfig.authProtocol = PPP_PROTOCOL_PAP;
555  }
556 #endif
557 #if (CHAP_SUPPORT == ENABLED)
558  //CHAP with MD5 ensures greater security in the implementation
559  if(context->settings.authProtocol & PPP_AUTH_PROTOCOL_CHAP_MD5)
560  {
561  //Select CHAP with MD5 authentication protocol
562  context->localConfig.authProtocol = PPP_PROTOCOL_CHAP;
563  context->localConfig.authAlgo = CHAP_ALGO_ID_CHAP_MD5;
564  }
565 #endif
566  }
567 
568  //Default peer's configuration
569  context->peerConfig.mru = PPP_DEFAULT_MRU;
570  context->peerConfig.accm = PPP_DEFAULT_ACCM;
571  context->peerConfig.authProtocol = 0;
572  context->peerConfig.magicNumber = PPP_DEFAULT_MAGIC_NUMBER;
573  context->peerConfig.pfc = FALSE;
574  context->peerConfig.acfc = FALSE;
575 
576 #if (IPV4_SUPPORT == ENABLED)
577  //Default local configuration
578  context->localConfig.ipAddr = interface->ipv4Context.addrList[0].addr;
579  context->localConfig.ipAddrRejected = FALSE;
580  context->localConfig.primaryDns = interface->ipv4Context.dnsServerList[0];
581  context->localConfig.primaryDnsRejected = FALSE;
582 
583 #if (IPV4_DNS_SERVER_LIST_SIZE >= 2)
584  context->localConfig.secondaryDns = interface->ipv4Context.dnsServerList[1];
585  context->localConfig.secondaryDnsRejected = FALSE;
586 #else
587  context->localConfig.secondaryDns = IPV4_UNSPECIFIED_ADDR;
588  context->localConfig.secondaryDnsRejected = FALSE;
589 #endif
590 
591  //Manual primary DNS configuration?
592  if(context->localConfig.primaryDns != IPV4_UNSPECIFIED_ADDR)
593  context->localConfig.primaryDnsRejected = TRUE;
594 
595  //Manual secondary DNS configuration?
596  if(context->localConfig.secondaryDns != IPV4_UNSPECIFIED_ADDR)
597  context->localConfig.secondaryDnsRejected = TRUE;
598 
599  //Default peer's configuration
600  context->peerConfig.ipAddr = interface->ipv4Context.addrList[0].defaultGateway;
601 #endif
602 
603 #if (IPV6_SUPPORT == ENABLED)
604  //Default local configuration
605  eui64CopyAddr(&context->localConfig.interfaceId,
606  interface->ipv6Context.addrList[0].addr.b + 8);
607 
608  context->localConfig.interfaceIdRejected = FALSE;
609 
610  //Default peer's configuration
611  eui64CopyAddr(&context->peerConfig.interfaceId,
612  interface->ipv6Context.routerList[0].addr.b + 8);
613 #endif
614 
615  //The link is available for traffic
616  error = lcpOpen(context);
617 
618  //Release exclusive access
620 
621  //Any error to report?
622  if(error)
623  return error;
624 
625 #if (NET_RTOS_SUPPORT == ENABLED)
626  //Save current time
627  start = osGetSystemTime();
628 
629  //Wait for the connection to be established
630  while(1)
631  {
632  //Check current PPP phase
633  if(context->pppPhase == PPP_PHASE_NETWORK)
634  {
635 #if (IPV4_SUPPORT == ENABLED)
636  //Check current IPCP state
637  if(context->ipcpFsm.state == PPP_STATE_9_OPENED)
638  {
639  //Connection successfully established
640  error = NO_ERROR;
641  //Exit immediately
642  break;
643  }
644 #endif
645 #if (IPV6_SUPPORT == ENABLED)
646  //Check current IPV6CP state
647  if(context->ipv6cpFsm.state == PPP_STATE_9_OPENED)
648  {
649  //Connection successfully established
650  error = NO_ERROR;
651  //Exit immediately
652  break;
653  }
654 #endif
655  }
656  else if(context->pppPhase == PPP_PHASE_DEAD)
657  {
658  //Failed to establish connection
659  error = ERROR_CONNECTION_FAILED;
660  //Exit immediately
661  break;
662  }
663 
664  //Check timeout value
665  if(context->timeout != INFINITE_DELAY)
666  {
667  //Get current time
668  time = osGetSystemTime();
669 
670  //Check whether the timeout period has elapsed
671  if(timeCompare(time, start + context->timeout) >= 0)
672  {
673  //Report an error
674  error = ERROR_TIMEOUT;
675  //Exit immediately
676  break;
677  }
678  }
679 
680  //Polling delay
682  }
683 
684  //Failed to establish connection?
685  if(error)
686  {
687  //Get exclusive access
689 
690  //Abort the PPP connection
691  context->pppPhase = PPP_PHASE_DEAD;
692  context->lcpFsm.state = PPP_STATE_0_INITIAL;
693 
694 #if (IPV4_SUPPORT == ENABLED)
695  //Reset IPCP finite state machine
696  context->ipcpFsm.state = PPP_STATE_0_INITIAL;
697 #endif
698 
699 #if (IPV6_SUPPORT == ENABLED)
700  //Reset IPV6CP finite state machine
701  context->ipv6cpFsm.state = PPP_STATE_0_INITIAL;
702 #endif
703 
704 #if (PAP_SUPPORT == ENABLED)
705  //Abort PAP authentication process
706  context->papFsm.localState = PAP_STATE_0_INITIAL;
707  context->papFsm.peerState = PAP_STATE_0_INITIAL;
708 #endif
709 
710 #if (CHAP_SUPPORT == ENABLED)
711  //Abort CHAP authentication process
712  context->chapFsm.localState = CHAP_STATE_0_INITIAL;
713  context->chapFsm.peerState = CHAP_STATE_0_INITIAL;
714 #endif
715 
716  //Release exclusive access
718  }
719 #endif
720 
721  //Return status code
722  return error;
723 }
724 
725 
726 /**
727  * @brief Close a PPP connection
728  * @param[in] interface Underlying network interface
729  * @return Error code
730  **/
731 
733 {
734  error_t error;
735  PppContext *context;
736 #if (NET_RTOS_SUPPORT == ENABLED)
737  systime_t time;
738  systime_t start;
739 #endif
740 
741  //Check parameters
742  if(interface == NULL)
744  //Make sure PPP has been properly configured
745  if(interface->pppContext == NULL)
746  return ERROR_NOT_CONFIGURED;
747 
748  //Point to the PPP context
749  context = interface->pppContext;
750 
751  //Get exclusive access
753 
754  //The link is no longer available for traffic
755  error = lcpClose(context);
756 
757  //Release exclusive access
759 
760  //Any error to report?
761  if(error)
762  return error;
763 
764 #if (NET_RTOS_SUPPORT == ENABLED)
765  //Save current time
766  start = osGetSystemTime();
767 
768  //Wait for the connection to be closed
769  while(1)
770  {
771  //Check current PPP phase
772  if(context->pppPhase == PPP_PHASE_DEAD)
773  {
774  //PPP connection is closed
775  error = NO_ERROR;
776  //Exit immediately
777  break;
778  }
779 
780  //Check timeout value
781  if(context->timeout != INFINITE_DELAY)
782  {
783  //Get current time
784  time = osGetSystemTime();
785 
786  //Check whether the timeout period has elapsed
787  if(timeCompare(time, start + context->timeout) >= 0)
788  {
789  //Report an error
790  error = ERROR_TIMEOUT;
791  //Exit immediately
792  break;
793  }
794  }
795 
796  //Poll the state
798  }
799 
800  //Failed to properly close the connection?
801  if(error)
802  {
803  //Get exclusive access
805 
806  //Abort the PPP connection
807  context->pppPhase = PPP_PHASE_DEAD;
808  context->lcpFsm.state = PPP_STATE_0_INITIAL;
809 
810 #if (IPV4_SUPPORT == ENABLED)
811  //Reset IPCP finite state machine
812  context->ipcpFsm.state = PPP_STATE_0_INITIAL;
813 #endif
814 
815 #if (IPV6_SUPPORT == ENABLED)
816  //Reset IPV6CP finite state machine
817  context->ipv6cpFsm.state = PPP_STATE_0_INITIAL;
818 #endif
819 
820 #if (PAP_SUPPORT == ENABLED)
821  //Abort PAP authentication process
822  context->papFsm.localState = PAP_STATE_0_INITIAL;
823  context->papFsm.peerState = PAP_STATE_0_INITIAL;
824 #endif
825 
826 #if (CHAP_SUPPORT == ENABLED)
827  //Abort CHAP authentication process
828  context->chapFsm.localState = CHAP_STATE_0_INITIAL;
829  context->chapFsm.peerState = CHAP_STATE_0_INITIAL;
830 #endif
831 
832  //Release exclusive access
834  }
835 #endif
836 
837  //Return status code
838  return error;
839 }
840 
841 
842 /**
843  * @brief PPP timer handler
844  *
845  * This routine must be periodically called by the TCP/IP stack to
846  * manage retransmissions
847  *
848  * @param[in] interface Underlying network interface
849  **/
850 
851 void pppTick(NetInterface *interface)
852 {
853  PppContext *context;
854 
855  //PPP driver?
856  if(interface->nicDriver->type == NIC_TYPE_PPP)
857  {
858  //Point to the PPP context
859  context = interface->pppContext;
860 
861  //Handle LCP retransmission timer
862  lcpTick(context);
863 
864 #if (IPV4_SUPPORT == ENABLED)
865  //Handle IPCP retransmission timer
866  ipcpTick(context);
867 #endif
868 
869 #if (IPV6_SUPPORT == ENABLED)
870  //Handle IPV6CP retransmission timer
871  ipv6cpTick(context);
872 #endif
873 
874 #if (PAP_SUPPORT == ENABLED)
875  //Handle PAP timer
876  papTick(context);
877 #endif
878 
879 #if (CHAP_SUPPORT == ENABLED)
880  //Handle CHAP timer
881  chapTick(context);
882 #endif
883  }
884 }
885 
886 
887 /**
888  * @brief Process an incoming PPP frame
889  * @param[in] interface Underlying network interface
890  * @param[in] frame Incoming PPP frame to process
891  * @param[in] length Total frame length
892  * @param[in] ancillary Additional options passed to the stack along with
893  * the packet
894  **/
895 
896 void pppProcessFrame(NetInterface *interface, uint8_t *frame, size_t length,
897  NetRxAncillary *ancillary)
898 {
899  size_t n;
900  uint16_t protocol;
901  PppContext *context;
902 #if (IPV6_SUPPORT == ENABLED)
903  NetBuffer1 buffer;
904 #endif
905 
906  //Point to the PPP context
907  context = interface->pppContext;
908 
909  //Total number of octets received on the interface, including framing
910  //characters
911  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInOctets, length);
912  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInOctets, length);
913  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInOctets, length);
914 
915  //Check the length of the PPP frame
916  if(length < PPP_FCS_SIZE)
917  return;
918 
919  //Debug message
920  TRACE_DEBUG("PPP frame received (%" PRIuSIZE " bytes)...\r\n", length);
921 
922  //The value of the residue is 0x0F47 when no FCS errors are detected
923  if(pppCalcFcs(frame, length) != 0x0F47)
924  {
925  //Debug message
926  TRACE_WARNING("Wrong FCS detected!\r\n");
927  //Drop the received frame
928  return;
929  }
930 
931  //Calculate the length of PPP frame excluding the FCS field
932  length -= PPP_FCS_SIZE;
933 
934  //Decompress the frame header
935  n = pppParseFrameHeader(frame, length, &protocol);
936  //Malformed PPP frame?
937  if(!n)
938  return;
939 
940  //Point to the payload field
941  frame += n;
942  length -= n;
943 
944  //Check protocol field
945  switch(protocol)
946  {
947  //Link control protocol?
948  case PPP_PROTOCOL_LCP:
949  //Process incoming LCP packet
950  lcpProcessPacket(context, (PppPacket *) frame, length);
951  break;
952 
953 #if (IPV4_SUPPORT == ENABLED)
954  //IP control protocol?
955  case PPP_PROTOCOL_IPCP:
956  //Process incoming IPCP packet
957  ipcpProcessPacket(context, (PppPacket *) frame, length);
958  break;
959 
960  //IP protocol?
961  case PPP_PROTOCOL_IP:
962  //Process incoming IPv4 packet
963  ipv4ProcessPacket(interface, (Ipv4Header *) frame, length, ancillary);
964  break;
965 #endif
966 
967 #if (IPV6_SUPPORT == ENABLED)
968  //IPv6 control protocol?
969  case PPP_PROTOCOL_IPV6CP:
970  //Process incoming IPV6CP packet
971  ipv6cpProcessPacket(context, (PppPacket *) frame, length);
972  break;
973 
974  //IPv6 protocol?
975  case PPP_PROTOCOL_IPV6:
976  //The incoming PPP frame fits in a single chunk
977  buffer.chunkCount = 1;
978  buffer.maxChunkCount = 1;
979  buffer.chunk[0].address = frame;
980  buffer.chunk[0].length = (uint16_t) length;
981  buffer.chunk[0].size = 0;
982 
983  //Process incoming IPv6 packet
984  ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0, ancillary);
985  break;
986 #endif
987 
988 #if (PAP_SUPPORT == ENABLED)
989  //PAP protocol?
990  case PPP_PROTOCOL_PAP:
991  //Process incoming PAP packet
992  papProcessPacket(context, (PppPacket *) frame, length);
993  break;
994 #endif
995 
996 #if (CHAP_SUPPORT == ENABLED)
997  //CHAP protocol?
998  case PPP_PROTOCOL_CHAP:
999  //Process incoming CHAP packet
1000  chapProcessPacket(context, (PppPacket *) frame, length);
1001  break;
1002 #endif
1003 
1004  //Unknown protocol field
1005  default:
1006  //The peer is attempting to use a protocol which is unsupported
1007  lcpProcessUnknownProtocol(context, protocol, frame, length);
1008  break;
1009  }
1010 }
1011 
1012 
1013 /**
1014  * @brief Send a PPP frame
1015  * @param[in] interface Underlying network interface
1016  * @param[in] buffer Multi-part buffer containing the data
1017  * @param[in] offset Offset to the first data byte
1018  * @param[in] protocol Protocol field value
1019  * @return Error code
1020  **/
1021 
1023  NetBuffer *buffer, size_t offset, uint16_t protocol)
1024 {
1025  error_t error;
1026  size_t length;
1027  uint16_t fcs;
1028  uint8_t *p;
1029  PppContext *context;
1030  NetTxAncillary ancillary;
1031 
1032  //Point to the PPP context
1033  context = interface->pppContext;
1034 
1035  //Check whether the Protocol field can be compressed
1036  if(context->peerConfig.pfc && MSB(protocol) == 0)
1037  {
1038  //Is there enough space in the buffer to store the compressed
1039  //Protocol field?
1040  if(offset < 1)
1041  return ERROR_FAILURE;
1042 
1043  //Make room for the Protocol field
1044  offset--;
1045  //Move backward
1046  p = netBufferAt(buffer, offset);
1047  //Compress the Protocol field
1048  p[0] = LSB(protocol);
1049  }
1050  else
1051  {
1052  //Is there enough space in the buffer to store the uncompressed
1053  //Protocol field?
1054  if(offset < 2)
1055  return ERROR_FAILURE;
1056 
1057  //Make room for the Protocol field
1058  offset -= 2;
1059  //Move backward
1060  p = netBufferAt(buffer, offset);
1061  //Do not compress the Protocol field
1062  p[0] = MSB(protocol);
1063  p[1] = LSB(protocol);
1064  }
1065 
1066  //Check whether the Address and Control fields can be compressed
1067  if(context->peerConfig.acfc && protocol != PPP_PROTOCOL_LCP)
1068  {
1069  //On transmission, compressed Address and Control fields
1070  //are simply omitted...
1071  }
1072  else
1073  {
1074  //Is there enough space in the buffer to store the uncompressed
1075  //Address and Control fields?
1076  if(offset < 2)
1077  return ERROR_FAILURE;
1078 
1079  //Make room for the Address and Control fields
1080  offset -= 2;
1081  //Move backward
1082  p = netBufferAt(buffer, offset);
1083  //Do not compress the Address and Control fields
1084  p[0] = PPP_ADDR_FIELD;
1085  p[1] = PPP_CTRL_FIELD;
1086  }
1087 
1088  //Retrieve the length of the frame
1089  length = netBufferGetLength(buffer) - offset;
1090 
1091  //Compute FCS over the header and payload
1092  fcs = pppCalcFcsEx(buffer, offset, length);
1093  //The FCS is transmitted least significant octet first
1094  fcs = htole16(fcs);
1095 
1096  //Append the calculated FCS value
1097  error = netBufferAppend(buffer, &fcs, PPP_FCS_SIZE);
1098  //Any error to report?
1099  if(error)
1100  return error;
1101 
1102  //Adjust frame length
1103  length += PPP_FCS_SIZE;
1104 
1105  //Total number of octets transmitted out of the interface, including
1106  //framing characters
1107  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifOutOctets, length);
1108  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifOutOctets, length);
1109  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutOctets, length);
1110 
1111  //Debug message
1112  TRACE_DEBUG("Sending PPP frame (%" PRIuSIZE " bytes)...\r\n", length);
1113  TRACE_DEBUG(" Protocol = 0x%04" PRIX16 "\r\n", protocol);
1114 
1115  //Additional options can be passed to the stack along with the packet
1116  ancillary = NET_DEFAULT_TX_ANCILLARY;
1117 
1118  //Send the resulting frame over the specified link
1119  error = nicSendPacket(interface, buffer, offset, &ancillary);
1120 
1121  //Return status code
1122  return error;
1123 }
1124 
1125 
1126 /**
1127  * @brief Parse PPP frame header
1128  * @param[in] frame Pointer to the PPP frame
1129  * @param[in] length Length of the frame, in bytes
1130  * @param[out] protocol Value of the Protocol field
1131  * @return If the PPP header was successfully parsed, the function returns the size
1132  * of the PPP header, in bytes. If a parsing error occurred, zero is returned
1133  **/
1134 
1135 size_t pppParseFrameHeader(const uint8_t *frame, size_t length, uint16_t *protocol)
1136 {
1137  size_t n;
1138 
1139  //Size of the PPP header, in bytes
1140  n = 0;
1141 
1142  //On reception, the Address and Control fields are decompressed by
1143  //examining the first two octets
1144  if(length >= 2)
1145  {
1146  //If they contain the values 0xff and 0x03, they are assumed to be
1147  //the Address and Control fields. If not, it is assumed that the
1148  //fields were compressed and were not transmitted
1149  if(frame[0] == PPP_ADDR_FIELD && frame[1] == PPP_CTRL_FIELD)
1150  {
1151  //Move to the Protocol field
1152  n = 2;
1153  }
1154  }
1155 
1156  //Check the length of the PPP frame
1157  if(length >= (n + 1))
1158  {
1159  //PPP Protocol field numbers are chosen such that some values may be
1160  //compressed into a single octet form which is clearly distinguishable
1161  //from the two octet form
1162  if(frame[n] & 0x01)
1163  {
1164  //The presence of a binary 1 as the LSB marks the last octet of
1165  //the Protocol field
1166  *protocol = frame[n];
1167 
1168  //Update the length of the header
1169  n++;
1170  }
1171  else
1172  {
1173  //Check the length of the PPP frame
1174  if(length >= (n + 2))
1175  {
1176  //The Protocol field is not compressed
1177  *protocol = (frame[n] << 8) | frame[n + 1];
1178 
1179  //Update the length of the header
1180  n += 2;
1181  }
1182  else
1183  {
1184  //Malformed PPP frame
1185  n = 0;
1186  }
1187  }
1188  }
1189  else
1190  {
1191  //Malformed PPP frame
1192  n = 0;
1193  }
1194 
1195  //Return the size of the PPP header, in bytes
1196  return n;
1197 }
1198 
1199 
1200 /**
1201  * @brief FCS calculation
1202  * @param[in] data Pointer to the data over which to calculate the FCS
1203  * @param[in] length Number of bytes to process
1204  * @return Resulting FCS value
1205  **/
1206 
1207 uint16_t pppCalcFcs(const uint8_t *data, size_t length)
1208 {
1209  size_t i;
1210  uint16_t fcs;
1211 
1212  //FCS preset value
1213  fcs = 0xFFFF;
1214 
1215  //Loop through data
1216  for(i = 0; i < length; i++)
1217  {
1218  //The message is processed byte by byte
1219  fcs = (fcs >> 8) ^ fcsTable[(fcs & 0xFF) ^ data[i]];
1220  }
1221 
1222  //Return 1's complement value
1223  return ~fcs;
1224 }
1225 
1226 
1227 /**
1228  * @brief Calculate FCS over a multi-part buffer
1229  * @param[in] buffer Pointer to the multi-part buffer
1230  * @param[in] offset Offset from the beginning of the buffer
1231  * @param[in] length Number of bytes to process
1232  * @return Resulting FCS value
1233  **/
1234 
1235 uint16_t pppCalcFcsEx(const NetBuffer *buffer, size_t offset, size_t length)
1236 {
1237  uint_t i;
1238  uint_t n;
1239  uint16_t fcs;
1240  uint8_t *p;
1241 
1242  //FCS preset value
1243  fcs = 0xFFFF;
1244 
1245  //Loop through data chunks
1246  for(i = 0; i < buffer->chunkCount && length > 0; i++)
1247  {
1248  //Is there any data to process in the current chunk?
1249  if(offset < buffer->chunk[i].length)
1250  {
1251  //Point to the first data byte
1252  p = (uint8_t *) buffer->chunk[i].address + offset;
1253  //Compute the number of bytes to process
1254  n = MIN(buffer->chunk[i].length - offset, length);
1255  //Adjust byte counter
1256  length -= n;
1257 
1258  //Process current chunk
1259  while(n > 0)
1260  {
1261  //The message is processed byte by byte
1262  fcs = (fcs >> 8) ^ fcsTable[(fcs & 0xFF) ^ *p];
1263 
1264  //Next byte
1265  p++;
1266  n--;
1267  }
1268 
1269  //Process the next block from the start
1270  offset = 0;
1271  }
1272  else
1273  {
1274  //Skip the current chunk
1275  offset -= buffer->chunk[i].length;
1276  }
1277  }
1278 
1279  //Return 1's complement value
1280  return ~fcs;
1281 }
1282 
1283 
1284 /**
1285  * @brief Allocate a buffer to hold a PPP frame
1286  * @param[in] length Desired payload length
1287  * @param[out] offset Offset to the first byte of the payload
1288  * @return The function returns a pointer to the newly allocated
1289  * buffer. If the system is out of resources, NULL is returned
1290  **/
1291 
1292 NetBuffer *pppAllocBuffer(size_t length, size_t *offset)
1293 {
1294  NetBuffer *buffer;
1295 
1296  //Allocate a buffer to hold the Ethernet header and the payload
1298  //Failed to allocate buffer?
1299  if(buffer == NULL)
1300  return NULL;
1301 
1302  //Offset to the first byte of the payload
1303  *offset = PPP_FRAME_HEADER_SIZE;
1304 
1305  //Return a pointer to the freshly allocated buffer
1306  return buffer;
1307 }
1308 
1309 #endif
uint8_t length
Definition: coap_common.h:193
@ CHAP_STATE_0_INITIAL
Definition: chap.h:71
MIB-II module.
#define htole16(value)
Definition: cpu_endian.h:429
Data logging functions for debugging purpose (PPP)
@ CHAP_ALGO_ID_CHAP_MD5
Definition: chap.h:103
String manipulation helper functions.
int bool_t
Definition: compiler_port.h:48
#define PppPacket
Definition: ppp.h:37
#define Ipv4Header
Definition: ipv4.h:36
#define PPP_ADDR_FIELD
Definition: ppp.h:150
error_t netSetDriver(NetInterface *interface, const NicDriver *driver)
Set Ethernet MAC driver.
Definition: net.c:737
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
void lcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming LCP packet.
Definition: lcp.c:155
uint8_t data[]
Definition: ethernet.h:220
#define PPP_FCS_SIZE
Definition: ppp.h:145
void lcpTick(PppContext *context)
LCP timer handler.
Definition: lcp.c:125
uint_t chunkCount
Definition: net_mem.h:98
#define netMutex
Definition: net_legacy.h:266
uint16_t pppCalcFcsEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate FCS over a multi-part buffer.
Definition: ppp.c:1235
CHAP (Challenge Handshake Authentication Protocol)
@ PAP_STATE_0_INITIAL
Definition: pap.h:71
void chapProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming CHAP packet.
Definition: chap.c:149
@ PPP_PROTOCOL_CHAP
Challenge Handshake Authentication Protocol.
Definition: ppp.h:206
uint_t authProtocol
Allowed authentication protocols.
Definition: ppp.h:385
uint8_t p
Definition: ndp.h:298
error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet to the network controller.
Definition: nic.c:280
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
void papProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming PAP packet.
Definition: pap.c:149
uint_t chunkCount
Definition: net_mem.h:90
error_t pppSetTimeout(NetInterface *interface, systime_t timeout)
Set timeout value for blocking operations.
Definition: ppp.c:199
#define TRUE
Definition: os_port.h:50
@ ERROR_ALREADY_CONNECTED
Definition: error.h:81
IPV6CP (PPP IPv6 Control Protocol)
PppAuthCallback authCallback
PPP authentication callback function.
Definition: ppp.h:387
void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length, NetRxAncillary *ancillary)
Incoming IPv4 packet processing.
Definition: ipv4.c:567
uint16_t mru
Default MRU.
Definition: ppp.h:383
void chapTick(PppContext *context)
CHAP timer handler.
Definition: chap.c:110
error_t lcpOpen(PppContext *context)
LCP Open event.
Definition: lcp.c:79
error_t pppReceiveAtCommand(NetInterface *interface, char_t *data, size_t size)
Wait for an incoming AT command.
Definition: ppp.c:383
@ PPP_PHASE_NETWORK
Network-layer protocol phase.
Definition: ppp.h:169
@ ERROR_NOT_CONFIGURED
Definition: error.h:216
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1292
void ipv6ProcessPacket(NetInterface *interface, NetBuffer *ipPacket, size_t ipPacketOffset, NetRxAncillary *ancillary)
Incoming IPv6 packet processing.
Definition: ipv6.c:939
void pppTick(NetInterface *interface)
PPP timer handler.
Definition: ppp.c:851
#define PPP_CTRL_FIELD
PPP Control field.
Definition: ppp.h:152
error_t pppHdlcDriverReceiveAtCommand(NetInterface *interface, char_t *data, size_t size)
Wait for an incoming AT command.
Definition: ppp_hdlc.c:430
#define timeCompare(t1, t2)
Definition: os_port.h:42
ChunkDesc chunk[1]
Definition: net_mem.h:100
#define PppContext
Definition: ppp.h:38
error_t pppSendAtCommand(NetInterface *interface, const char_t *data)
Send AT command.
Definition: ppp.c:320
#define IF_MIB_INC_COUNTER64(name, value)
Definition: if_mib_module.h:48
bool_t pppCheckPassword(NetInterface *interface, const char_t *password)
Password verification.
Definition: ppp.c:273
systime_t pppTickCounter
Definition: ppp.c:53
uint32_t accm
Default async control character map.
Definition: ppp.h:384
IPCP (PPP Internet Protocol Control Protocol)
#define PPP_POLLING_INTERVAL
Definition: ppp.h:89
LCP (PPP Link Control Protocol)
error_t lcpProcessUnknownProtocol(PppContext *context, uint16_t protocol, const uint8_t *information, size_t length)
Process PPP frame with unknown protocol.
Definition: lcp.c:830
uint16_t length
Definition: net_mem.h:79
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ PPP_STATE_9_OPENED
Definition: ppp.h:189
error_t
Error codes.
Definition: error.h:43
error_t pppHdlcDriverSendAtCommand(NetInterface *interface, const char_t *data)
Send AT command.
Definition: ppp_hdlc.c:395
@ PPP_AUTH_PROTOCOL_PAP
Definition: ppp.h:236
uint8_t protocol
#define eui64CopyAddr(destEui64Addr, srcEui64Addr)
Definition: ethernet.h:136
#define PPP_DEFAULT_ACCM
Definition: ppp.h:130
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
void pppGetDefaultSettings(PppSettings *settings)
Initialize settings with default values.
Definition: ppp.c:98
bool_t papCheckPassword(PppContext *context, const char_t *password)
Password verification.
Definition: pap.c:602
void * address
Definition: net_mem.h:78
#define MIB2_IF_INC_COUNTER32(name, value)
Definition: mib2_module.h:156
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t pppInit(PppContext *context, const PppSettings *settings)
PPP initialization.
Definition: ppp.c:124
uint_t maxChunkCount
Definition: net_mem.h:99
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
error_t pppHdlcDriverPurgeRxBuffer(PppContext *context)
Purge RX buffer.
Definition: ppp_hdlc.c:551
error_t pppConnect(NetInterface *interface)
Establish a PPP connection.
Definition: ppp.c:464
size_t pppParseFrameHeader(const uint8_t *frame, size_t length, uint16_t *protocol)
Parse PPP frame header.
Definition: ppp.c:1135
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:410
@ ERROR_BUFFER_EMPTY
Definition: error.h:140
#define NetTxAncillary
Definition: net_misc.h:36
#define PPP_DEFAULT_MAGIC_NUMBER
Definition: ppp.h:132
@ PPP_PHASE_DEAD
Link dead.
Definition: ppp.h:166
#define MSB(x)
Definition: os_port.h:58
#define PPP_FRAME_HEADER_SIZE
Definition: ppp.h:143
void pppProcessFrame(NetInterface *interface, uint8_t *frame, size_t length, NetRxAncillary *ancillary)
Process an incoming PPP frame.
Definition: ppp.c:896
@ PPP_PROTOCOL_IPV6
Internet Protocol version 6.
Definition: ppp.h:200
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define LSB(x)
Definition: os_port.h:54
@ PPP_PROTOCOL_IPV6CP
IPv6 Control Protocol.
Definition: ppp.h:202
Interfaces Group MIB module.
#define MIN(a, b)
Definition: os_port.h:62
void ipv6cpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming IPV6CP packet.
Definition: ipv6cp.c:152
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
uint32_t systime_t
System time.
@ NIC_TYPE_PPP
PPP interface.
Definition: nic.h:84
#define TRACE_WARNING(...)
Definition: debug.h:85
#define TRACE_DEBUG(...)
Definition: debug.h:107
@ ERROR_TIMEOUT
Definition: error.h:94
char char_t
Definition: compiler_port.h:43
@ PPP_PROTOCOL_LCP
Link Control Protocol.
Definition: ppp.h:203
error_t pppSetAuthInfo(NetInterface *interface, const char_t *username, const char_t *password)
Set PPP authentication information.
Definition: ppp.c:235
uint32_t time
ChunkDesc chunk[]
Definition: net_mem.h:92
error_t strSafeCopy(char_t *dest, const char_t *src, size_t destSize)
Copy string.
Definition: str.c:167
@ PPP_PROTOCOL_IPCP
IP Control Protocol.
Definition: ppp.h:201
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1022
@ PPP_AUTH_PROTOCOL_CHAP_MD5
Definition: ppp.h:237
uint16_t pppCalcFcs(const uint8_t *data, size_t length)
FCS calculation.
Definition: ppp.c:1207
void ipv6cpTick(PppContext *context)
IPV6CP timer handler.
Definition: ipv6cp.c:122
void ipcpTick(PppContext *context)
IPCP timer handler.
Definition: ipcp.c:121
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
bool_t chapCheckPassword(PppContext *context, const char_t *password)
Password verification.
Definition: chap.c:712
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:586
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
#define IF_MIB_INC_COUNTER32(name, value)
Definition: if_mib_module.h:47
PPP settings.
Definition: ppp.h:381
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
const NicDriver pppHdlcDriver
PPP HDLC driver.
Definition: ppp_hdlc.c:49
@ PPP_STATE_0_INITIAL
Definition: ppp.h:180
PPP (Point-to-Point Protocol)
void ipcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming IPCP packet.
Definition: ipcp.c:151
void osDelayTask(systime_t delay)
Delay routine.
PPP HDLC driver.
NetInterface * interface
Underlying network interface.
Definition: ppp.h:382
#define PPP_MAX_PASSWORD_LEN
Definition: ppp.h:75
@ ERROR_CONNECTION_FAILED
Definition: error.h:75
@ PPP_PROTOCOL_IP
Internet Protocol.
Definition: ppp.h:199
error_t lcpClose(PppContext *context)
LCP Close event.
Definition: lcp.c:103
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:45
#define osMemset(p, value, length)
Definition: os_port.h:131
TCP/IP stack core.
PppRandCallback randCallback
Random data generation callback function.
Definition: ppp.h:386
void papTick(PppContext *context)
PAP timer handler.
Definition: pap.c:110
uint16_t size
Definition: net_mem.h:80
PAP (Password Authentication Protocol)
error_t pppClose(NetInterface *interface)
Close a PPP connection.
Definition: ppp.c:732
#define PPP_DEFAULT_MRU
Definition: ppp.h:128
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:74
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:104
@ PPP_PROTOCOL_PAP
Password Authentication Protocol.
Definition: ppp.h:204
systime_t osGetSystemTime(void)
Retrieve system time.
#define PPP_MAX_USERNAME_LEN
Definition: ppp.h:68