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