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