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