ReactOS  0.4.15-dev-1207-g698a8e6
ppp.c
Go to the documentation of this file.
1 /*****************************************************************************
2 * ppp.c - Network Point to Point Protocol program file.
3 *
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
6 *
7 * The authors hereby grant permission to use, copy, modify, distribute,
8 * and license this software and its documentation for any purpose, provided
9 * that existing copyright notices are retained in all copies and that this
10 * notice and the following disclaimer are included verbatim in any
11 * distributions. No written agreement, license, or royalty fee is required
12 * for any of the authorized uses.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 ******************************************************************************
26 * REVISION HISTORY
27 *
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
29 * Ported to lwIP.
30 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
31 * Original.
32 *****************************************************************************/
33 
34 /*
35  * ppp_defs.h - PPP definitions.
36  *
37  * if_pppvar.h - private structures and declarations for PPP.
38  *
39  * Copyright (c) 1994 The Australian National University.
40  * All rights reserved.
41  *
42  * Permission to use, copy, modify, and distribute this software and its
43  * documentation is hereby granted, provided that the above copyright
44  * notice appears in all copies. This software is provided without any
45  * warranty, express or implied. The Australian National University
46  * makes no representations about the suitability of this software for
47  * any purpose.
48  *
49  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
50  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
51  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
52  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
53  * OF SUCH DAMAGE.
54  *
55  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
56  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
57  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
58  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
59  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
60  * OR MODIFICATIONS.
61  */
62 
63 /*
64  * if_ppp.h - Point-to-Point Protocol definitions.
65  *
66  * Copyright (c) 1989 Carnegie Mellon University.
67  * All rights reserved.
68  *
69  * Redistribution and use in source and binary forms are permitted
70  * provided that the above copyright notice and this paragraph are
71  * duplicated in all such forms and that any documentation,
72  * advertising materials, and other materials related to such
73  * distribution and use acknowledge that the software was developed
74  * by Carnegie Mellon University. The name of the
75  * University may not be used to endorse or promote products derived
76  * from this software without specific prior written permission.
77  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
78  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
79  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
80  */
81 
82 #include "lwip/opt.h"
83 
84 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
85 
86 #include "ppp_impl.h"
87 #include "lwip/ip.h" /* for ip_input() */
88 
89 #include "pppdebug.h"
90 
91 #include "randm.h"
92 #include "fsm.h"
93 #if PAP_SUPPORT
94 #include "pap.h"
95 #endif /* PAP_SUPPORT */
96 #if CHAP_SUPPORT
97 #include "chap.h"
98 #endif /* CHAP_SUPPORT */
99 #include "ipcp.h"
100 #include "lcp.h"
101 #include "magic.h"
102 #include "auth.h"
103 #if VJ_SUPPORT
104 #include "vj.h"
105 #endif /* VJ_SUPPORT */
106 #if PPPOE_SUPPORT
107 #include "netif/ppp_oe.h"
108 #endif /* PPPOE_SUPPORT */
109 
110 #include "lwip/tcpip.h"
111 #include "lwip/api.h"
112 #include "lwip/snmp.h"
113 
114 #include <string.h>
115 
116 /*************************/
117 /*** LOCAL DEFINITIONS ***/
118 /*************************/
119 
124 #ifndef PPP_INPROC_MULTITHREADED
125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0)
126 #endif
127 
131 #ifndef PPP_INPROC_OWNTHREAD
132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED
133 #endif
134 
135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED
136  #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1"
137 #endif
138 
139 /*
140  * The basic PPP frame.
141  */
142 #define PPP_ADDRESS(p) (((u_char *)(p))[0])
143 #define PPP_CONTROL(p) (((u_char *)(p))[1])
144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
145 
146 /* PPP packet parser states. Current state indicates operation yet to be
147  * completed. */
148 typedef enum {
149  PDIDLE = 0, /* Idle state - waiting. */
150  PDSTART, /* Process start flag. */
151  PDADDRESS, /* Process address field. */
152  PDCONTROL, /* Process control field. */
153  PDPROTOCOL1, /* Process protocol field 1. */
154  PDPROTOCOL2, /* Process protocol field 2. */
155  PDDATA /* Process data byte. */
156 } PPPDevStates;
157 
158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
159 
160 /************************/
161 /*** LOCAL DATA TYPES ***/
162 /************************/
163 
165 #ifndef PPPOS_RX_BUFSIZE
166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN)
167 #endif
168 
169 typedef struct PPPControlRx_s {
171  int pd;
173  sio_fd_t fd;
175 #if PPP_INPROC_OWNTHREAD
176  u_char rxbuf[PPPOS_RX_BUFSIZE];
177 #endif /* PPP_INPROC_OWNTHREAD */
178 
179  /* The input packet. */
180  struct pbuf *inHead, *inTail;
181 
182 #if PPPOS_SUPPORT
183  u16_t inProtocol; /* The input protocol code. */
184  u16_t inFCS; /* Input Frame Check Sequence value. */
185 #endif /* PPPOS_SUPPORT */
186  PPPDevStates inState; /* The input process state. */
187  char inEscaped; /* Escape next character. */
188  ext_accm inACCM; /* Async-Ctl-Char-Map for input. */
189 } PPPControlRx;
190 
191 /*
192  * PPP interface control block.
193  */
194 typedef struct PPPControl_s {
195  PPPControlRx rx;
196  char openFlag; /* True when in use. */
197 #if PPPOE_SUPPORT
198  struct netif *ethif;
199  struct pppoe_softc *pppoe_sc;
200 #endif /* PPPOE_SUPPORT */
201  int if_up; /* True when the interface is up. */
202  int errCode; /* Code indicating why interface is down. */
203 #if PPPOS_SUPPORT
204  sio_fd_t fd; /* File device ID of port. */
205 #endif /* PPPOS_SUPPORT */
206  u16_t mtu; /* Peer's mru */
207  int pcomp; /* Does peer accept protocol compression? */
208  int accomp; /* Does peer accept addr/ctl compression? */
209  u_long lastXMit; /* Time of last transmission. */
210  ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
211 #if PPPOS_SUPPORT && VJ_SUPPORT
212  int vjEnabled; /* Flag indicating VJ compression enabled. */
213  struct vjcompress vjComp; /* Van Jacobson compression header. */
214 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
215 
216  struct netif netif;
217 
218  struct ppp_addrs addrs;
219 
220  void (*linkStatusCB)(void *ctx, int errCode, void *arg);
221  void *linkStatusCtx;
222 
223 } PPPControl;
224 
225 
226 /*
227  * Ioctl definitions.
228  */
229 
230 struct npioctl {
231  int protocol; /* PPP procotol, e.g. PPP_IP */
232  enum NPmode mode;
233 };
234 
235 
236 
237 /***********************************/
238 /*** LOCAL FUNCTION DECLARATIONS ***/
239 /***********************************/
240 #if PPPOS_SUPPORT
241 #if PPP_INPROC_OWNTHREAD
242 static void pppInputThread(void *arg);
243 #endif /* PPP_INPROC_OWNTHREAD */
244 static void pppDrop(PPPControlRx *pcrx);
245 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l);
246 static void pppFreeCurrentInputPacket(PPPControlRx *pcrx);
247 #endif /* PPPOS_SUPPORT */
248 
249 
250 /******************************/
251 /*** PUBLIC DATA STRUCTURES ***/
252 /******************************/
253 u_long subnetMask;
254 
255 static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */
256 
257 /*
258  * PPP Data Link Layer "protocol" table.
259  * One entry per supported protocol.
260  * The last entry must be NULL.
261  */
262 struct protent *ppp_protocols[] = {
263  &lcp_protent,
264 #if PAP_SUPPORT
265  &pap_protent,
266 #endif /* PAP_SUPPORT */
267 #if CHAP_SUPPORT
268  &chap_protent,
269 #endif /* CHAP_SUPPORT */
270 #if CBCP_SUPPORT
271  &cbcp_protent,
272 #endif /* CBCP_SUPPORT */
273  &ipcp_protent,
274 #if CCP_SUPPORT
275  &ccp_protent,
276 #endif /* CCP_SUPPORT */
277  NULL
278 };
279 
280 
281 /*
282  * Buffers for outgoing packets. This must be accessed only from the appropriate
283  * PPP task so that it doesn't need to be protected to avoid collisions.
284  */
285 u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
286 
287 
288 /*****************************/
289 /*** LOCAL DATA STRUCTURES ***/
290 /*****************************/
291 
292 #if PPPOS_SUPPORT
293 /*
294  * FCS lookup table as calculated by genfcstab.
295  * @todo: smaller, slower implementation for lower memory footprint?
296  */
297 static const u_short fcstab[256] = {
298  0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
299  0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
300  0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
301  0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
302  0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
303  0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
304  0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
305  0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
306  0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
307  0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
308  0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
309  0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
310  0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
311  0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
312  0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
313  0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
314  0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
315  0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
316  0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
317  0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
318  0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
319  0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
320  0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
321  0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
322  0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
323  0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
324  0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
325  0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
326  0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
327  0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
328  0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
329  0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
330 };
331 
332 /* PPP's Asynchronous-Control-Character-Map. The mask array is used
333  * to select the specific bit for a character. */
334 static u_char pppACCMMask[] = {
335  0x01,
336  0x02,
337  0x04,
338  0x08,
339  0x10,
340  0x20,
341  0x40,
342  0x80
343 };
344 
345 #if PPP_INPROC_OWNTHREAD
346 
347 static void
348 pppRecvWakeup(int pd)
349 {
350  PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
351  if (pppControl[pd].openFlag != 0) {
352  sio_read_abort(pppControl[pd].fd);
353  }
354 }
355 #endif /* PPP_INPROC_OWNTHREAD */
356 #endif /* PPPOS_SUPPORT */
357 
358 void
359 pppLinkTerminated(int pd)
360 {
361  PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd));
362 
363 #if PPPOE_SUPPORT
364  if (pppControl[pd].ethif) {
365  pppoe_disconnect(pppControl[pd].pppoe_sc);
366  } else
367 #endif /* PPPOE_SUPPORT */
368  {
369 #if PPPOS_SUPPORT
370  PPPControl* pc;
371 #if PPP_INPROC_OWNTHREAD
372  pppRecvWakeup(pd);
373 #endif /* PPP_INPROC_OWNTHREAD */
374  pc = &pppControl[pd];
375 
376  PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
377  if (pc->linkStatusCB) {
378  pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
379  }
380 
381  pc->openFlag = 0;
382 #endif /* PPPOS_SUPPORT */
383  }
384  PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n"));
385 }
386 
387 void
388 pppLinkDown(int pd)
389 {
390  PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd));
391 
392 #if PPPOE_SUPPORT
393  if (pppControl[pd].ethif) {
394  pppoe_disconnect(pppControl[pd].pppoe_sc);
395  } else
396 #endif /* PPPOE_SUPPORT */
397  {
398 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
399  pppRecvWakeup(pd);
400 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD*/
401  }
402 }
403 
405 static void
406 pppStart(int pd)
407 {
408  PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd));
409  lcp_lowerup(pd);
410  lcp_open(pd); /* Start protocol */
411  PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n"));
412 }
413 
415 static void
416 pppStop(int pd)
417 {
418  PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd));
419  lcp_close(pd, "User request");
420 }
421 
423 static void
424 pppHup(int pd)
425 {
426  PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd));
427  lcp_lowerdown(pd);
428  link_terminated(pd);
429 }
430 
431 /***********************************/
432 /*** PUBLIC FUNCTION DEFINITIONS ***/
433 /***********************************/
434 /* Initialize the PPP subsystem. */
435 
436 struct ppp_settings ppp_settings;
437 
438 void
439 pppInit(void)
440 {
441  struct protent *protp;
442  int i, j;
443 
444  memset(&ppp_settings, 0, sizeof(ppp_settings));
445  ppp_settings.usepeerdns = 1;
446  pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
447 
448  magicInit();
449 
450  subnetMask = PP_HTONL(0xffffff00UL);
451 
452  for (i = 0; i < NUM_PPP; i++) {
453  /* Initialize each protocol to the standard option set. */
454  for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
455  (*protp->init)(i);
456  }
457  }
458 }
459 
460 void
461 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
462 {
463  switch(authType) {
464  case PPPAUTHTYPE_NONE:
465  default:
466 #ifdef LWIP_PPP_STRICT_PAP_REJECT
467  ppp_settings.refuse_pap = 1;
468 #else /* LWIP_PPP_STRICT_PAP_REJECT */
469  /* some providers request pap and accept an empty login/pw */
470  ppp_settings.refuse_pap = 0;
471 #endif /* LWIP_PPP_STRICT_PAP_REJECT */
472  ppp_settings.refuse_chap = 1;
473  break;
474 
475  case PPPAUTHTYPE_ANY:
476  /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
477  * RFC 1994 says:
478  *
479  * In practice, within or associated with each PPP server, there is a
480  * database which associates "user" names with authentication
481  * information ("secrets"). It is not anticipated that a particular
482  * named user would be authenticated by multiple methods. This would
483  * make the user vulnerable to attacks which negotiate the least secure
484  * method from among a set (such as PAP rather than CHAP). If the same
485  * secret was used, PAP would reveal the secret to be used later with
486  * CHAP.
487  *
488  * Instead, for each user name there should be an indication of exactly
489  * one method used to authenticate that user name. If a user needs to
490  * make use of different authentication methods under different
491  * circumstances, then distinct user names SHOULD be employed, each of
492  * which identifies exactly one authentication method.
493  *
494  */
495  ppp_settings.refuse_pap = 0;
496  ppp_settings.refuse_chap = 0;
497  break;
498 
499  case PPPAUTHTYPE_PAP:
500  ppp_settings.refuse_pap = 0;
501  ppp_settings.refuse_chap = 1;
502  break;
503 
504  case PPPAUTHTYPE_CHAP:
505  ppp_settings.refuse_pap = 1;
506  ppp_settings.refuse_chap = 0;
507  break;
508  }
509 
510  if(user) {
511  strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
512  ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
513  } else {
514  ppp_settings.user[0] = '\0';
515  }
516 
517  if(passwd) {
518  strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
519  ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
520  } else {
521  ppp_settings.passwd[0] = '\0';
522  }
523 }
524 
525 #if PPPOS_SUPPORT
526 
536 int
537 pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx)
538 {
539  PPPControl *pc;
540  int pd;
541 
542  if (linkStatusCB == NULL) {
543  /* PPP is single-threaded: without a callback,
544  * there is no way to know when the link is up. */
545  return PPPERR_PARAM;
546  }
547 
548  /* Find a free PPP session descriptor. */
549  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
550 
551  if (pd >= NUM_PPP) {
552  pd = PPPERR_OPEN;
553  } else {
554  pc = &pppControl[pd];
555  /* input pbuf left over from last session? */
556  pppFreeCurrentInputPacket(&pc->rx);
557  /* @todo: is this correct or do I overwrite something? */
558  memset(pc, 0, sizeof(PPPControl));
559  pc->rx.pd = pd;
560  pc->rx.fd = fd;
561 
562  pc->openFlag = 1;
563  pc->fd = fd;
564 
565 #if VJ_SUPPORT
566  vj_compress_init(&pc->vjComp);
567 #endif /* VJ_SUPPORT */
568 
569  /*
570  * Default the in and out accm so that escape and flag characters
571  * are always escaped.
572  */
573  pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */
574  pc->outACCM[15] = 0x60;
575 
576  pc->linkStatusCB = linkStatusCB;
577  pc->linkStatusCtx = linkStatusCtx;
578 
579  /*
580  * Start the connection and handle incoming events (packet or timeout).
581  */
582  PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd));
583  pppStart(pd);
584 #if PPP_INPROC_OWNTHREAD
585  sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
586 #endif /* PPP_INPROC_OWNTHREAD */
587  }
588 
589  return pd;
590 }
591 #endif /* PPPOS_SUPPORT */
592 
593 #if PPPOE_SUPPORT
594 static void pppOverEthernetLinkStatusCB(int pd, int up);
595 
596 void
597 pppOverEthernetClose(int pd)
598 {
599  PPPControl* pc = &pppControl[pd];
600 
601  /* *TJL* There's no lcp_deinit */
602  lcp_close(pd, NULL);
603 
604  pppoe_destroy(&pc->netif);
605 }
606 
607 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name,
608  pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx)
609 {
610  PPPControl *pc;
611  int pd;
612 
614  LWIP_UNUSED_ARG(concentrator_name);
615 
616  if (linkStatusCB == NULL) {
617  /* PPP is single-threaded: without a callback,
618  * there is no way to know when the link is up. */
619  return PPPERR_PARAM;
620  }
621 
622  /* Find a free PPP session descriptor. Critical region? */
623  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
624  if (pd >= NUM_PPP) {
625  pd = PPPERR_OPEN;
626  } else {
627  pc = &pppControl[pd];
628  memset(pc, 0, sizeof(PPPControl));
629  pc->openFlag = 1;
630  pc->ethif = ethif;
631 
632  pc->linkStatusCB = linkStatusCB;
633  pc->linkStatusCtx = linkStatusCtx;
634 
635  lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
639 
640  lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
644 
645  if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
646  pc->openFlag = 0;
647  return PPPERR_OPEN;
648  }
649 
650  pppoe_connect(pc->pppoe_sc);
651  }
652 
653  return pd;
654 }
655 #endif /* PPPOE_SUPPORT */
656 
657 
658 /* Close a PPP connection and release the descriptor.
659  * Any outstanding packets in the queues are dropped.
660  * Return 0 on success, an error code on failure. */
661 int
662 pppClose(int pd)
663 {
664  PPPControl *pc = &pppControl[pd];
665  int st = 0;
666 
667  PPPDEBUG(LOG_DEBUG, ("pppClose() called\n"));
668 
669  /* Disconnect */
670 #if PPPOE_SUPPORT
671  if(pc->ethif) {
672  PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
673  pc->errCode = PPPERR_USER;
674  /* This will leave us at PHASE_DEAD. */
675  pppStop(pd);
676  } else
677 #endif /* PPPOE_SUPPORT */
678  {
679 #if PPPOS_SUPPORT
680  PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
681  pc->errCode = PPPERR_USER;
682  /* This will leave us at PHASE_DEAD. */
683  pppStop(pd);
684 #if PPP_INPROC_OWNTHREAD
685  pppRecvWakeup(pd);
686 #endif /* PPP_INPROC_OWNTHREAD */
687 #endif /* PPPOS_SUPPORT */
688  }
689 
690  return st;
691 }
692 
693 /* This function is called when carrier is lost on the PPP channel. */
694 void
695 pppSigHUP(int pd)
696 {
697  PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
698  pppHup(pd);
699 }
700 
701 #if PPPOS_SUPPORT
702 static void
703 nPut(PPPControl *pc, struct pbuf *nb)
704 {
705  struct pbuf *b;
706  int c;
707 
708  for(b = nb; b != NULL; b = b->next) {
709  if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
711  ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c));
712  LINK_STATS_INC(link.err);
713  pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
714  snmp_inc_ifoutdiscards(&pc->netif);
715  pbuf_free(nb);
716  return;
717  }
718  }
719 
720  snmp_add_ifoutoctets(&pc->netif, nb->tot_len);
721  snmp_inc_ifoutucastpkts(&pc->netif);
722  pbuf_free(nb);
723  LINK_STATS_INC(link.xmit);
724 }
725 
726 /*
727  * pppAppend - append given character to end of given pbuf. If outACCM
728  * is not NULL and the character needs to be escaped, do so.
729  * If pbuf is full, append another.
730  * Return the current pbuf.
731  */
732 static struct pbuf *
733 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
734 {
735  struct pbuf *tb = nb;
736 
737  /* Make sure there is room for the character and an escape code.
738  * Sure we don't quite fill the buffer if the character doesn't
739  * get escaped but is one character worth complicating this? */
740  /* Note: We assume no packet header. */
741  if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
743  if (tb) {
744  nb->next = tb;
745  } else {
746  LINK_STATS_INC(link.memerr);
747  }
748  nb = tb;
749  }
750 
751  if (nb) {
752  if (outACCM && ESCAPE_P(*outACCM, c)) {
753  *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
754  *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
755  } else {
756  *((u_char*)nb->payload + nb->len++) = c;
757  }
758  }
759 
760  return tb;
761 }
762 #endif /* PPPOS_SUPPORT */
763 
764 #if PPPOE_SUPPORT
765 static err_t
766 pppifOutputOverEthernet(int pd, struct pbuf *p)
767 {
768  PPPControl *pc = &pppControl[pd];
769  struct pbuf *pb;
770  u_short protocol = PPP_IP;
771  int i=0;
772  u16_t tot_len;
773 
774  /* @todo: try to use pbuf_header() here! */
775  pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM);
776  if(!pb) {
777  LINK_STATS_INC(link.memerr);
778  LINK_STATS_INC(link.proterr);
779  snmp_inc_ifoutdiscards(&pc->netif);
780  return ERR_MEM;
781  }
782 
783  pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
784 
785  pc->lastXMit = sys_jiffies();
786 
787  if (!pc->pcomp || protocol > 0xFF) {
788  *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
789  }
790  *((u_char*)pb->payload + i) = protocol & 0xFF;
791 
792  pbuf_chain(pb, p);
793  tot_len = pb->tot_len;
794 
795  if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
796  LINK_STATS_INC(link.err);
797  snmp_inc_ifoutdiscards(&pc->netif);
798  return PPPERR_DEVICE;
799  }
800 
801  snmp_add_ifoutoctets(&pc->netif, tot_len);
802  snmp_inc_ifoutucastpkts(&pc->netif);
803  LINK_STATS_INC(link.xmit);
804  return ERR_OK;
805 }
806 #endif /* PPPOE_SUPPORT */
807 
808 /* Send a packet on the given connection. */
809 static err_t
810 pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr)
811 {
812  int pd = (int)(size_t)netif->state;
813  PPPControl *pc = &pppControl[pd];
814 #if PPPOS_SUPPORT
815  u_short protocol = PPP_IP;
816  u_int fcsOut = PPP_INITFCS;
817  struct pbuf *headMB = NULL, *tailMB = NULL, *p;
818  u_char c;
819 #endif /* PPPOS_SUPPORT */
820 
821  LWIP_UNUSED_ARG(ipaddr);
822 
823  /* Validate parameters. */
824  /* We let any protocol value go through - it can't hurt us
825  * and the peer will just drop it if it's not accepting it. */
826  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
827  PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n",
828  pd, PPP_IP, pb));
829  LINK_STATS_INC(link.opterr);
830  LINK_STATS_INC(link.drop);
832  return ERR_ARG;
833  }
834 
835  /* Check that the link is up. */
836  if (lcp_phase[pd] == PHASE_DEAD) {
837  PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd));
838  LINK_STATS_INC(link.rterr);
839  LINK_STATS_INC(link.drop);
841  return ERR_RTE;
842  }
843 
844 #if PPPOE_SUPPORT
845  if(pc->ethif) {
846  return pppifOutputOverEthernet(pd, pb);
847  }
848 #endif /* PPPOE_SUPPORT */
849 
850 #if PPPOS_SUPPORT
851  /* Grab an output buffer. */
852  headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
853  if (headMB == NULL) {
854  PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd));
855  LINK_STATS_INC(link.memerr);
856  LINK_STATS_INC(link.drop);
858  return ERR_MEM;
859  }
860 
861 #if VJ_SUPPORT
862  /*
863  * Attempt Van Jacobson header compression if VJ is configured and
864  * this is an IP packet.
865  */
866  if (protocol == PPP_IP && pc->vjEnabled) {
867  switch (vj_compress_tcp(&pc->vjComp, pb)) {
868  case TYPE_IP:
869  /* No change...
870  protocol = PPP_IP_PROTOCOL; */
871  break;
872  case TYPE_COMPRESSED_TCP:
873  protocol = PPP_VJC_COMP;
874  break;
876  protocol = PPP_VJC_UNCOMP;
877  break;
878  default:
879  PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd));
880  LINK_STATS_INC(link.proterr);
881  LINK_STATS_INC(link.drop);
883  pbuf_free(headMB);
884  return ERR_VAL;
885  }
886  }
887 #endif /* VJ_SUPPORT */
888 
889  tailMB = headMB;
890 
891  /* Build the PPP header. */
892  if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
893  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
894  }
895 
896  pc->lastXMit = sys_jiffies();
897  if (!pc->accomp) {
898  fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
899  tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
900  fcsOut = PPP_FCS(fcsOut, PPP_UI);
901  tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
902  }
903  if (!pc->pcomp || protocol > 0xFF) {
904  c = (protocol >> 8) & 0xFF;
905  fcsOut = PPP_FCS(fcsOut, c);
906  tailMB = pppAppend(c, tailMB, &pc->outACCM);
907  }
908  c = protocol & 0xFF;
909  fcsOut = PPP_FCS(fcsOut, c);
910  tailMB = pppAppend(c, tailMB, &pc->outACCM);
911 
912  /* Load packet. */
913  for(p = pb; p; p = p->next) {
914  int n;
915  u_char *sPtr;
916 
917  sPtr = (u_char*)p->payload;
918  n = p->len;
919  while (n-- > 0) {
920  c = *sPtr++;
921 
922  /* Update FCS before checking for special characters. */
923  fcsOut = PPP_FCS(fcsOut, c);
924 
925  /* Copy to output buffer escaping special characters. */
926  tailMB = pppAppend(c, tailMB, &pc->outACCM);
927  }
928  }
929 
930  /* Add FCS and trailing flag. */
931  c = ~fcsOut & 0xFF;
932  tailMB = pppAppend(c, tailMB, &pc->outACCM);
933  c = (~fcsOut >> 8) & 0xFF;
934  tailMB = pppAppend(c, tailMB, &pc->outACCM);
935  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
936 
937  /* If we failed to complete the packet, throw it away. */
938  if (!tailMB) {
940  ("pppifOutput[%d]: Alloc err - dropping proto=%d\n",
941  pd, protocol));
942  pbuf_free(headMB);
943  LINK_STATS_INC(link.memerr);
944  LINK_STATS_INC(link.drop);
946  return ERR_MEM;
947  }
948 
949  /* Send it. */
950  PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol));
951 
952  nPut(pc, headMB);
953 #endif /* PPPOS_SUPPORT */
954 
955  return ERR_OK;
956 }
957 
958 /* Get and set parameters for the given connection.
959  * Return 0 on success, an error code on failure. */
960 int
961 pppIOCtl(int pd, int cmd, void *arg)
962 {
963  PPPControl *pc = &pppControl[pd];
964  int st = 0;
965 
966  if (pd < 0 || pd >= NUM_PPP) {
967  st = PPPERR_PARAM;
968  } else {
969  switch(cmd) {
970  case PPPCTLG_UPSTATUS: /* Get the PPP up status. */
971  if (arg) {
972  *(int *)arg = (int)(pc->if_up);
973  } else {
974  st = PPPERR_PARAM;
975  }
976  break;
977  case PPPCTLS_ERRCODE: /* Set the PPP error code. */
978  if (arg) {
979  pc->errCode = *(int *)arg;
980  } else {
981  st = PPPERR_PARAM;
982  }
983  break;
984  case PPPCTLG_ERRCODE: /* Get the PPP error code. */
985  if (arg) {
986  *(int *)arg = (int)(pc->errCode);
987  } else {
988  st = PPPERR_PARAM;
989  }
990  break;
991 #if PPPOS_SUPPORT
992  case PPPCTLG_FD: /* Get the fd associated with the ppp */
993  if (arg) {
994  *(sio_fd_t *)arg = pc->fd;
995  } else {
996  st = PPPERR_PARAM;
997  }
998  break;
999 #endif /* PPPOS_SUPPORT */
1000  default:
1001  st = PPPERR_PARAM;
1002  break;
1003  }
1004  }
1005 
1006  return st;
1007 }
1008 
1009 /*
1010  * Return the Maximum Transmission Unit for the given PPP connection.
1011  */
1012 u_short
1013 pppMTU(int pd)
1014 {
1015  PPPControl *pc = &pppControl[pd];
1016  u_short st;
1017 
1018  /* Validate parameters. */
1019  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1020  st = 0;
1021  } else {
1022  st = pc->mtu;
1023  }
1024 
1025  return st;
1026 }
1027 
1028 #if PPPOE_SUPPORT
1029 int
1030 pppWriteOverEthernet(int pd, const u_char *s, int n)
1031 {
1032  PPPControl *pc = &pppControl[pd];
1033  struct pbuf *pb;
1034 
1035  /* skip address & flags */
1036  s += 2;
1037  n -= 2;
1038 
1039  LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff);
1040  pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM);
1041  if(!pb) {
1042  LINK_STATS_INC(link.memerr);
1043  LINK_STATS_INC(link.proterr);
1044  snmp_inc_ifoutdiscards(&pc->netif);
1045  return PPPERR_ALLOC;
1046  }
1047 
1048  pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
1049 
1050  pc->lastXMit = sys_jiffies();
1051 
1052  MEMCPY(pb->payload, s, n);
1053 
1054  if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
1055  LINK_STATS_INC(link.err);
1056  snmp_inc_ifoutdiscards(&pc->netif);
1057  return PPPERR_DEVICE;
1058  }
1059 
1060  snmp_add_ifoutoctets(&pc->netif, (u16_t)n);
1061  snmp_inc_ifoutucastpkts(&pc->netif);
1062  LINK_STATS_INC(link.xmit);
1063  return PPPERR_NONE;
1064 }
1065 #endif /* PPPOE_SUPPORT */
1066 
1067 /*
1068  * Write n characters to a ppp link.
1069  * RETURN: >= 0 Number of characters written
1070  * -1 Failed to write to device
1071  */
1072 int
1073 pppWrite(int pd, const u_char *s, int n)
1074 {
1075  PPPControl *pc = &pppControl[pd];
1076 #if PPPOS_SUPPORT
1077  u_char c;
1078  u_int fcsOut;
1079  struct pbuf *headMB, *tailMB;
1080 #endif /* PPPOS_SUPPORT */
1081 
1082 #if PPPOE_SUPPORT
1083  if(pc->ethif) {
1084  return pppWriteOverEthernet(pd, s, n);
1085  }
1086 #endif /* PPPOE_SUPPORT */
1087 
1088 #if PPPOS_SUPPORT
1089  headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1090  if (headMB == NULL) {
1091  LINK_STATS_INC(link.memerr);
1092  LINK_STATS_INC(link.proterr);
1093  snmp_inc_ifoutdiscards(&pc->netif);
1094  return PPPERR_ALLOC;
1095  }
1096 
1097  tailMB = headMB;
1098 
1099  /* If the link has been idle, we'll send a fresh flag character to
1100  * flush any noise. */
1101  if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
1102  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
1103  }
1104  pc->lastXMit = sys_jiffies();
1105 
1106  fcsOut = PPP_INITFCS;
1107  /* Load output buffer. */
1108  while (n-- > 0) {
1109  c = *s++;
1110 
1111  /* Update FCS before checking for special characters. */
1112  fcsOut = PPP_FCS(fcsOut, c);
1113 
1114  /* Copy to output buffer escaping special characters. */
1115  tailMB = pppAppend(c, tailMB, &pc->outACCM);
1116  }
1117 
1118  /* Add FCS and trailing flag. */
1119  c = ~fcsOut & 0xFF;
1120  tailMB = pppAppend(c, tailMB, &pc->outACCM);
1121  c = (~fcsOut >> 8) & 0xFF;
1122  tailMB = pppAppend(c, tailMB, &pc->outACCM);
1123  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
1124 
1125  /* If we failed to complete the packet, throw it away.
1126  * Otherwise send it. */
1127  if (!tailMB) {
1129  ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
1130  /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1131  pbuf_free(headMB);
1132  LINK_STATS_INC(link.memerr);
1133  LINK_STATS_INC(link.proterr);
1134  snmp_inc_ifoutdiscards(&pc->netif);
1135  return PPPERR_ALLOC;
1136  }
1137 
1138  PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len));
1139  /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1140  nPut(pc, headMB);
1141 #endif /* PPPOS_SUPPORT */
1142 
1143  return PPPERR_NONE;
1144 }
1145 
1146 /*
1147  * ppp_send_config - configure the transmit characteristics of
1148  * the ppp interface.
1149  */
1150 void
1151 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp)
1152 {
1153  PPPControl *pc = &pppControl[unit];
1154  int i;
1155 
1156  pc->mtu = mtu;
1157  pc->pcomp = pcomp;
1158  pc->accomp = accomp;
1159 
1160  /* Load the ACCM bits for the 32 control codes. */
1161  for (i = 0; i < 32/8; i++) {
1162  pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
1163  }
1164  PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n",
1165  unit,
1166  pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
1167 }
1168 
1169 
1170 /*
1171  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1172  */
1173 void
1174 ppp_set_xaccm(int unit, ext_accm *accm)
1175 {
1176  SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
1177  PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
1178  unit,
1179  pppControl[unit].outACCM[0],
1180  pppControl[unit].outACCM[1],
1181  pppControl[unit].outACCM[2],
1182  pppControl[unit].outACCM[3]));
1183 }
1184 
1185 
1186 /*
1187  * ppp_recv_config - configure the receive-side characteristics of
1188  * the ppp interface.
1189  */
1190 void
1191 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
1192 {
1193  PPPControl *pc = &pppControl[unit];
1194  int i;
1195  SYS_ARCH_DECL_PROTECT(lev);
1196 
1197  LWIP_UNUSED_ARG(accomp);
1198  LWIP_UNUSED_ARG(pcomp);
1199  LWIP_UNUSED_ARG(mru);
1200 
1201  /* Load the ACCM bits for the 32 control codes. */
1202  SYS_ARCH_PROTECT(lev);
1203  for (i = 0; i < 32 / 8; i++) {
1204  /* @todo: does this work? ext_accm has been modified from pppd! */
1205  pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8));
1206  }
1207  SYS_ARCH_UNPROTECT(lev);
1208  PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
1209  unit,
1210  pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3]));
1211 }
1212 
1213 #if 0
1214 /*
1215  * ccp_test - ask kernel whether a given compression method
1216  * is acceptable for use. Returns 1 if the method and parameters
1217  * are OK, 0 if the method is known but the parameters are not OK
1218  * (e.g. code size should be reduced), or -1 if the method is unknown.
1219  */
1220 int
1221 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr)
1222 {
1223  return 0; /* XXX Currently no compression. */
1224 }
1225 
1226 /*
1227  * ccp_flags_set - inform kernel about the current state of CCP.
1228  */
1229 void
1230 ccp_flags_set(int unit, int isopen, int isup)
1231 {
1232  /* XXX */
1233 }
1234 
1235 /*
1236  * ccp_fatal_error - returns 1 if decompression was disabled as a
1237  * result of an error detected after decompression of a packet,
1238  * 0 otherwise. This is necessary because of patent nonsense.
1239  */
1240 int
1241 ccp_fatal_error(int unit)
1242 {
1243  /* XXX */
1244  return 0;
1245 }
1246 #endif
1247 
1248 /*
1249  * get_idle_time - return how long the link has been idle.
1250  */
1251 int
1252 get_idle_time(int u, struct ppp_idle *ip)
1253 {
1254  /* XXX */
1255  LWIP_UNUSED_ARG(u);
1257 
1258  return 0;
1259 }
1260 
1261 
1262 /*
1263  * Return user specified netmask, modified by any mask we might determine
1264  * for address `addr' (in network byte order).
1265  * Here we scan through the system's list of interfaces, looking for
1266  * any non-point-to-point interfaces which might appear to be on the same
1267  * network as `addr'. If we find any, we OR in their netmask to the
1268  * user-specified netmask.
1269  */
1270 u32_t
1271 GetMask(u32_t addr)
1272 {
1273  u32_t mask, nmask;
1274 
1275  addr = htonl(addr);
1276  if (IP_CLASSA(addr)) { /* determine network mask for address class */
1277  nmask = IP_CLASSA_NET;
1278  } else if (IP_CLASSB(addr)) {
1279  nmask = IP_CLASSB_NET;
1280  } else {
1281  nmask = IP_CLASSC_NET;
1282  }
1283 
1284  /* class D nets are disallowed by bad_ip_adrs */
1285  mask = subnetMask | htonl(nmask);
1286 
1287  /* XXX
1288  * Scan through the system's network interfaces.
1289  * Get each netmask and OR them into our mask.
1290  */
1291 
1292  return mask;
1293 }
1294 
1295 /*
1296  * sifvjcomp - config tcp header compression
1297  */
1298 int
1299 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid)
1300 {
1301 #if PPPOS_SUPPORT && VJ_SUPPORT
1302  PPPControl *pc = &pppControl[pd];
1303 
1304  pc->vjEnabled = vjcomp;
1305  pc->vjComp.compressSlot = cidcomp;
1306  pc->vjComp.maxSlotIndex = maxcid;
1307  PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
1308  vjcomp, cidcomp, maxcid));
1309 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1310  LWIP_UNUSED_ARG(pd);
1311  LWIP_UNUSED_ARG(vjcomp);
1312  LWIP_UNUSED_ARG(cidcomp);
1313  LWIP_UNUSED_ARG(maxcid);
1314 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1315 
1316  return 0;
1317 }
1318 
1319 /*
1320  * pppifNetifInit - netif init callback
1321  */
1322 static err_t
1323 pppifNetifInit(struct netif *netif)
1324 {
1325  netif->name[0] = 'p';
1326  netif->name[1] = 'p';
1327  netif->output = pppifOutput;
1328  netif->mtu = pppMTU((int)(size_t)netif->state);
1330 #if LWIP_NETIF_HOSTNAME
1331  /* @todo: Initialize interface hostname */
1332  /* netif_set_hostname(netif, "lwip"); */
1333 #endif /* LWIP_NETIF_HOSTNAME */
1334  return ERR_OK;
1335 }
1336 
1337 
1338 /*
1339  * sifup - Config the interface up and enable IP packets to pass.
1340  */
1341 int
1342 sifup(int pd)
1343 {
1344  PPPControl *pc = &pppControl[pd];
1345  int st = 1;
1346 
1347  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1348  st = 0;
1349  PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
1350  } else {
1351  netif_remove(&pc->netif);
1352  if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask,
1353  &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) {
1354  netif_set_up(&pc->netif);
1355  pc->if_up = 1;
1356  pc->errCode = PPPERR_NONE;
1357 
1358  PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1359  if (pc->linkStatusCB) {
1360  pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
1361  }
1362  } else {
1363  st = 0;
1364  PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd));
1365  }
1366  }
1367 
1368  return st;
1369 }
1370 
1371 /*
1372  * sifnpmode - Set the mode for handling packets for a given NP.
1373  */
1374 int
1375 sifnpmode(int u, int proto, enum NPmode mode)
1376 {
1377  LWIP_UNUSED_ARG(u);
1380  return 0;
1381 }
1382 
1383 /*
1384  * sifdown - Config the interface down and disable IP.
1385  */
1386 int
1387 sifdown(int pd)
1388 {
1389  PPPControl *pc = &pppControl[pd];
1390  int st = 1;
1391 
1392  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1393  st = 0;
1394  PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd));
1395  } else {
1396  pc->if_up = 0;
1397  /* make sure the netif status callback is called */
1398  netif_set_down(&pc->netif);
1399  netif_remove(&pc->netif);
1400  PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1401  if (pc->linkStatusCB) {
1402  pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
1403  }
1404  }
1405  return st;
1406 }
1407 
1417 int
1418 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
1419 {
1420  PPPControl *pc = &pppControl[pd];
1421  int st = 1;
1422 
1423  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1424  st = 0;
1425  PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
1426  } else {
1427  SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
1428  SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
1429  SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
1430  SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
1431  SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
1432  }
1433  return st;
1434 }
1435 
1443 int
1444 cifaddr( int pd, u32_t o, u32_t h)
1445 {
1446  PPPControl *pc = &pppControl[pd];
1447  int st = 1;
1448 
1449  LWIP_UNUSED_ARG(o);
1450  LWIP_UNUSED_ARG(h);
1451  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1452  st = 0;
1453  PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
1454  } else {
1455  IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
1456  IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
1457  IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
1458  IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
1459  IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
1460  }
1461  return st;
1462 }
1463 
1464 /*
1465  * sifdefaultroute - assign a default route through the address given.
1466  */
1467 int
1468 sifdefaultroute(int pd, u32_t l, u32_t g)
1469 {
1470  PPPControl *pc = &pppControl[pd];
1471  int st = 1;
1472 
1473  LWIP_UNUSED_ARG(l);
1474  LWIP_UNUSED_ARG(g);
1475 
1476  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1477  st = 0;
1478  PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
1479  } else {
1480  netif_set_default(&pc->netif);
1481  }
1482 
1483  /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1484 
1485  return st;
1486 }
1487 
1488 /*
1489  * cifdefaultroute - delete a default route through the address given.
1490  */
1491 int
1492 cifdefaultroute(int pd, u32_t l, u32_t g)
1493 {
1494  PPPControl *pc = &pppControl[pd];
1495  int st = 1;
1496 
1497  LWIP_UNUSED_ARG(l);
1498  LWIP_UNUSED_ARG(g);
1499 
1500  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1501  st = 0;
1502  PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
1503  } else {
1505  }
1506 
1507  return st;
1508 }
1509 
1510 /**********************************/
1511 /*** LOCAL FUNCTION DEFINITIONS ***/
1512 /**********************************/
1513 
1514 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
1515 /* The main PPP process function. This implements the state machine according
1516  * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1517 static void
1518 pppInputThread(void *arg)
1519 {
1520  int count;
1521  PPPControlRx *pcrx = arg;
1522 
1523  while (lcp_phase[pcrx->pd] != PHASE_DEAD) {
1524  count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE);
1525  if(count > 0) {
1526  pppInProc(pcrx, pcrx->rxbuf, count);
1527  } else {
1528  /* nothing received, give other tasks a chance to run */
1529  sys_msleep(1);
1530  }
1531  }
1532 }
1533 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */
1534 
1535 #if PPPOE_SUPPORT
1536 
1537 void
1538 pppOverEthernetInitFailed(int pd)
1539 {
1540  PPPControl* pc;
1541 
1542  pppHup(pd);
1543  pppStop(pd);
1544 
1545  pc = &pppControl[pd];
1546  pppoe_destroy(&pc->netif);
1547  pc->openFlag = 0;
1548 
1549  if(pc->linkStatusCB) {
1550  pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1551  }
1552 }
1553 
1554 static void
1555 pppOverEthernetLinkStatusCB(int pd, int up)
1556 {
1557  if(up) {
1558  PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd));
1559  pppStart(pd);
1560  } else {
1561  pppOverEthernetInitFailed(pd);
1562  }
1563 }
1564 #endif /* PPPOE_SUPPORT */
1565 
1566 struct pbuf *
1567 pppSingleBuf(struct pbuf *p)
1568 {
1569  struct pbuf *q, *b;
1570  u_char *pl;
1571 
1572  if(p->tot_len == p->len) {
1573  return p;
1574  }
1575 
1576  q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1577  if(!q) {
1578  PPPDEBUG(LOG_ERR,
1579  ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
1580  return p; /* live dangerously */
1581  }
1582 
1583  for(b = p, pl = q->payload; b != NULL; b = b->next) {
1584  MEMCPY(pl, b->payload, b->len);
1585  pl += b->len;
1586  }
1587 
1588  pbuf_free(p);
1589 
1590  return q;
1591 }
1592 
1593 struct pppInputHeader {
1594  int unit;
1595  u16_t proto;
1596 };
1597 
1598 /*
1599  * Pass the processed input packet to the appropriate handler.
1600  * This function and all handlers run in the context of the tcpip_thread
1601  */
1602 static void
1603 pppInput(void *arg)
1604 {
1605  struct pbuf *nb = (struct pbuf *)arg;
1606  u16_t protocol;
1607  int pd;
1608 
1609  pd = ((struct pppInputHeader *)nb->payload)->unit;
1610  protocol = ((struct pppInputHeader *)nb->payload)->proto;
1611 
1612  if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) {
1613  LWIP_ASSERT("pbuf_header failed\n", 0);
1614  goto drop;
1615  }
1616 
1617  LINK_STATS_INC(link.recv);
1618  snmp_inc_ifinucastpkts(&pppControl[pd].netif);
1619  snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len);
1620 
1621  /*
1622  * Toss all non-LCP packets unless LCP is OPEN.
1623  * Until we get past the authentication phase, toss all packets
1624  * except LCP, LQR and authentication packets.
1625  */
1626  if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
1627  if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
1628  (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
1629  PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd]));
1630  goto drop;
1631  }
1632  }
1633 
1634  switch(protocol) {
1635  case PPP_VJC_COMP: /* VJ compressed TCP */
1636 #if PPPOS_SUPPORT && VJ_SUPPORT
1637  PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
1638  /*
1639  * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1640  * pass the result to IP.
1641  */
1642  if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) {
1643  pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1644  return;
1645  }
1646  /* Something's wrong so drop it. */
1647  PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd));
1648 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1649  /* No handler for this protocol so drop the packet. */
1650  PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
1651 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1652  break;
1653 
1654  case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
1655 #if PPPOS_SUPPORT && VJ_SUPPORT
1656  PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
1657  /*
1658  * Process the TCP/IP header for VJ header compression and then pass
1659  * the packet to IP.
1660  */
1661  if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) {
1662  pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1663  return;
1664  }
1665  /* Something's wrong so drop it. */
1666  PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd));
1667 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1668  /* No handler for this protocol so drop the packet. */
1670  ("pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1671  pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
1672 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1673  break;
1674 
1675  case PPP_IP: /* Internet Protocol */
1676  PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
1677  if (pppControl[pd].netif.input) {
1678  pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1679  return;
1680  }
1681  break;
1682 
1683  default: {
1684  struct protent *protp;
1685  int i;
1686 
1687  /*
1688  * Upcall the proper protocol input routine.
1689  */
1690  for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
1691  if (protp->protocol == protocol && protp->enabled_flag) {
1692  PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
1693  nb = pppSingleBuf(nb);
1694  (*protp->input)(pd, nb->payload, nb->len);
1695  PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd));
1696  goto out;
1697  }
1698  }
1699 
1700  /* No handler for this protocol so reject the packet. */
1701  PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len));
1702  if (pbuf_header(nb, sizeof(protocol))) {
1703  LWIP_ASSERT("pbuf_header failed\n", 0);
1704  goto drop;
1705  }
1706 #if BYTE_ORDER == LITTLE_ENDIAN
1707  protocol = htons(protocol);
1708 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
1709  SMEMCPY(nb->payload, &protocol, sizeof(protocol));
1710  lcp_sprotrej(pd, nb->payload, nb->len);
1711  }
1712  break;
1713  }
1714 
1715 drop:
1716  LINK_STATS_INC(link.drop);
1717  snmp_inc_ifindiscards(&pppControl[pd].netif);
1718 
1719 out:
1720  pbuf_free(nb);
1721  return;
1722 }
1723 
1724 #if PPPOS_SUPPORT
1725 /*
1726  * Drop the input packet.
1727  */
1728 static void
1729 pppFreeCurrentInputPacket(PPPControlRx *pcrx)
1730 {
1731  if (pcrx->inHead != NULL) {
1732  if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) {
1733  pbuf_free(pcrx->inTail);
1734  }
1735  pbuf_free(pcrx->inHead);
1736  pcrx->inHead = NULL;
1737  }
1738  pcrx->inTail = NULL;
1739 }
1740 
1741 /*
1742  * Drop the input packet and increase error counters.
1743  */
1744 static void
1745 pppDrop(PPPControlRx *pcrx)
1746 {
1747  if (pcrx->inHead != NULL) {
1748 #if 0
1749  PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload));
1750 #endif
1751  PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead));
1752  }
1753  pppFreeCurrentInputPacket(pcrx);
1754 #if VJ_SUPPORT
1755  vj_uncompress_err(&pppControl[pcrx->pd].vjComp);
1756 #endif /* VJ_SUPPORT */
1757 
1758  LINK_STATS_INC(link.drop);
1759  snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
1760 }
1761 
1762 #if !PPP_INPROC_OWNTHREAD
1763 
1770 void
1771 pppos_input(int pd, u_char* data, int len)
1772 {
1773  pppInProc(&pppControl[pd].rx, data, len);
1774 }
1775 #endif
1776 
1780 static void
1781 pppInProc(PPPControlRx *pcrx, u_char *s, int l)
1782 {
1783  struct pbuf *nextNBuf;
1784  u_char curChar;
1785  u_char escaped;
1786  SYS_ARCH_DECL_PROTECT(lev);
1787 
1788  PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l));
1789  while (l-- > 0) {
1790  curChar = *s++;
1791 
1792  SYS_ARCH_PROTECT(lev);
1793  escaped = ESCAPE_P(pcrx->inACCM, curChar);
1794  SYS_ARCH_UNPROTECT(lev);
1795  /* Handle special characters. */
1796  if (escaped) {
1797  /* Check for escape sequences. */
1798  /* XXX Note that this does not handle an escaped 0x5d character which
1799  * would appear as an escape character. Since this is an ASCII ']'
1800  * and there is no reason that I know of to escape it, I won't complicate
1801  * the code to handle this case. GLL */
1802  if (curChar == PPP_ESCAPE) {
1803  pcrx->inEscaped = 1;
1804  /* Check for the flag character. */
1805  } else if (curChar == PPP_FLAG) {
1806  /* If this is just an extra flag character, ignore it. */
1807  if (pcrx->inState <= PDADDRESS) {
1808  /* ignore it */;
1809  /* If we haven't received the packet header, drop what has come in. */
1810  } else if (pcrx->inState < PDDATA) {
1812  ("pppInProc[%d]: Dropping incomplete packet %d\n",
1813  pcrx->pd, pcrx->inState));
1814  LINK_STATS_INC(link.lenerr);
1815  pppDrop(pcrx);
1816  /* If the fcs is invalid, drop the packet. */
1817  } else if (pcrx->inFCS != PPP_GOODFCS) {
1819  ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
1820  pcrx->pd, pcrx->inFCS, pcrx->inProtocol));
1821  /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
1822  LINK_STATS_INC(link.chkerr);
1823  pppDrop(pcrx);
1824  /* Otherwise it's a good packet so pass it on. */
1825  } else {
1826  struct pbuf *inp;
1827  /* Trim off the checksum. */
1828  if(pcrx->inTail->len >= 2) {
1829  pcrx->inTail->len -= 2;
1830 
1831  pcrx->inTail->tot_len = pcrx->inTail->len;
1832  if (pcrx->inTail != pcrx->inHead) {
1833  pbuf_cat(pcrx->inHead, pcrx->inTail);
1834  }
1835  } else {
1836  pcrx->inTail->tot_len = pcrx->inTail->len;
1837  if (pcrx->inTail != pcrx->inHead) {
1838  pbuf_cat(pcrx->inHead, pcrx->inTail);
1839  }
1840 
1841  pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2);
1842  }
1843 
1844  /* Dispatch the packet thereby consuming it. */
1845  inp = pcrx->inHead;
1846  /* Packet consumed, release our references. */
1847  pcrx->inHead = NULL;
1848  pcrx->inTail = NULL;
1849 #if PPP_INPROC_MULTITHREADED
1850  if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) {
1851  PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
1852  pbuf_free(inp);
1853  LINK_STATS_INC(link.drop);
1854  snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
1855  }
1856 #else /* PPP_INPROC_MULTITHREADED */
1857  pppInput(inp);
1858 #endif /* PPP_INPROC_MULTITHREADED */
1859  }
1860 
1861  /* Prepare for a new packet. */
1862  pcrx->inFCS = PPP_INITFCS;
1863  pcrx->inState = PDADDRESS;
1864  pcrx->inEscaped = 0;
1865  /* Other characters are usually control characters that may have
1866  * been inserted by the physical layer so here we just drop them. */
1867  } else {
1869  ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar));
1870  }
1871  /* Process other characters. */
1872  } else {
1873  /* Unencode escaped characters. */
1874  if (pcrx->inEscaped) {
1875  pcrx->inEscaped = 0;
1876  curChar ^= PPP_TRANS;
1877  }
1878 
1879  /* Process character relative to current state. */
1880  switch(pcrx->inState) {
1881  case PDIDLE: /* Idle state - waiting. */
1882  /* Drop the character if it's not 0xff
1883  * we would have processed a flag character above. */
1884  if (curChar != PPP_ALLSTATIONS) {
1885  break;
1886  }
1887 
1888  /* Fall through */
1889  case PDSTART: /* Process start flag. */
1890  /* Prepare for a new packet. */
1891  pcrx->inFCS = PPP_INITFCS;
1892 
1893  /* Fall through */
1894  case PDADDRESS: /* Process address field. */
1895  if (curChar == PPP_ALLSTATIONS) {
1896  pcrx->inState = PDCONTROL;
1897  break;
1898  }
1899  /* Else assume compressed address and control fields so
1900  * fall through to get the protocol... */
1901  case PDCONTROL: /* Process control field. */
1902  /* If we don't get a valid control code, restart. */
1903  if (curChar == PPP_UI) {
1904  pcrx->inState = PDPROTOCOL1;
1905  break;
1906  }
1907 #if 0
1908  else {
1910  ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar));
1911  pcrx->inState = PDSTART;
1912  }
1913 #endif
1914  case PDPROTOCOL1: /* Process protocol field 1. */
1915  /* If the lower bit is set, this is the end of the protocol
1916  * field. */
1917  if (curChar & 1) {
1918  pcrx->inProtocol = curChar;
1919  pcrx->inState = PDDATA;
1920  } else {
1921  pcrx->inProtocol = (u_int)curChar << 8;
1922  pcrx->inState = PDPROTOCOL2;
1923  }
1924  break;
1925  case PDPROTOCOL2: /* Process protocol field 2. */
1926  pcrx->inProtocol |= curChar;
1927  pcrx->inState = PDDATA;
1928  break;
1929  case PDDATA: /* Process data byte. */
1930  /* Make space to receive processed data. */
1931  if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
1932  if (pcrx->inTail != NULL) {
1933  pcrx->inTail->tot_len = pcrx->inTail->len;
1934  if (pcrx->inTail != pcrx->inHead) {
1935  pbuf_cat(pcrx->inHead, pcrx->inTail);
1936  /* give up the inTail reference now */
1937  pcrx->inTail = NULL;
1938  }
1939  }
1940  /* If we haven't started a packet, we need a packet header. */
1941  nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1942  if (nextNBuf == NULL) {
1943  /* No free buffers. Drop the input packet and let the
1944  * higher layers deal with it. Continue processing
1945  * the received pbuf chain in case a new packet starts. */
1946  PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd));
1947  LINK_STATS_INC(link.memerr);
1948  pppDrop(pcrx);
1949  pcrx->inState = PDSTART; /* Wait for flag sequence. */
1950  break;
1951  }
1952  if (pcrx->inHead == NULL) {
1953  struct pppInputHeader *pih = nextNBuf->payload;
1954 
1955  pih->unit = pcrx->pd;
1956  pih->proto = pcrx->inProtocol;
1957 
1958  nextNBuf->len += sizeof(*pih);
1959 
1960  pcrx->inHead = nextNBuf;
1961  }
1962  pcrx->inTail = nextNBuf;
1963  }
1964  /* Load character into buffer. */
1965  ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar;
1966  break;
1967  }
1968 
1969  /* update the frame check sequence number. */
1970  pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar);
1971  }
1972  } /* while (l-- > 0), all bytes processed */
1973 
1974  avRandomize();
1975 }
1976 #endif /* PPPOS_SUPPORT */
1977 
1978 #if PPPOE_SUPPORT
1979 void
1980 pppInProcOverEthernet(int pd, struct pbuf *pb)
1981 {
1982  struct pppInputHeader *pih;
1983  u16_t inProtocol;
1984 
1985  if(pb->len < sizeof(inProtocol)) {
1986  PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n"));
1987  goto drop;
1988  }
1989 
1990  inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
1991 
1992  /* make room for pppInputHeader - should not fail */
1993  if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
1994  PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n"));
1995  goto drop;
1996  }
1997 
1998  pih = pb->payload;
1999 
2000  pih->unit = pd;
2001  pih->proto = inProtocol;
2002 
2003  /* Dispatch the packet thereby consuming it. */
2004  pppInput(pb);
2005  return;
2006 
2007 drop:
2008  LINK_STATS_INC(link.drop);
2009  snmp_inc_ifindiscards(&pppControl[pd].netif);
2010  pbuf_free(pb);
2011  return;
2012 }
2013 #endif /* PPPOE_SUPPORT */
2014 
2015 #if LWIP_NETIF_STATUS_CALLBACK
2016 
2023 void
2024 ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback)
2025 {
2026  netif_set_status_callback(&pppControl[pd].netif, status_callback);
2027 }
2028 #endif /* LWIP_NETIF_STATUS_CALLBACK */
2029 
2030 #if LWIP_NETIF_LINK_CALLBACK
2031 
2038 void
2039 ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback)
2040 {
2041  netif_set_link_callback(&pppControl[pd].netif, link_callback);
2042 }
2043 #endif /* LWIP_NETIF_LINK_CALLBACK */
2044 
2045 #endif /* PPP_SUPPORT */
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define PP_HTONL(x)
Definition: def.h:90
#define snmp_add_ifinoctets(ni, value)
Definition: snmp.h:245
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.c:280
u16_t tot_len
Definition: pbuf.h:93
#define snmp_add_ifoutoctets(ni, value)
Definition: snmp.h:249
#define ERR_ARG
Definition: err.h:70
void(* netif_status_callback_fn)(struct netif *netif)
Definition: netif.h:128
#define SMEMCPY(dst, src, len)
Definition: opt.h:92
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define PPPDEBUG(a, b)
Definition: pppdebug.h:69
u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)
unsigned long u_long
Definition: linux.h:269
struct pbuf * next
Definition: pbuf.h:81
#define ERR_RTE
Definition: err.h:56
u16_t len
Definition: pbuf.h:96
#define LOG_WARNING
Definition: syslog.h:49
#define htonl(x)
Definition: module.h:212
Definition: ftp_var.h:139
int vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp)
Definition: vj.h:133
GLuint GLuint GLsizei count
Definition: gl.h:1545
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define IP_CLASSC_NET
Definition: ip_addr.h:121
lcp_options lcp_allowoptions[]
struct protent lcp_protent
#define IP_CLASSB(a)
Definition: ip_addr.h:114
#define TYPE_IP
Definition: vj.h:78
u_int neg_asyncmap
Definition: lcp.h:88
GLdouble n
Definition: glext.h:7729
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:212
err_t ip_input(struct pbuf *p, struct netif *inp)
Definition: ip.c:305
static int fd
Definition: io.c:51
#define NETIF_FLAG_LINK_UP
Definition: netif.h:84
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
void * arg
Definition: msvc.h:10
netif_output_fn output
Definition: netif.h:151
void vj_compress_init(struct vjcompress *comp)
void netif_set_default(struct netif *netif)
Definition: netif.c:430
#define LOG_DEBUG
Definition: syslog.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
Definition: ftp.c:950
const GLfloat * m
Definition: glext.h:10848
#define snmp_inc_ifindiscards(ni)
Definition: snmp.h:248
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
Definition: pbuf.h:58
#define up(mutex)
Definition: glue.h:30
#define LOG_DETAIL
Definition: pppdebug.h:45
while(1)
Definition: macro.lex.yy.c:740
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition: ip_addr.h:139
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLenum GLint GLuint mask
Definition: glext.h:6028
void netif_set_up(struct netif *netif)
Definition: netif.c:453
Definition: pbuf.h:53
#define ERR_VAL
Definition: err.h:58
#define LWIP_MIN(x, y)
Definition: def.h:44
void sio_read_abort(sio_fd_t fd)
lcp_options lcp_wantoptions[]
png_const_structrp png_const_inforp int * unit
Definition: png.h:2161
#define PPP_THREAD_NAME
Definition: opt.h:1300
smooth NULL
Definition: ftsmooth.c:416
u_int neg_pcompression
Definition: lcp.h:92
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
s8_t err_t
Definition: err.h:47
Definition: pbuf.h:54
struct protent ipcp_protent
#define TYPE_COMPRESSED_TCP
Definition: vj.h:80
#define IP_CLASSB_NET
Definition: ip_addr.h:115
#define b
Definition: ke_i.h:79
#define PPP_THREAD_PRIO
Definition: opt.h:1318
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
void lcp_open(int)
struct netif * netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:139
void link_terminated(int)
r l[0]
Definition: byte_order.h:167
#define ERR_OK
Definition: err.h:52
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:786
void lcp_lowerdown(int)
GLboolean GLboolean g
Definition: glext.h:6204
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
void lcp_sprotrej(int, u_char *, int)
Definition: dhcpd.h:61
Definition: pbuf.h:79
unsigned long u32_t
Definition: cc.h:25
u8_t flags
Definition: netif.h:192
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
Definition: pbuf.h:61
u_int neg_accompression
Definition: lcp.h:93
#define LINK_STATS_INC(x)
Definition: stats.h:227
const GLubyte * c
Definition: glext.h:8905
#define NETIF_FLAG_POINTTOPOINT
Definition: netif.h:75
#define X16_F
Definition: cc.h:38
static FILE * out
Definition: regtests2xml.c:44
static char service_name[100]
Definition: netif.h:136
void netif_remove(struct netif *netif)
Definition: netif.c:235
#define SZT_F
Definition: arch.h:47
static const WCHAR tb[]
Definition: suminfo.c:286
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
u_int vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb)
#define LOG_ERR
Definition: syslog.h:48
#define SYS_ARCH_PROTECT(lev)
Definition: cc.h:55
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
unsigned short u_short
Definition: types.h:81
#define snmp_inc_ifoutucastpkts(ni)
Definition: snmp.h:250
void vj_uncompress_err(struct vjcompress *comp)
#define snmp_inc_ifoutdiscards(ni)
Definition: snmp.h:252
GLenum const GLvoid * addr
Definition: glext.h:9621
void lcp_lowerup(int)
#define PBUF_POOL_BUFSIZE
Definition: opt.h:1104
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
u16_t mtu
Definition: netif.h:186
#define PPP_THREAD_STACKSIZE
Definition: opt.h:1309
GLenum mode
Definition: glext.h:6217
void netif_set_down(struct netif *netif)
Definition: netif.c:490
UINT32 u_int
Definition: types.h:82
#define ERR_MEM
Definition: fontsub.h:52
void * state
Definition: netif.h:172
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:745
u32_t sys_jiffies(void)
unsigned char u8_t
Definition: cc.h:23
#define min(a, b)
Definition: monoChain.cc:55
netif_input_fn input
Definition: netif.h:147
void * payload
Definition: pbuf.h:84
u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)
#define SYS_ARCH_DECL_PROTECT(lev)
Definition: cc.h:54
char name[2]
Definition: netif.h:194
#define IP_CLASSA(a)
Definition: ip_addr.h:108
#define SYS_ARCH_UNPROTECT(lev)
Definition: cc.h:56
#define c
Definition: ke_i.h:80
#define snmp_inc_ifinucastpkts(ni)
Definition: snmp.h:246
void lcp_close(int, char *)
void magicInit(void)
#define IP_CLASSA_NET
Definition: ip_addr.h:109
unsigned short u16_t
Definition: cc.h:24
const WCHAR * link
Definition: db.cpp:989
struct protent chap_protent
GLfloat GLfloat p
Definition: glext.h:8902
#define htons(x)
Definition: module.h:213
#define TYPE_UNCOMPRESSED_TCP
Definition: vj.h:79
UCHAR u_char
Definition: types.h:80
void sys_msleep(u32_t ms)
Definition: sys.c:55
#define memset(x, y, z)
Definition: compat.h:39
#define X8_F
Definition: arch.h:52
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
void user(int argc, const char *argv[])
Definition: cmds.c:1350
LinkPhase lcp_phase[NUM_PPP]
#define LOG_INFO
Definition: syslog.h:51
void avRandomize(void)
int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp)
u_short mru
Definition: lcp.h:101
signed short s16_t
Definition: cc.h:29
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31