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