pap.c
Go to the documentation of this file.
1 /**
2  * @file pap.c
3  * @brief PAP (Password Authentication 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_debug.h"
35 #include "ppp/lcp.h"
36 #include "ppp/ipcp.h"
37 #include "ppp/ipv6cp.h"
38 #include "ppp/pap.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (PPP_SUPPORT == ENABLED && PAP_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Start PAP authentication
47  * @param[in] context PPP context
48  * @return Error code
49  **/
50 
52 {
53  //Debug message
54  TRACE_INFO("\r\nStarting PAP authentication...\r\n");
55 
56  //Check whether the other end of the PPP link is being authenticated
57  if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP)
58  {
59  //Switch to the Started state
60  context->papFsm.localState = PAP_STATE_1_STARTED;
61  }
62 
63  //Check whether the other end of the PPP link is the authenticator
64  if(context->peerConfig.authProtocol == PPP_PROTOCOL_PAP)
65  {
66  //Initialize restart counter
67  context->papFsm.restartCounter = PAP_MAX_REQUESTS;
68  //Send Authenticate-Request packet
69  papSendAuthReq(context);
70  //Switch to the Req-Sent state
71  context->papFsm.peerState = PAP_STATE_2_REQ_SENT;
72  }
73 
74  //Successful processing
75  return NO_ERROR;
76 }
77 
78 
79 /**
80  * @brief Abort PAP authentication
81  * @param[in] context PPP context
82  * @return Error code
83  **/
84 
86 {
87  //Debug message
88  TRACE_INFO("\r\nAborting PAP authentication...\r\n");
89 
90  //Abort PAP authentication process
91  context->papFsm.localState = PAP_STATE_0_INITIAL;
92  context->papFsm.peerState = PAP_STATE_0_INITIAL;
93 
94  //Successful processing
95  return NO_ERROR;
96 }
97 
98 
99 /**
100  * @brief PAP timer handler
101  *
102  * This routine must be periodically called by the TCP/IP stack to
103  * manage retransmissions
104  *
105  * @param[in] context PPP context
106  **/
107 
108 void papTick(PppContext *context)
109 {
110  //Check whether the restart timer is running
111  if(context->papFsm.peerState == PAP_STATE_2_REQ_SENT)
112  {
113  //Get current time
115 
116  //Check restart timer
117  if((time - context->papFsm.timestamp) >= PAP_RESTART_TIMER)
118  {
119  //Debug message
120  TRACE_INFO("\r\nPAP Timeout event\r\n");
121 
122  //Check whether the restart counter is greater than zero
123  if(context->papFsm.restartCounter > 0)
124  {
125  //Retransmit the Authenticate-Request packet
126  papSendAuthReq(context);
127  }
128  else
129  {
130  //Abort PAP authentication
131  context->papFsm.peerState = PAP_STATE_0_INITIAL;
132  //Authentication failed
133  lcpClose(context);
134  }
135  }
136  }
137 }
138 
139 
140 /**
141  * @brief Process an incoming PAP packet
142  * @param[in] context PPP context
143  * @param[in] packet PAP packet received from the peer
144  * @param[in] length Length of the packet, in bytes
145  **/
146 
148  const PppPacket *packet, size_t length)
149 {
150  //Ensure the length of the incoming PAP packet is valid
151  if(length < sizeof(PppPacket))
152  return;
153 
154  //Check the length field
155  if(ntohs(packet->length) > length)
156  return;
157  if(ntohs(packet->length) < sizeof(PppPacket))
158  return;
159 
160  //Save the length of the PAP packet
161  length = ntohs(packet->length);
162 
163  //Debug message
164  TRACE_INFO("PAP packet received (%" PRIuSIZE " bytes)...\r\n", length);
165  //Dump PAP packet contents for debugging purpose
167 
168  //Because the Authenticate-Ack might be lost, the authenticator must
169  //allow repeated Authenticate-Request packets after completing the
170  //Authentication phase
171  if(context->pppPhase != PPP_PHASE_AUTHENTICATE &&
172  context->pppPhase != PPP_PHASE_NETWORK)
173  {
174  //Any packets received during any other phase must be silently discarded
175  return;
176  }
177 
178  //Check PAP code field
179  switch(packet->code)
180  {
181  //Authenticate-Request packet?
182  case PAP_CODE_AUTH_REQ:
183  //Process Authenticate-Request packet
184  papProcessAuthReq(context, (PapAuthReqPacket *) packet, length);
185  break;
186  //Authenticate-Ack packet?
187  case PAP_CODE_AUTH_ACK:
188  //Process Authenticate-Ack packet
189  papProcessAuthAck(context, (PapAuthAckPacket *) packet, length);
190  break;
191  //Authenticate-Nak packet?
192  case PAP_CODE_AUTH_NAK:
193  //Process Authenticate-Nak packet
194  papProcessAuthNak(context, (PapAuthNakPacket *) packet, length);
195  break;
196  //Unknown code field
197  default:
198  //Silently drop the incoming packet
199  break;
200  }
201 }
202 
203 
204 /**
205  * @brief Process Authenticate-Request packet
206  * @param[in] context PPP context
207  * @param[in] authReqPacket Packet received from the peer
208  * @param[in] length Length of the packet, in bytes
209  * @return Error code
210  **/
211 
213  const PapAuthReqPacket *authReqPacket, size_t length)
214 {
215  bool_t status;
216  size_t usernameLen;
217  const uint8_t *p;
218 
219  //Debug message
220  TRACE_INFO("\r\nPAP Authenticate-Request packet received\r\n");
221 
222  //Make sure the Authenticate-Request packet is acceptable
223  if(context->localConfig.authProtocol != PPP_PROTOCOL_PAP)
224  return ERROR_FAILURE;
225 
226  //Check the length of the packet
227  if(length < sizeof(PapAuthReqPacket))
228  return ERROR_INVALID_LENGTH;
229 
230  //Retrieve the length of the Peer-ID field
231  usernameLen = authReqPacket->peerIdLength;
232 
233  //Malformed Authenticate-Request packet?
234  if(length < (sizeof(PapAuthReqPacket) + 1 + usernameLen))
235  return ERROR_INVALID_LENGTH;
236 
237  //Limit the length of the string
238  usernameLen = MIN(usernameLen, PPP_MAX_USERNAME_LEN);
239  //Copy the name of the peer to be identified
240  memcpy(context->peerName, authReqPacket->peerId, usernameLen);
241  //Properly terminate the string with a NULL character
242  context->peerName[usernameLen] = '\0';
243 
244  //Point to the Passwd-Length field
245  p = authReqPacket->peerId + usernameLen;
246 
247  //Save the length of Password field
248  context->papFsm.passwordLen = p[0];
249  //Point to the Password field
250  context->papFsm.password = p + 1;
251 
252  //Malformed Authenticate-Request packet?
253  if(length < (sizeof(PapAuthReqPacket) + 1 + usernameLen + context->papFsm.passwordLen))
254  return ERROR_INVALID_LENGTH;
255 
256  //Invoke user-defined callback, if any
257  if(context->settings.authCallback != NULL)
258  {
259  //Perfom username and password verification
260  status = context->settings.authCallback(context->interface,
261  context->peerName);
262  }
263  else
264  {
265  //Unable to perform authentication...
266  status = FALSE;
267  }
268 
269  //Successful authentication?
270  if(status)
271  {
272  //If the Peer-ID/Password pair received in the Authenticate-Request
273  //is both recognizable and acceptable, then the authenticator must
274  //transmit an Authenticate-Ack packet
275  papSendAuthAck(context, authReqPacket->identifier);
276 
277  //Switch to the Ack-Sent state
278  context->papFsm.localState = PAP_STATE_4_ACK_SENT;
279  //The user has been successfully authenticated
280  context->localAuthDone = TRUE;
281 
282  //Check whether PPP authentication is complete
283  if(context->localAuthDone && context->peerAuthDone)
284  {
285  //Check current PPP phase
286  if(context->pppPhase == PPP_PHASE_AUTHENTICATE)
287  {
288  //Advance to the Network phase
289  context->pppPhase = PPP_PHASE_NETWORK;
290 
291 #if (IPV4_SUPPORT == ENABLED)
292  //IPCP Open event
293  ipcpOpen(context);
294 #endif
295 #if (IPV6_SUPPORT == ENABLED)
296  //IPV6CP Open event
297  ipv6cpOpen(context);
298 #endif
299  }
300  }
301  }
302  else
303  {
304  //If the Peer-ID/Password pair received in the Authenticate-Request
305  //is not recognizable or acceptable, then the authenticator must
306  //transmit an Authenticate-Nak packet
307  papSendAuthNak(context, authReqPacket->identifier);
308 
309  //Switch to the Nak-Sent state
310  context->papFsm.localState = PAP_STATE_6_NAK_SENT;
311  //The authenticator should take action to terminate the link
312  lcpClose(context);
313  }
314 
315  //Successful processing
316  return NO_ERROR;
317 }
318 
319 
320 /**
321  * @brief Process Authenticate-Ack packet
322  * @param[in] context PPP context
323  * @param[in] authAckPacket Packet received from the peer
324  * @param[in] length Length of the packet, in bytes
325  * @return Error code
326  **/
327 
329  const PapAuthAckPacket *authAckPacket, size_t length)
330 {
331  //Debug message
332  TRACE_INFO("\r\nPAP Authenticate-Ack packet received\r\n");
333 
334  //Make sure the Authenticate-Ack packet is acceptable
335  if(context->peerConfig.authProtocol != PPP_PROTOCOL_PAP)
336  return ERROR_FAILURE;
337 
338  //Check the length of the packet
339  if(length < sizeof(PapAuthAckPacket))
340  return ERROR_INVALID_LENGTH;
341 
342  //When a packet is received with an invalid Identifier field, the
343  //packet is silently discarded without affecting the automaton
344  if(authAckPacket->identifier != context->papFsm.identifier)
345  return ERROR_WRONG_IDENTIFIER;
346 
347  //Switch to the Ack-Rcvd state
348  context->papFsm.peerState = PAP_STATE_5_ACK_RCVD;
349  //The user name has been accepted by the authenticator
350  context->peerAuthDone = TRUE;
351 
352  //Check whether PPP authentication is complete
353  if(context->localAuthDone && context->peerAuthDone)
354  {
355  //Check current PPP phase
356  if(context->pppPhase == PPP_PHASE_AUTHENTICATE)
357  {
358  //Advance to the Network phase
359  context->pppPhase = PPP_PHASE_NETWORK;
360 
361 #if (IPV4_SUPPORT == ENABLED)
362  //IPCP Open event
363  ipcpOpen(context);
364 #endif
365 #if (IPV6_SUPPORT == ENABLED)
366  //IPV6CP Open event
367  ipv6cpOpen(context);
368 #endif
369  }
370  }
371 
372  //Successful processing
373  return NO_ERROR;
374 }
375 
376 
377 /**
378  * @brief Process Authenticate-Nak packet
379  * @param[in] context PPP context
380  * @param[in] authNakPacket Packet received from the peer
381  * @param[in] length Length of the packet, in bytes
382  * @return Error code
383  **/
384 
386  const PapAuthNakPacket *authNakPacket, size_t length)
387 {
388  //Debug message
389  TRACE_INFO("\r\nPAP Authenticate-Nak packet received\r\n");
390 
391  //Make sure the Authenticate-Nak packet is acceptable
392  if(context->peerConfig.authProtocol != PPP_PROTOCOL_PAP)
393  return ERROR_FAILURE;
394 
395  //Check the length of the packet
396  if(length < sizeof(PapAuthNakPacket))
397  return ERROR_INVALID_LENGTH;
398 
399  //When a packet is received with an invalid Identifier field, the
400  //packet is silently discarded without affecting the automaton
401  if(authNakPacket->identifier != context->papFsm.identifier)
402  return ERROR_WRONG_IDENTIFIER;
403 
404  //Switch to the Nak-Rcvd state
405  context->papFsm.peerState = PAP_STATE_7_NAK_RCVD;
406  //Authentication failed
407  lcpClose(context);
408 
409  //Successful processing
410  return NO_ERROR;
411 }
412 
413 
414 /**
415  * @brief Send Authenticate-Request packet
416  * @param[in] context PPP context
417  * @return Error code
418  **/
419 
421 {
422  error_t error;
423  size_t usernameLen;
424  size_t passwordLen;
425  size_t length;
426  size_t offset;
427  uint8_t *p;
428  NetBuffer *buffer;
429  PapAuthReqPacket *authReqPacket;
430 
431  //Get the length of the user name
432  usernameLen = strlen(context->username);
433  //Get the length of the password
434  passwordLen = strlen(context->password);
435 
436  //Calculate the length of the Authenticate-Request packet
437  length = sizeof(PapAuthReqPacket) + 1 + usernameLen + passwordLen;
438 
439  //Allocate a buffer memory to hold the packet
440  buffer = pppAllocBuffer(length, &offset);
441  //Failed to allocate memory?
442  if(buffer == NULL)
443  return ERROR_OUT_OF_MEMORY;
444 
445  //Point to the Authenticate-Request packet
446  authReqPacket = netBufferAt(buffer, offset);
447 
448  //Format packet header
449  authReqPacket->code = PAP_CODE_AUTH_REQ;
450  authReqPacket->identifier = ++context->papFsm.identifier;
451  authReqPacket->length = htons(length);
452 
453  //The Peer-ID-Length field indicates the length of Peer-ID field
454  authReqPacket->peerIdLength = usernameLen;
455  //Append Peer-ID
456  memcpy(authReqPacket->peerId, context->username, usernameLen);
457 
458  //Point to the Passwd-Length field
459  p = authReqPacket->peerId + usernameLen;
460  //The Passwd-Length field indicates the length of Password field
461  p[0] = passwordLen;
462 
463  //Append Password
464  memcpy(p + 1, context->password, passwordLen);
465 
466  //Adjust the length of the multi-part buffer
467  netBufferSetLength(buffer, offset + length);
468 
469  //Debug message
470  TRACE_INFO("Sending PAP Authenticate-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
471  //Dump packet contents for debugging purpose
472  pppDumpPacket((PppPacket *) authReqPacket, length, PPP_PROTOCOL_PAP);
473 
474  //Send PPP frame
475  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP);
476 
477  //The restart counter is decremented each time a Authenticate-Request is sent
478  if(context->papFsm.restartCounter > 0)
479  context->papFsm.restartCounter--;
480 
481  //Save the time at which the packet was sent
482  context->papFsm.timestamp = osGetSystemTime();
483 
484  //Free previously allocated memory block
485  netBufferFree(buffer);
486  //Return status code
487  return error;
488 }
489 
490 
491 /**
492  * @brief Send Authenticate-Ack packet
493  * @param[in] context PPP context
494  * @param[in] identifier Identifier field
495  * @return Error code
496  **/
497 
499 {
500  error_t error;
501  size_t length;
502  size_t offset;
503  NetBuffer *buffer;
504  PapAuthAckPacket *authAckPacket;
505 
506  //Retrieve the length of the Authenticate-Ack packet
507  length = sizeof(PapAuthAckPacket);
508 
509  //Allocate a buffer memory to hold the Authenticate-Ack packet
510  buffer = pppAllocBuffer(length, &offset);
511  //Failed to allocate memory?
512  if(buffer == NULL)
513  return ERROR_OUT_OF_MEMORY;
514 
515  //Point to the Authenticate-Ack packet
516  authAckPacket = netBufferAt(buffer, offset);
517 
518  //Format packet header
519  authAckPacket->code = PAP_CODE_AUTH_ACK;
520  authAckPacket->identifier = identifier;
521  authAckPacket->length = htons(length);
522 
523  //The Message field is zero or more octets, and its contents are
524  //implementation dependent
525  authAckPacket->msgLength = 0;
526 
527  //Debug message
528  TRACE_INFO("Sending PAP Authenticate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length);
529  //Dump packet contents for debugging purpose
530  pppDumpPacket((PppPacket *) authAckPacket, length, PPP_PROTOCOL_PAP);
531 
532  //Send PPP frame
533  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP);
534 
535  //Free previously allocated memory block
536  netBufferFree(buffer);
537  //Return status code
538  return error;
539 }
540 
541 
542 /**
543  * @brief Send Authenticate-Nak packet
544  * @param[in] context PPP context
545  * @param[in] identifier Identifier field
546  * @return Error code
547  **/
548 
550 {
551  error_t error;
552  size_t length;
553  size_t offset;
554  NetBuffer *buffer;
555  PapAuthNakPacket *authNakPacket;
556 
557  //Retrieve the length of the Authenticate-Nak packet
558  length = sizeof(PapAuthNakPacket);
559 
560  //Allocate a buffer memory to hold the Authenticate-Nak packet
561  buffer = pppAllocBuffer(length, &offset);
562  //Failed to allocate memory?
563  if(buffer == NULL)
564  return ERROR_OUT_OF_MEMORY;
565 
566  //Point to the Authenticate-Nak packet
567  authNakPacket = netBufferAt(buffer, offset);
568 
569  //Format packet header
570  authNakPacket->code = PAP_CODE_AUTH_NAK;
571  authNakPacket->identifier = identifier;
572  authNakPacket->length = htons(length);
573 
574  //The Message field is zero or more octets, and its contents are
575  //implementation dependent
576  authNakPacket->msgLength = 0;
577 
578  //Debug message
579  TRACE_INFO("Sending PAP Authenticate-Nak packet (%" PRIuSIZE " bytes)...\r\n", length);
580  //Dump packet contents for debugging purpose
581  pppDumpPacket((PppPacket *) authNakPacket, length, PPP_PROTOCOL_PAP);
582 
583  //Send PPP frame
584  error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP);
585 
586  //Free previously allocated memory block
587  netBufferFree(buffer);
588  //Return status code
589  return error;
590 }
591 
592 
593 /**
594  * @brief Password verification
595  * @param[in] context PPP context
596  * @param[in] password NULL-terminated string containing the password to be checked
597  * @return TRUE if the password is valid, else FALSE
598  **/
599 
600 bool_t papCheckPassword(PppContext *context, const char_t *password)
601 {
602  size_t n;
603  bool_t status;
604 
605  //This flag tells whether the password is valid
606  status = FALSE;
607 
608  //Retrieve the length of the password
609  n = strlen(password);
610 
611  //Compare the length of the password against the expected value
612  if(n == context->papFsm.passwordLen)
613  {
614  //Check whether the password is valid
615  if(!memcmp(password, context->papFsm.password, n))
616  status = TRUE;
617  }
618 
619  //Return TRUE is the password is valid, else FALSE
620  return status;
621 }
622 
623 #endif
uint32_t systime_t
Definition: compiler_port.h:44
Authentication phase.
Definition: ppp.h:166
char char_t
Definition: compiler_port.h:41
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
IPV6CP (PPP IPv6 Control Protocol)
Data logging functions for debugging purpose (PPP)
TCP/IP stack core.
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
Debugging facilities.
uint8_t p
Definition: ndp.h:295
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
bool_t papCheckPassword(PppContext *context, const char_t *password)
Password verification.
Definition: pap.c:600
Network-layer protocol phase.
Definition: ppp.h:167
error_t lcpClose(PppContext *context)
LCP Close event.
Definition: lcp.c:101
__start_packed struct @286 PapAuthAckPacket
Authenticate-Ack packet.
#define htons(value)
Definition: cpu_endian.h:390
void papProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
Process an incoming PAP packet.
Definition: pap.c:147
#define PppPacket
Definition: ppp.h:35
error_t ipcpOpen(PppContext *context)
IPCP Open event.
Definition: ipcp.c:74
#define PPP_MAX_USERNAME_LEN
Definition: ppp.h:66
#define TRUE
Definition: os_port.h:48
error_t papProcessAuthReq(PppContext *context, const PapAuthReqPacket *authReqPacket, size_t length)
Process Authenticate-Request packet.
Definition: pap.c:212
__start_packed struct @287 PapAuthNakPacket
Authenticate-Nak packet.
Password Authentication Protocol.
Definition: ppp.h:202
#define ntohs(value)
Definition: cpu_endian.h:396
Authenticate-Ack.
Definition: pap.h:87
#define PAP_MAX_REQUESTS
Definition: pap.h:52
error_t papSendAuthReq(PppContext *context)
Send Authenticate-Request packet.
Definition: pap.c:420
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
#define PAP_RESTART_TIMER
Definition: pap.h:45
LCP (PPP Link Control Protocol)
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
Authenticate-Nak.
Definition: pap.h:88
uint8_t identifier[]
error_t papProcessAuthAck(PppContext *context, const PapAuthAckPacket *authAckPacket, size_t length)
Process Authenticate-Ack packet.
Definition: pap.c:328
#define PppContext
Definition: ppp.h:36
#define TRACE_INFO(...)
Definition: debug.h:86
error_t papSendAuthAck(PppContext *context, uint8_t identifier)
Send Authenticate-Ack packet.
Definition: pap.c:498
Success.
Definition: error.h:42
error_t papProcessAuthNak(PppContext *context, const PapAuthNakPacket *authNakPacket, size_t length)
Process Authenticate-Nak packet.
Definition: pap.c:385
__start_packed struct @285 PapAuthReqPacket
Authenticate-Request packet.
void papTick(PppContext *context)
PAP timer handler.
Definition: pap.c:108
error_t
Error codes.
Definition: error.h:40
#define PRIuSIZE
Definition: compiler_port.h:72
Authenticate-Request.
Definition: pap.h:86
error_t pppDumpPacket(const PppPacket *packet, size_t length, PppProtocol protocol)
Dump LCP/NCP packet for debugging purpose.
Definition: ppp_debug.c:141
error_t pppSendFrame(NetInterface *interface, NetBuffer *buffer, size_t offset, uint16_t protocol)
Send a PPP frame.
Definition: ppp.c:1004
error_t papSendAuthNak(PppContext *context, uint8_t identifier)
Send Authenticate-Nak packet.
Definition: pap.c:549
error_t ipv6cpOpen(PppContext *context)
IPV6CP Open event.
Definition: ipv6cp.c:75
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
IPCP (PPP Internet Protocol Control Protocol)
int bool_t
Definition: compiler_port.h:47
NetBuffer * pppAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a PPP frame.
Definition: ppp.c:1263