The Pedigree Project  0.1
upap.c
1 /*
2  * upap.c - User/Password Authentication Protocol.
3  *
4  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The name "Carnegie Mellon University" must not be used to
19  * endorse or promote products derived from this software without
20  * prior written permission. For permission or any legal
21  * details, please contact
22  * Office of Technology Transfer
23  * Carnegie Mellon University
24  * 5000 Forbes Avenue
25  * Pittsburgh, PA 15213-3890
26  * (412) 268-4387, fax: (412) 268-7395
27  * tech-transfer@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  * acknowledgment:
31  * "This product includes software developed by Computing Services
32  * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  */
42 
43 #include "netif/ppp/ppp_opts.h"
44 #if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
45 
46 /*
47  * @todo:
48  */
49 
50 #if 0 /* UNUSED */
51 #include <stdio.h>
52 #include <string.h>
53 #endif /* UNUSED */
54 
55 #include "netif/ppp/ppp_impl.h"
56 
57 #include "netif/ppp/upap.h"
58 
59 #if PPP_OPTIONS
60 /*
61  * Command-line options.
62  */
63 static option_t pap_option_list[] = {
64  { "hide-password", o_bool, &hide_password,
65  "Don't output passwords to log", OPT_PRIO | 1 },
66  { "show-password", o_bool, &hide_password,
67  "Show password string in debug log messages", OPT_PRIOSUB | 0 },
68 
69  { "pap-restart", o_int, &upap[0].us_timeouttime,
70  "Set retransmit timeout for PAP", OPT_PRIO },
71  { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
72  "Set max number of transmissions for auth-reqs", OPT_PRIO },
73  { "pap-timeout", o_int, &upap[0].us_reqtimeout,
74  "Set time limit for peer PAP authentication", OPT_PRIO },
75 
76  { NULL }
77 };
78 #endif /* PPP_OPTIONS */
79 
80 /*
81  * Protocol entry points.
82  */
83 static void upap_init(ppp_pcb *pcb);
84 static void upap_lowerup(ppp_pcb *pcb);
85 static void upap_lowerdown(ppp_pcb *pcb);
86 static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87 static void upap_protrej(ppp_pcb *pcb);
88 #if PRINTPKT_SUPPORT
89 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90 #endif /* PRINTPKT_SUPPORT */
91 
92 const struct protent pap_protent = {
93  PPP_PAP,
94  upap_init,
95  upap_input,
96  upap_protrej,
97  upap_lowerup,
98  upap_lowerdown,
99  NULL,
100  NULL,
101 #if PRINTPKT_SUPPORT
102  upap_printpkt,
103 #endif /* PRINTPKT_SUPPORT */
104 #if PPP_DATAINPUT
105  NULL,
106 #endif /* PPP_DATAINPUT */
107 #if PRINTPKT_SUPPORT
108  "PAP",
109  NULL,
110 #endif /* PRINTPKT_SUPPORT */
111 #if PPP_OPTIONS
112  pap_option_list,
113  NULL,
114 #endif /* PPP_OPTIONS */
115 #if DEMAND_SUPPORT
116  NULL,
117  NULL
118 #endif /* DEMAND_SUPPORT */
119 };
120 
121 static void upap_timeout(void *arg);
122 #if PPP_SERVER
123 static void upap_reqtimeout(void *arg);
124 static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125 #endif /* PPP_SERVER */
126 static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128 static void upap_sauthreq(ppp_pcb *pcb);
129 #if PPP_SERVER
130 static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen);
131 #endif /* PPP_SERVER */
132 
133 
134 /*
135  * upap_init - Initialize a UPAP unit.
136  */
137 static void upap_init(ppp_pcb *pcb) {
138  pcb->upap.us_user = NULL;
139  pcb->upap.us_userlen = 0;
140  pcb->upap.us_passwd = NULL;
141  pcb->upap.us_passwdlen = 0;
142  pcb->upap.us_clientstate = UPAPCS_INITIAL;
143 #if PPP_SERVER
144  pcb->upap.us_serverstate = UPAPSS_INITIAL;
145 #endif /* PPP_SERVER */
146  pcb->upap.us_id = 0;
147 }
148 
149 
150 /*
151  * upap_authwithpeer - Authenticate us with our peer (start client).
152  *
153  * Set new state and send authenticate's.
154  */
155 void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) {
156 
157  if(!user || !password)
158  return;
159 
160  /* Save the username and password we're given */
161  pcb->upap.us_user = user;
162  pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff);
163  pcb->upap.us_passwd = password;
164  pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff);
165  pcb->upap.us_transmits = 0;
166 
167  /* Lower layer up yet? */
168  if (pcb->upap.us_clientstate == UPAPCS_INITIAL ||
169  pcb->upap.us_clientstate == UPAPCS_PENDING) {
170  pcb->upap.us_clientstate = UPAPCS_PENDING;
171  return;
172  }
173 
174  upap_sauthreq(pcb); /* Start protocol */
175 }
176 
177 #if PPP_SERVER
178 /*
179  * upap_authpeer - Authenticate our peer (start server).
180  *
181  * Set new state.
182  */
183 void upap_authpeer(ppp_pcb *pcb) {
184 
185  /* Lower layer up yet? */
186  if (pcb->upap.us_serverstate == UPAPSS_INITIAL ||
187  pcb->upap.us_serverstate == UPAPSS_PENDING) {
188  pcb->upap.us_serverstate = UPAPSS_PENDING;
189  return;
190  }
191 
192  pcb->upap.us_serverstate = UPAPSS_LISTEN;
193  if (pcb->settings.pap_req_timeout > 0)
194  TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
195 }
196 #endif /* PPP_SERVER */
197 
198 /*
199  * upap_timeout - Retransmission timer for sending auth-reqs expired.
200  */
201 static void upap_timeout(void *arg) {
202  ppp_pcb *pcb = (ppp_pcb*)arg;
203 
204  if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ)
205  return;
206 
207  if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) {
208  /* give up in disgust */
209  ppp_error("No response to PAP authenticate-requests");
210  pcb->upap.us_clientstate = UPAPCS_BADAUTH;
211  auth_withpeer_fail(pcb, PPP_PAP);
212  return;
213  }
214 
215  upap_sauthreq(pcb); /* Send Authenticate-Request */
216 }
217 
218 
219 #if PPP_SERVER
220 /*
221  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
222  */
223 static void upap_reqtimeout(void *arg) {
224  ppp_pcb *pcb = (ppp_pcb*)arg;
225 
226  if (pcb->upap.us_serverstate != UPAPSS_LISTEN)
227  return; /* huh?? */
228 
229  auth_peer_fail(pcb, PPP_PAP);
230  pcb->upap.us_serverstate = UPAPSS_BADAUTH;
231 }
232 #endif /* PPP_SERVER */
233 
234 
235 /*
236  * upap_lowerup - The lower layer is up.
237  *
238  * Start authenticating if pending.
239  */
240 static void upap_lowerup(ppp_pcb *pcb) {
241 
242  if (pcb->upap.us_clientstate == UPAPCS_INITIAL)
243  pcb->upap.us_clientstate = UPAPCS_CLOSED;
244  else if (pcb->upap.us_clientstate == UPAPCS_PENDING) {
245  upap_sauthreq(pcb); /* send an auth-request */
246  }
247 
248 #if PPP_SERVER
249  if (pcb->upap.us_serverstate == UPAPSS_INITIAL)
250  pcb->upap.us_serverstate = UPAPSS_CLOSED;
251  else if (pcb->upap.us_serverstate == UPAPSS_PENDING) {
252  pcb->upap.us_serverstate = UPAPSS_LISTEN;
253  if (pcb->settings.pap_req_timeout > 0)
254  TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
255  }
256 #endif /* PPP_SERVER */
257 }
258 
259 
260 /*
261  * upap_lowerdown - The lower layer is down.
262  *
263  * Cancel all timeouts.
264  */
265 static void upap_lowerdown(ppp_pcb *pcb) {
266 
267  if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
268  UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */
269 #if PPP_SERVER
270  if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0)
271  UNTIMEOUT(upap_reqtimeout, pcb);
272 #endif /* PPP_SERVER */
273 
274  pcb->upap.us_clientstate = UPAPCS_INITIAL;
275 #if PPP_SERVER
276  pcb->upap.us_serverstate = UPAPSS_INITIAL;
277 #endif /* PPP_SERVER */
278 }
279 
280 
281 /*
282  * upap_protrej - Peer doesn't speak this protocol.
283  *
284  * This shouldn't happen. In any case, pretend lower layer went down.
285  */
286 static void upap_protrej(ppp_pcb *pcb) {
287 
288  if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) {
289  ppp_error("PAP authentication failed due to protocol-reject");
290  auth_withpeer_fail(pcb, PPP_PAP);
291  }
292 #if PPP_SERVER
293  if (pcb->upap.us_serverstate == UPAPSS_LISTEN) {
294  ppp_error("PAP authentication of peer failed (protocol-reject)");
295  auth_peer_fail(pcb, PPP_PAP);
296  }
297 #endif /* PPP_SERVER */
298  upap_lowerdown(pcb);
299 }
300 
301 
302 /*
303  * upap_input - Input UPAP packet.
304  */
305 static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) {
306  u_char *inp;
307  u_char code, id;
308  int len;
309 
310  /*
311  * Parse header (code, id and length).
312  * If packet too short, drop it.
313  */
314  inp = inpacket;
315  if (l < UPAP_HEADERLEN) {
316  UPAPDEBUG(("pap_input: rcvd short header."));
317  return;
318  }
319  GETCHAR(code, inp);
320  GETCHAR(id, inp);
321  GETSHORT(len, inp);
322  if (len < UPAP_HEADERLEN) {
323  UPAPDEBUG(("pap_input: rcvd illegal length."));
324  return;
325  }
326  if (len > l) {
327  UPAPDEBUG(("pap_input: rcvd short packet."));
328  return;
329  }
330  len -= UPAP_HEADERLEN;
331 
332  /*
333  * Action depends on code.
334  */
335  switch (code) {
336  case UPAP_AUTHREQ:
337 #if PPP_SERVER
338  upap_rauthreq(pcb, inp, id, len);
339 #endif /* PPP_SERVER */
340  break;
341 
342  case UPAP_AUTHACK:
343  upap_rauthack(pcb, inp, id, len);
344  break;
345 
346  case UPAP_AUTHNAK:
347  upap_rauthnak(pcb, inp, id, len);
348  break;
349 
350  default: /* XXX Need code reject */
351  break;
352  }
353 }
354 
355 #if PPP_SERVER
356 /*
357  * upap_rauth - Receive Authenticate.
358  */
359 static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
360  u_char ruserlen, rpasswdlen;
361  char *ruser;
362  char *rpasswd;
363  char rhostname[256];
364  int retcode;
365  const char *msg;
366  int msglen;
367 
368  if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
369  return;
370 
371  /*
372  * If we receive a duplicate authenticate-request, we are
373  * supposed to return the same status as for the first request.
374  */
375  if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
376  upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
377  return;
378  }
379  if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
380  upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
381  return;
382  }
383 
384  /*
385  * Parse user/passwd.
386  */
387  if (len < 1) {
388  UPAPDEBUG(("pap_rauth: rcvd short packet."));
389  return;
390  }
391  GETCHAR(ruserlen, inp);
392  len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393  if (len < 0) {
394  UPAPDEBUG(("pap_rauth: rcvd short packet."));
395  return;
396  }
397  ruser = (char *) inp;
398  INCPTR(ruserlen, inp);
399  GETCHAR(rpasswdlen, inp);
400  if (len < rpasswdlen) {
401  UPAPDEBUG(("pap_rauth: rcvd short packet."));
402  return;
403  }
404 
405  rpasswd = (char *) inp;
406 
407  /*
408  * Check the username and password given.
409  */
410  retcode = UPAP_AUTHNAK;
411  if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
412  retcode = UPAP_AUTHACK;
413  }
414  BZERO(rpasswd, rpasswdlen);
415 
416 #if 0 /* UNUSED */
417  /*
418  * Check remote number authorization. A plugin may have filled in
419  * the remote number or added an allowed number, and rather than
420  * return an authenticate failure, is leaving it for us to verify.
421  */
422  if (retcode == UPAP_AUTHACK) {
423  if (!auth_number()) {
424  /* We do not want to leak info about the pap result. */
425  retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
426  warn("calling number %q is not authorized", remote_number);
427  }
428  }
429 
430  msglen = strlen(msg);
431  if (msglen > 255)
432  msglen = 255;
433 #endif /* UNUSED */
434 
435  upap_sresp(pcb, retcode, id, msg, msglen);
436 
437  /* Null terminate and clean remote name. */
438  ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);
439 
440  if (retcode == UPAP_AUTHACK) {
441  pcb->upap.us_serverstate = UPAPSS_OPEN;
442  ppp_notice("PAP peer authentication succeeded for %q", rhostname);
443  auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
444  } else {
445  pcb->upap.us_serverstate = UPAPSS_BADAUTH;
446  ppp_warn("PAP peer authentication failed for %q", rhostname);
447  auth_peer_fail(pcb, PPP_PAP);
448  }
449 
450  if (pcb->settings.pap_req_timeout > 0)
451  UNTIMEOUT(upap_reqtimeout, pcb);
452 }
453 #endif /* PPP_SERVER */
454 
455 /*
456  * upap_rauthack - Receive Authenticate-Ack.
457  */
458 static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) {
459  u_char msglen;
460  char *msg;
461  LWIP_UNUSED_ARG(id);
462 
463  if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
464  return;
465 
466  /*
467  * Parse message.
468  */
469  if (len < 1) {
470  UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
471  } else {
472  GETCHAR(msglen, inp);
473  if (msglen > 0) {
474  len -= sizeof (u_char);
475  if (len < msglen) {
476  UPAPDEBUG(("pap_rauthack: rcvd short packet."));
477  return;
478  }
479  msg = (char *) inp;
480  PRINTMSG(msg, msglen);
481  }
482  }
483 
484  pcb->upap.us_clientstate = UPAPCS_OPEN;
485 
486  auth_withpeer_success(pcb, PPP_PAP, 0);
487 }
488 
489 
490 /*
491  * upap_rauthnak - Receive Authenticate-Nak.
492  */
493 static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
494  u_char msglen;
495  char *msg;
496  LWIP_UNUSED_ARG(id);
497 
498  if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
499  return;
500 
501  /*
502  * Parse message.
503  */
504  if (len < 1) {
505  UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
506  } else {
507  GETCHAR(msglen, inp);
508  if (msglen > 0) {
509  len -= sizeof (u_char);
510  if (len < msglen) {
511  UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
512  return;
513  }
514  msg = (char *) inp;
515  PRINTMSG(msg, msglen);
516  }
517  }
518 
519  pcb->upap.us_clientstate = UPAPCS_BADAUTH;
520 
521  ppp_error("PAP authentication failed");
522  auth_withpeer_fail(pcb, PPP_PAP);
523 }
524 
525 
526 /*
527  * upap_sauthreq - Send an Authenticate-Request.
528  */
529 static void upap_sauthreq(ppp_pcb *pcb) {
530  struct pbuf *p;
531  u_char *outp;
532  int outlen;
533 
534  outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
535  pcb->upap.us_userlen + pcb->upap.us_passwdlen;
536  p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
537  if(NULL == p)
538  return;
539  if(p->tot_len != p->len) {
540  pbuf_free(p);
541  return;
542  }
543 
544  outp = (u_char*)p->payload;
545  MAKEHEADER(outp, PPP_PAP);
546 
547  PUTCHAR(UPAP_AUTHREQ, outp);
548  PUTCHAR(++pcb->upap.us_id, outp);
549  PUTSHORT(outlen, outp);
550  PUTCHAR(pcb->upap.us_userlen, outp);
551  MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
552  INCPTR(pcb->upap.us_userlen, outp);
553  PUTCHAR(pcb->upap.us_passwdlen, outp);
554  MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
555 
556  ppp_write(pcb, p);
557 
558  TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
559  ++pcb->upap.us_transmits;
560  pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
561 }
562 
563 #if PPP_SERVER
564 /*
565  * upap_sresp - Send a response (ack or nak).
566  */
567 static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
568  struct pbuf *p;
569  u_char *outp;
570  int outlen;
571 
572  outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
573  p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
574  if(NULL == p)
575  return;
576  if(p->tot_len != p->len) {
577  pbuf_free(p);
578  return;
579  }
580 
581  outp = (u_char*)p->payload;
582  MAKEHEADER(outp, PPP_PAP);
583 
584  PUTCHAR(code, outp);
585  PUTCHAR(id, outp);
586  PUTSHORT(outlen, outp);
587  PUTCHAR(msglen, outp);
588  MEMCPY(outp, msg, msglen);
589 
590  ppp_write(pcb, p);
591 }
592 #endif /* PPP_SERVER */
593 
594 #if PRINTPKT_SUPPORT
595 /*
596  * upap_printpkt - print the contents of a PAP packet.
597  */
598 static const char* const upap_codenames[] = {
599  "AuthReq", "AuthAck", "AuthNak"
600 };
601 
602 static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
603  int code, id, len;
604  int mlen, ulen, wlen;
605  const u_char *user, *pwd, *msg;
606  const u_char *pstart;
607 
608  if (plen < UPAP_HEADERLEN)
609  return 0;
610  pstart = p;
611  GETCHAR(code, p);
612  GETCHAR(id, p);
613  GETSHORT(len, p);
614  if (len < UPAP_HEADERLEN || len > plen)
615  return 0;
616 
617  if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
618  printer(arg, " %s", upap_codenames[code-1]);
619  else
620  printer(arg, " code=0x%x", code);
621  printer(arg, " id=0x%x", id);
622  len -= UPAP_HEADERLEN;
623  switch (code) {
624  case UPAP_AUTHREQ:
625  if (len < 1)
626  break;
627  ulen = p[0];
628  if (len < ulen + 2)
629  break;
630  wlen = p[ulen + 1];
631  if (len < ulen + wlen + 2)
632  break;
633  user = (const u_char *) (p + 1);
634  pwd = (const u_char *) (p + ulen + 2);
635  p += ulen + wlen + 2;
636  len -= ulen + wlen + 2;
637  printer(arg, " user=");
638  ppp_print_string(user, ulen, printer, arg);
639  printer(arg, " password=");
640 /* FIXME: require ppp_pcb struct as printpkt() argument */
641 #if 0
642  if (!pcb->settings.hide_password)
643 #endif
644  ppp_print_string(pwd, wlen, printer, arg);
645 #if 0
646  else
647  printer(arg, "<hidden>");
648 #endif
649  break;
650  case UPAP_AUTHACK:
651  case UPAP_AUTHNAK:
652  if (len < 1)
653  break;
654  mlen = p[0];
655  if (len < mlen + 1)
656  break;
657  msg = (const u_char *) (p + 1);
658  p += mlen + 1;
659  len -= mlen + 1;
660  printer(arg, " ");
661  ppp_print_string(msg, mlen, printer, arg);
662  break;
663  default:
664  break;
665  }
666 
667  /* print the rest of the bytes in the packet */
668  for (; len > 0; --len) {
669  GETCHAR(code, p);
670  printer(arg, " %.2x", code);
671  }
672 
673  return p - pstart;
674 }
675 #endif /* PRINTPKT_SUPPORT */
676 
677 #endif /* PPP_SUPPORT && PAP_SUPPORT */
u16_t tot_len
Definition: pbuf.h:175
Definition: pbuf.h:113
u16_t len
Definition: pbuf.h:178
Definition: pbuf.h:161
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:327
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
void * payload
Definition: pbuf.h:166