1 /*****************************************************************************
2 * ppp.c - Network Point to Point Protocol program file.
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
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.
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.
25 ******************************************************************************
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
30 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
32 *****************************************************************************/
35 * ppp_defs.h - PPP definitions.
37 * if_pppvar.h - private structures and declarations for PPP.
39 * Copyright (c) 1994 The Australian National University.
40 * All rights reserved.
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
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
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,
64 * if_ppp.h - Point-to-Point Protocol definitions.
66 * Copyright (c) 1989 Carnegie Mellon University.
67 * All rights reserved.
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.
84 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
86 #include "lwip/ip.h" /* for ip_input() */
95 #endif /* PAP_SUPPORT */
98 #endif /* CHAP_SUPPORT */
105 #endif /* VJ_SUPPORT */
107 #include "netif/ppp_oe.h"
108 #endif /* PPPOE_SUPPORT */
112 /*************************/
113 /*** LOCAL DEFINITIONS ***/
114 /*************************/
117 * The basic PPP frame.
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])
123 /* PPP packet parser states. Current state indicates operation yet to be
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. */
135 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
137 /************************/
138 /*** LOCAL DATA TYPES ***/
139 /************************/
141 * PPP interface control block.
143 typedef struct PPPControl_s {
144 char openFlag; /* True when in use. */
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. */
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 */
174 struct ppp_addrs addrs;
176 void (*linkStatusCB)(void *ctx, int errCode, void *arg);
187 int protocol; /* PPP procotol, e.g. PPP_IP */
193 /***********************************/
194 /*** LOCAL FUNCTION DECLARATIONS ***/
195 /***********************************/
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 */
203 /******************************/
204 /*** PUBLIC DATA STRUCTURES ***/
205 /******************************/
208 static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */
211 * PPP Data Link Layer "protocol" table.
212 * One entry per supported protocol.
213 * The last entry must be NULL.
215 struct protent *ppp_protocols[] = {
219 #endif /* PAP_SUPPORT */
222 #endif /* CHAP_SUPPORT */
225 #endif /* CBCP_SUPPORT */
229 #endif /* CCP_SUPPORT */
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.
238 u_char *outpacket_buf[NUM_PPP];
241 /*****************************/
242 /*** LOCAL DATA STRUCTURES ***/
243 /*****************************/
247 * FCS lookup table as calculated by genfcstab.
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
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[] = {
299 pppMainWakeup(int pd)
301 PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
302 sio_read_abort(pppControl[pd].fd);
304 #endif /* PPPOS_SUPPORT */
307 pppLinkTerminated(int pd)
309 PPPControl *pc = &pppControl[pd];
311 PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
315 pppoe_disconnect(pc->pppoe_sc);
317 #endif /* PPPOE_SUPPORT */
321 #endif /* PPPOS_SUPPORT */
328 PPPControl *pc = &pppControl[pd];
330 PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
334 pppoe_disconnect(pc->pppoe_sc);
336 #endif /* PPPOE_SUPPORT */
340 #endif /* PPPOS_SUPPORT */
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
351 pppStartCB(void *arg)
355 PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
357 lcp_open(pd); /* Start protocol */
365 PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
366 lcp_close(pd, "User request");
374 PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
379 /***********************************/
380 /*** PUBLIC FUNCTION DEFINITIONS ***/
381 /***********************************/
382 /* Initialize the PPP subsystem. */
384 struct ppp_settings ppp_settings;
389 struct protent *protp;
392 memset(&ppp_settings, 0, sizeof(ppp_settings));
393 ppp_settings.usepeerdns = 1;
394 pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
398 for (i = 0; i < NUM_PPP; i++) {
399 pppControl[i].openFlag = 0;
401 subnetMask = htonl(0xffffff00);
403 outpacket_buf[i] = (u_char *)mem_malloc(PPP_MRU+PPP_HDRLEN);
404 if(!outpacket_buf[i]) {
409 * Initialize to the standard option set.
411 for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
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 */
424 #endif /* PPPOE_SUPPORT */
430 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
433 case PPPAUTHTYPE_NONE:
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;
444 case PPPAUTHTYPE_ANY:
445 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
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
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.
464 ppp_settings.refuse_pap = 0;
465 ppp_settings.refuse_chap = 0;
468 case PPPAUTHTYPE_PAP:
469 ppp_settings.refuse_pap = 0;
470 ppp_settings.refuse_chap = 1;
473 case PPPAUTHTYPE_CHAP:
474 ppp_settings.refuse_pap = 1;
475 ppp_settings.refuse_chap = 0;
480 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
481 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
483 ppp_settings.user[0] = '\0';
487 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
488 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
490 ppp_settings.passwd[0] = '\0';
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. */
503 pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
508 /* Find a free PPP session descriptor. Critical region? */
509 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
514 pppControl[pd].openFlag = !0;
517 /* Launch a deamon thread. */
519 pppControl[pd].openFlag = 1;
522 pc = &pppControl[pd];
526 #endif /* PPPOE_SUPPORT */
531 pc->inState = PDIDLE;
539 vj_compress_init(&pc->vjComp);
540 #endif /* VJ_SUPPORT */
543 * Default the in and out accm so that escape and flag characters
544 * are always escaped.
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;
551 pc->linkStatusCB = linkStatusCB;
552 pc->linkStatusCtx = linkStatusCtx;
554 sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
556 while(pd >= 0 && !pc->if_up) {
558 if (lcp_phase[pd] == PHASE_DEAD) {
572 #endif /* PPPOS_SUPPORT */
575 static void pppOverEthernetLinkStatusCB(int pd, int up);
578 pppOverEthernetClose(int pd)
580 PPPControl* pc = &pppControl[pd];
582 /* *TJL* There's no lcp_deinit */
585 pppoe_destroy(&pc->netif);
588 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
593 LWIP_UNUSED_ARG(service_name);
594 LWIP_UNUSED_ARG(concentrator_name);
596 /* Find a free PPP session descriptor. Critical region? */
597 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
601 pppControl[pd].openFlag = !0;
604 /* Launch a deamon thread. */
607 pppControl[pd].openFlag = 1;
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;
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;
621 pc = &pppControl[pd];
628 pc->inState = PDIDLE;
634 #endif /* VJ_SUPPORT */
635 #endif /* PPPOS_SUPPORT */
638 memset(pc->inACCM, 0, sizeof(ext_accm));
639 memset(pc->outACCM, 0, sizeof(ext_accm));
641 pc->linkStatusCB = linkStatusCB;
642 pc->linkStatusCtx = linkStatusCtx;
644 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
649 pppoe_connect(pc->pppoe_sc);
652 while(pd >= 0 && !pc->if_up) {
654 if (lcp_phase[pd] == PHASE_DEAD) {
668 #endif /* PPPOE_SUPPORT */
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. */
677 PPPControl *pc = &pppControl[pd];
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);
688 #endif /* PPPOE_SUPPORT */
693 #endif /* PPPOS_SUPPORT */
696 if(!pc->linkStatusCB) {
697 while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
706 /* This function is called when carrier is lost on the PPP channel. */
710 PPPControl *pc = &pppControl[pd];
714 PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
715 tcpip_callback(pppHupCB, (void*)pd);
717 #endif /* PPPOE_SUPPORT */
722 #endif /* PPPOS_SUPPORT */
728 nPut(PPPControl *pc, struct pbuf *nb)
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 */
744 LINK_STATS_INC(link.xmit);
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.
754 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
756 struct pbuf *tb = nb;
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);
767 LINK_STATS_INC(link.memerr);
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;
777 *((u_char*)nb->payload + nb->len++) = c;
783 #endif /* PPPOS_SUPPORT */
787 pppifOutputOverEthernet(int pd, struct pbuf *p)
789 PPPControl *pc = &pppControl[pd];
791 u_short protocol = PPP_IP;
794 pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM);
796 LINK_STATS_INC(link.memerr);
797 LINK_STATS_INC(link.proterr);
801 pbuf_header(pb, -pppoe_hdrlen);
803 pc->lastXMit = sys_jiffies();
805 if (!pc->pcomp || protocol > 0xFF) {
806 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
808 *((u_char*)pb->payload + i) = protocol & 0xFF;
812 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
813 LINK_STATS_INC(link.err);
814 return PPPERR_DEVICE;
817 LINK_STATS_INC(link.xmit);
820 #endif /* PPPOE_SUPPORT */
822 /* Send a packet on the given connection. */
824 pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
826 int pd = (int)netif->state;
827 u_short protocol = PPP_IP;
828 PPPControl *pc = &pppControl[pd];
830 u_int fcsOut = PPP_INITFCS;
831 struct pbuf *headMB = NULL, *tailMB = NULL, *p;
833 #endif /* PPPOS_SUPPORT */
835 LWIP_UNUSED_ARG(ipaddr);
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",
843 LINK_STATS_INC(link.opterr);
844 LINK_STATS_INC(link.drop);
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);
858 return pppifOutputOverEthernet(pd, pb);
860 #endif /* PPPOE_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);
874 * Attempt Van Jacobson header compression if VJ is configured and
875 * this is an IP packet.
877 if (protocol == PPP_IP && pc->vjEnabled) {
878 switch (vj_compress_tcp(&pc->vjComp, pb)) {
881 protocol = PPP_IP_PROTOCOL; */
883 case TYPE_COMPRESSED_TCP:
884 protocol = PPP_VJC_COMP;
886 case TYPE_UNCOMPRESSED_TCP:
887 protocol = PPP_VJC_UNCOMP;
890 PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
891 LINK_STATS_INC(link.proterr);
892 LINK_STATS_INC(link.drop);
897 #endif /* VJ_SUPPORT */
901 /* Build the PPP header. */
902 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
903 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
906 pc->lastXMit = sys_jiffies();
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);
913 if (!pc->pcomp || protocol > 0xFF) {
914 c = (protocol >> 8) & 0xFF;
915 fcsOut = PPP_FCS(fcsOut, c);
916 tailMB = pppAppend(c, tailMB, &pc->outACCM);
919 fcsOut = PPP_FCS(fcsOut, c);
920 tailMB = pppAppend(c, tailMB, &pc->outACCM);
923 for(p = pb; p; p = p->next) {
927 sPtr = (u_char*)p->payload;
932 /* Update FCS before checking for special characters. */
933 fcsOut = PPP_FCS(fcsOut, c);
935 /* Copy to output buffer escaping special characters. */
936 tailMB = pppAppend(c, tailMB, &pc->outACCM);
940 /* Add FCS and trailing flag. */
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);
947 /* If we failed to complete the packet, throw it away. */
949 PPPDEBUG((LOG_WARNING,
950 "pppifOutput[%d]: Alloc err - dropping proto=%d\n",
953 LINK_STATS_INC(link.memerr);
954 LINK_STATS_INC(link.drop);
959 PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));
962 #endif /* PPPOS_SUPPORT */
967 /* Get and set parameters for the given connection.
968 * Return 0 on success, an error code on failure. */
970 pppIOCtl(int pd, int cmd, void *arg)
972 PPPControl *pc = &pppControl[pd];
975 if (pd < 0 || pd >= NUM_PPP) {
979 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */
981 *(int *)arg = (int)(pc->if_up);
986 case PPPCTLS_ERRCODE: /* Set the PPP error code. */
988 pc->errCode = *(int *)arg;
993 case PPPCTLG_ERRCODE: /* Get the PPP error code. */
995 *(int *)arg = (int)(pc->errCode);
1003 *(sio_fd_t *)arg = pc->fd;
1008 #endif /* PPPOS_SUPPORT */
1019 * Return the Maximum Transmission Unit for the given PPP connection.
1024 PPPControl *pc = &pppControl[pd];
1027 /* Validate parameters. */
1028 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1039 pppWriteOverEthernet(int pd, const u_char *s, int n)
1041 PPPControl *pc = &pppControl[pd];
1044 /* skip address & flags */
1048 pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM);
1050 LINK_STATS_INC(link.memerr);
1051 LINK_STATS_INC(link.proterr);
1052 return PPPERR_ALLOC;
1055 pbuf_header(pb, -pppoe_hdrlen);
1057 pc->lastXMit = sys_jiffies();
1059 SMEMCPY(pb->payload, s, n);
1061 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
1062 LINK_STATS_INC(link.err);
1063 return PPPERR_DEVICE;
1066 LINK_STATS_INC(link.xmit);
1069 #endif /* PPPOE_SUPPORT */
1072 * Write n characters to a ppp link.
1073 * RETURN: >= 0 Number of characters written
1074 * -1 Failed to write to device
1077 pppWrite(int pd, const u_char *s, int n)
1079 PPPControl *pc = &pppControl[pd];
1083 struct pbuf *headMB, *tailMB;
1084 #endif /* PPPOS_SUPPORT */
1088 return pppWriteOverEthernet(pd, s, n);
1090 #endif /* PPPOE_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;
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);
1107 pc->lastXMit = sys_jiffies();
1109 fcsOut = PPP_INITFCS;
1110 /* Load output buffer. */
1114 /* Update FCS before checking for special characters. */
1115 fcsOut = PPP_FCS(fcsOut, c);
1117 /* Copy to output buffer escaping special characters. */
1118 tailMB = pppAppend(c, tailMB, &pc->outACCM);
1121 /* Add FCS and trailing flag. */
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);
1128 /* If we failed to complete the packet, throw it away.
1129 * Otherwise send it. */
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)); */
1135 LINK_STATS_INC(link.memerr);
1136 LINK_STATS_INC(link.proterr);
1137 return PPPERR_ALLOC;
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)); */
1143 #endif /* PPPOS_SUPPORT */
1149 * ppp_send_config - configure the transmit characteristics of
1150 * the ppp interface.
1153 ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp)
1155 PPPControl *pc = &pppControl[unit];
1160 pc->accomp = accomp;
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);
1166 PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n",
1168 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
1173 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1176 ppp_set_xaccm(int unit, ext_accm *accm)
1178 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
1179 PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
1181 pppControl[unit].outACCM[0],
1182 pppControl[unit].outACCM[1],
1183 pppControl[unit].outACCM[2],
1184 pppControl[unit].outACCM[3]));
1189 * ppp_recv_config - configure the receive-side characteristics of
1190 * the ppp interface.
1193 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
1195 PPPControl *pc = &pppControl[unit];
1198 LWIP_UNUSED_ARG(accomp);
1199 LWIP_UNUSED_ARG(pcomp);
1200 LWIP_UNUSED_ARG(mru);
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));
1206 PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
1208 pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
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.
1219 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr)
1221 return 0; /* XXX Currently no compression. */
1225 * ccp_flags_set - inform kernel about the current state of CCP.
1228 ccp_flags_set(int unit, int isopen, int isup)
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.
1239 ccp_fatal_error(int unit)
1247 * get_idle_time - return how long the link has been idle.
1250 get_idle_time(int u, struct ppp_idle *ip)
1254 LWIP_UNUSED_ARG(ip);
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.
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;
1279 nmask = IN_CLASSC_NET;
1282 /* class D nets are disallowed by bad_ip_adrs */
1283 mask = subnetMask | htonl(nmask);
1286 * Scan through the system's network interfaces.
1287 * Get each netmask and OR them into our mask.
1294 * sifvjcomp - config tcp header compression
1297 sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
1299 #if PPPOS_SUPPORT && VJ_SUPPORT
1300 PPPControl *pc = &pppControl[pd];
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 */
1313 * pppifNetifInit - netif init callback
1316 pppifNetifInit(struct netif *netif)
1318 netif->name[0] = 'p';
1319 netif->name[1] = 'p';
1320 netif->output = pppifOutput;
1321 netif->mtu = pppMTU((int)netif->state);
1327 * sifup - Config the interface up and enable IP packets to pass.
1332 PPPControl *pc = &pppControl[pd];
1335 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1337 PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
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);
1343 /* ugly workaround for storing a reference to the ppp related info*/
1344 pc->netif.dhcp = (struct dhcp *) &pc->addrs;
1345 #endif /* LWIP_DHCP */
1347 pc->errCode = PPPERR_NONE;
1349 PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1350 if(pc->linkStatusCB) {
1351 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
1355 PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
1363 * sifnpmode - Set the mode for handling packets for a given NP.
1366 sifnpmode(int u, int proto, enum NPmode mode)
1369 LWIP_UNUSED_ARG(proto);
1370 LWIP_UNUSED_ARG(mode);
1375 * sifdown - Config the interface down and disable IP.
1380 PPPControl *pc = &pppControl[pd];
1383 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1385 PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
1388 netif_remove(&pc->netif);
1389 PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1390 if(pc->linkStatusCB) {
1391 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
1398 * sifaddr - Config the interface IP addresses and netmask.
1399 * @param pd Interface unit ???
1400 * @param o Our IP address ???
1401 * @param h His IP address ???
1402 * @param m IP subnet mask ???
1403 * @param ns1 Primary DNS
1404 * @param ns2 Secondary DNS
1407 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
1409 PPPControl *pc = &pppControl[pd];
1412 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1414 PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1416 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
1417 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
1418 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
1419 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
1420 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
1426 * cifaddr - Clear the interface IP addresses, and delete routes
1427 * through the interface if possible.
1428 * @param pd Interface unit ???
1429 * @param o Our IP address ???
1430 * @param h IP broadcast address ???
1433 cifaddr( int pd, u32_t o, u32_t h)
1435 PPPControl *pc = &pppControl[pd];
1440 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1442 PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1444 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
1445 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
1446 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
1447 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
1448 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
1454 * sifdefaultroute - assign a default route through the address given.
1457 sifdefaultroute(int pd, u32_t l, u32_t g)
1459 PPPControl *pc = &pppControl[pd];
1465 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1467 PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1469 netif_set_default(&pc->netif);
1472 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1478 * cifdefaultroute - delete a default route through the address given.
1481 cifdefaultroute(int pd, u32_t l, u32_t g)
1483 PPPControl *pc = &pppControl[pd];
1489 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1491 PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1493 netif_set_default(NULL);
1499 /**********************************/
1500 /*** LOCAL FUNCTION DEFINITIONS ***/
1501 /**********************************/
1504 /* The main PPP process function. This implements the state machine according
1505 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1514 pc = &pppControl[pd];
1516 p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
1518 LWIP_ASSERT("p != NULL", p);
1519 pc->errCode = PPPERR_ALLOC;
1524 * Start the connection and handle incoming events (packet or timeout).
1526 PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1527 tcpip_callback(pppStartCB, arg);
1528 while (lcp_phase[pd] != PHASE_DEAD) {
1529 if (pc->kill_link) {
1530 PPPDEBUG((LOG_DEBUG, "pppMain: unit %d kill_link -> pppStopCB\n", pd));
1531 pc->errCode = PPPERR_USER;
1532 /* This will leave us at PHASE_DEAD. */
1533 tcpip_callback(pppStopCB, arg);
1535 } else if (pc->sig_hup) {
1536 PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sig_hup -> pppHupCB\n", pd));
1538 tcpip_callback(pppHupCB, arg);
1540 c = sio_read(pc->fd, p->payload, p->len);
1542 pppInProc(pd, p->payload, c);
1544 PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
1545 sys_msleep(1); /* give other tasks a chance to run */
1549 PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
1550 pppDrop(pc); /* bug fix #17726 */
1554 PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1555 if(pc->linkStatusCB) {
1556 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1561 #endif /* PPPOS_SUPPORT */
1566 pppOverEthernetInitFailed(void* arg)
1574 pc = &pppControl[pd];
1575 pppoe_destroy(&pc->netif);
1578 if(pc->linkStatusCB) {
1579 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1584 pppOverEthernetLinkStatusCB(int pd, int up)
1587 PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1588 tcpip_callback(pppStartCB, (void*)pd);
1591 pc = &pppControl[pd];
1592 tcpip_callback(pppOverEthernetInitFailed, (void*)pd);
1595 #endif /* PPPOE_SUPPORT */
1598 pppSingleBuf(struct pbuf *p)
1603 if(p->tot_len == p->len) {
1607 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1610 "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
1611 return p; /* live dangerously */
1614 for(b = p, pl = q->payload; b != NULL; b = b->next) {
1615 MEMCPY(pl, b->payload, b->len);
1624 struct pppInputHeader {
1630 * Pass the processed input packet to the appropriate handler.
1631 * This function and all handlers run in the context of the tcpip_thread
1636 struct pbuf *nb = (struct pbuf *)arg;
1640 pd = ((struct pppInputHeader *)nb->payload)->unit;
1641 protocol = ((struct pppInputHeader *)nb->payload)->proto;
1643 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) {
1644 LWIP_ASSERT("pbuf_header failed\n", 0);
1648 LINK_STATS_INC(link.recv);
1651 * Toss all non-LCP packets unless LCP is OPEN.
1652 * Until we get past the authentication phase, toss all packets
1653 * except LCP, LQR and authentication packets.
1655 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
1656 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
1657 (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
1658 PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd]));
1664 case PPP_VJC_COMP: /* VJ compressed TCP */
1666 PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
1668 * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1669 * pass the result to IP.
1671 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) {
1672 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1675 /* Something's wrong so drop it. */
1676 PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
1677 #else /* VJ_SUPPORT */
1678 /* No handler for this protocol so drop the packet. */
1679 PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
1680 #endif /* VJ_SUPPORT */
1683 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
1685 PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
1687 * Process the TCP/IP header for VJ header compression and then pass
1690 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) {
1691 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1694 /* Something's wrong so drop it. */
1695 PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
1696 #else /* VJ_SUPPORT */
1697 /* No handler for this protocol so drop the packet. */
1699 "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1700 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
1701 #endif /* VJ_SUPPORT */
1704 case PPP_IP: /* Internet Protocol */
1705 PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
1706 if (pppControl[pd].netif.input) {
1707 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1713 struct protent *protp;
1717 * Upcall the proper protocol input routine.
1719 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
1720 if (protp->protocol == protocol && protp->enabled_flag) {
1721 PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
1722 nb = pppSingleBuf(nb);
1723 (*protp->input)(pd, nb->payload, nb->len);
1728 /* No handler for this protocol so reject the packet. */
1729 PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len));
1730 if (pbuf_header(nb, sizeof(protocol))) {
1731 LWIP_ASSERT("pbuf_header failed\n", 0);
1734 #if BYTE_ORDER == LITTLE_ENDIAN
1735 protocol = htons(protocol);
1736 SMEMCPY(nb->payload, &protocol, sizeof(protocol));
1737 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
1738 lcp_sprotrej(pd, nb->payload, nb->len);
1744 LINK_STATS_INC(link.drop);
1753 * Drop the input packet.
1756 pppDrop(PPPControl *pc)
1758 if (pc->inHead != NULL) {
1760 PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
1762 PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
1763 if (pc->inTail && (pc->inTail != pc->inHead)) {
1764 pbuf_free(pc->inTail);
1766 pbuf_free(pc->inHead);
1771 vj_uncompress_err(&pc->vjComp);
1772 #endif /* VJ_SUPPORT */
1774 LINK_STATS_INC(link.drop);
1778 * Process a received octet string.
1781 pppInProc(int pd, u_char *s, int l)
1783 PPPControl *pc = &pppControl[pd];
1784 struct pbuf *nextNBuf;
1787 PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l));
1791 /* Handle special characters. */
1792 if (ESCAPE_P(pc->inACCM, curChar)) {
1793 /* Check for escape sequences. */
1794 /* XXX Note that this does not handle an escaped 0x5d character which
1795 * would appear as an escape character. Since this is an ASCII ']'
1796 * and there is no reason that I know of to escape it, I won't complicate
1797 * the code to handle this case. GLL */
1798 if (curChar == PPP_ESCAPE) {
1800 /* Check for the flag character. */
1801 } else if (curChar == PPP_FLAG) {
1802 /* If this is just an extra flag character, ignore it. */
1803 if (pc->inState <= PDADDRESS) {
1805 /* If we haven't received the packet header, drop what has come in. */
1806 } else if (pc->inState < PDDATA) {
1807 PPPDEBUG((LOG_WARNING,
1808 "pppInProc[%d]: Dropping incomplete packet %d\n",
1810 LINK_STATS_INC(link.lenerr);
1812 /* If the fcs is invalid, drop the packet. */
1813 } else if (pc->inFCS != PPP_GOODFCS) {
1815 "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
1816 pd, pc->inFCS, pc->inProtocol));
1817 LINK_STATS_INC(link.chkerr);
1819 /* Otherwise it's a good packet so pass it on. */
1821 /* Trim off the checksum. */
1822 if(pc->inTail->len >= 2) {
1823 pc->inTail->len -= 2;
1825 pc->inTail->tot_len = pc->inTail->len;
1826 if (pc->inTail != pc->inHead) {
1827 pbuf_cat(pc->inHead, pc->inTail);
1830 pc->inTail->tot_len = pc->inTail->len;
1831 if (pc->inTail != pc->inHead) {
1832 pbuf_cat(pc->inHead, pc->inTail);
1835 pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
1838 /* Dispatch the packet thereby consuming it. */
1839 if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
1840 PPPDEBUG((LOG_ERR, "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
1841 pbuf_free(pc->inHead);
1842 LINK_STATS_INC(link.drop);
1848 /* Prepare for a new packet. */
1849 pc->inFCS = PPP_INITFCS;
1850 pc->inState = PDADDRESS;
1852 /* Other characters are usually control characters that may have
1853 * been inserted by the physical layer so here we just drop them. */
1855 PPPDEBUG((LOG_WARNING,
1856 "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar));
1858 /* Process other characters. */
1860 /* Unencode escaped characters. */
1861 if (pc->inEscaped) {
1863 curChar ^= PPP_TRANS;
1866 /* Process character relative to current state. */
1867 switch(pc->inState) {
1868 case PDIDLE: /* Idle state - waiting. */
1869 /* Drop the character if it's not 0xff
1870 * we would have processed a flag character above. */
1871 if (curChar != PPP_ALLSTATIONS) {
1876 case PDSTART: /* Process start flag. */
1877 /* Prepare for a new packet. */
1878 pc->inFCS = PPP_INITFCS;
1881 case PDADDRESS: /* Process address field. */
1882 if (curChar == PPP_ALLSTATIONS) {
1883 pc->inState = PDCONTROL;
1886 /* Else assume compressed address and control fields so
1887 * fall through to get the protocol... */
1888 case PDCONTROL: /* Process control field. */
1889 /* If we don't get a valid control code, restart. */
1890 if (curChar == PPP_UI) {
1891 pc->inState = PDPROTOCOL1;
1896 PPPDEBUG((LOG_WARNING,
1897 "pppInProc[%d]: Invalid control <%d>\n", pd, curChar));
1898 pc->inState = PDSTART;
1901 case PDPROTOCOL1: /* Process protocol field 1. */
1902 /* If the lower bit is set, this is the end of the protocol
1905 pc->inProtocol = curChar;
1906 pc->inState = PDDATA;
1908 pc->inProtocol = (u_int)curChar << 8;
1909 pc->inState = PDPROTOCOL2;
1912 case PDPROTOCOL2: /* Process protocol field 2. */
1913 pc->inProtocol |= curChar;
1914 pc->inState = PDDATA;
1916 case PDDATA: /* Process data byte. */
1917 /* Make space to receive processed data. */
1918 if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
1920 pc->inTail->tot_len = pc->inTail->len;
1921 if (pc->inTail != pc->inHead) {
1922 pbuf_cat(pc->inHead, pc->inTail);
1925 /* If we haven't started a packet, we need a packet header. */
1926 nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1927 if (nextNBuf == NULL) {
1928 /* No free buffers. Drop the input packet and let the
1929 * higher layers deal with it. Continue processing
1930 * the received pbuf chain in case a new packet starts. */
1931 PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
1932 LINK_STATS_INC(link.memerr);
1934 pc->inState = PDSTART; /* Wait for flag sequence. */
1937 if (pc->inHead == NULL) {
1938 struct pppInputHeader *pih = nextNBuf->payload;
1941 pih->proto = pc->inProtocol;
1943 nextNBuf->len += sizeof(*pih);
1945 pc->inHead = nextNBuf;
1947 pc->inTail = nextNBuf;
1949 /* Load character into buffer. */
1950 ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
1954 /* update the frame check sequence number. */
1955 pc->inFCS = PPP_FCS(pc->inFCS, curChar);
1961 #endif /* PPPOS_SUPPORT */
1965 pppInProcOverEthernet(int pd, struct pbuf *pb)
1967 struct pppInputHeader *pih;
1970 if(pb->len < sizeof(inProtocol)) {
1971 PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n"));
1975 inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
1977 /* make room for pppInputHeader - should not fail */
1978 if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
1979 PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n"));
1986 pih->proto = inProtocol;
1988 /* Dispatch the packet thereby consuming it. */
1989 if(tcpip_callback(pppInput, pb) != ERR_OK) {
1990 PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd));
1997 LINK_STATS_INC(link.drop);
2001 #endif /* PPPOE_SUPPORT */
2003 #endif /* PPP_SUPPORT */