BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file
3 * Network Point to Point Protocol over Serial file.
4 *
5 */
6  
7 /*
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28 * OF SUCH DAMAGE.
29 *
30 * This file is part of the lwIP TCP/IP stack.
31 *
32 */
33  
34 #include "netif/ppp/ppp_opts.h"
35 #if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */
36  
37 #include <string.h>
38  
39 #include "lwip/arch.h"
40 #include "lwip/err.h"
41 #include "lwip/pbuf.h"
42 #include "lwip/sys.h"
43 #include "lwip/memp.h"
44 #include "lwip/netif.h"
45 #include "lwip/snmp.h"
46 #include "lwip/priv/tcpip_priv.h"
47 #include "lwip/api.h"
48 #include "lwip/ip4.h" /* for ip4_input() */
49  
50 #include "netif/ppp/ppp_impl.h"
51 #include "netif/ppp/pppos.h"
52 #include "netif/ppp/vj.h"
53  
54 /* Memory pool */
55 LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB")
56  
57 /* callbacks called from PPP core */
58 static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p);
59 static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol);
60 static void pppos_connect(ppp_pcb *ppp, void *ctx);
61 #if PPP_SERVER
62 static void pppos_listen(ppp_pcb *ppp, void *ctx);
63 #endif /* PPP_SERVER */
64 static void pppos_disconnect(ppp_pcb *ppp, void *ctx);
65 static err_t pppos_destroy(ppp_pcb *ppp, void *ctx);
66 static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp);
67 static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp);
68  
69 /* Prototypes for procedures local to this file. */
70 #if PPP_INPROC_IRQ_SAFE
71 static void pppos_input_callback(void *arg);
72 #endif /* PPP_INPROC_IRQ_SAFE */
73 static void pppos_input_free_current_packet(pppos_pcb *pppos);
74 static void pppos_input_drop(pppos_pcb *pppos);
75 static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs);
76 static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs);
77  
78 /* Callbacks structure for PPP core */
79 static const struct link_callbacks pppos_callbacks = {
80 pppos_connect,
81 #if PPP_SERVER
82 pppos_listen,
83 #endif /* PPP_SERVER */
84 pppos_disconnect,
85 pppos_destroy,
86 pppos_write,
87 pppos_netif_output,
88 pppos_send_config,
89 pppos_recv_config
90 };
91  
92 /* PPP's Asynchronous-Control-Character-Map. The mask array is used
93 * to select the specific bit for a character. */
94 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07))
95  
96 #if PPP_FCS_TABLE
97 /*
98 * FCS lookup table as calculated by genfcstab.
99 */
100 static const u16_t fcstab[256] = {
101 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
102 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
103 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
104 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
105 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
106 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
107 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
108 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
109 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
110 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
111 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
112 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
113 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
114 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
115 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
116 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
117 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
118 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
119 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
120 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
121 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
122 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
123 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
124 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
125 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
126 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
127 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
128 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
129 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
130 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
131 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
132 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
133 };
134 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
135 #else /* PPP_FCS_TABLE */
136 /* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */
137 #define PPP_FCS_POLYNOMIAL 0x8408
138 static u16_t
139 ppp_get_fcs(u8_t byte)
140 {
141 unsigned int octet;
142 int bit;
143 octet = byte;
144 for (bit = 8; bit-- > 0; ) {
145 octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1);
146 }
147 return octet & 0xffff;
148 }
149 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff))
150 #endif /* PPP_FCS_TABLE */
151  
152 /*
153 * Values for FCS calculations.
154 */
155 #define PPP_INITFCS 0xffff /* Initial FCS value */
156 #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
157  
158 #if PPP_INPROC_IRQ_SAFE
159 #define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev)
160 #define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev)
161 #define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev)
162 #else
163 #define PPPOS_DECL_PROTECT(lev)
164 #define PPPOS_PROTECT(lev)
165 #define PPPOS_UNPROTECT(lev)
166 #endif /* PPP_INPROC_IRQ_SAFE */
167  
168  
169 /*
170 * Create a new PPP connection using the given serial I/O device.
171 *
172 * Return 0 on success, an error code on failure.
173 */
174 ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb,
175 ppp_link_status_cb_fn link_status_cb, void *ctx_cb)
176 {
177 pppos_pcb *pppos;
178 ppp_pcb *ppp;
179  
180 pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB);
181 if (pppos == NULL) {
182 return NULL;
183 }
184  
185 ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb);
186 if (ppp == NULL) {
187 LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos);
188 return NULL;
189 }
190  
191 memset(pppos, 0, sizeof(pppos_pcb));
192 pppos->ppp = ppp;
193 pppos->output_cb = output_cb;
194 return ppp;
195 }
196  
197 /* Called by PPP core */
198 static err_t
199 pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p)
200 {
201 pppos_pcb *pppos = (pppos_pcb *)ctx;
202 u8_t *s;
203 struct pbuf *nb;
204 u16_t n;
205 u16_t fcs_out;
206 err_t err;
207 LWIP_UNUSED_ARG(ppp);
208  
209 /* Grab an output buffer. */
210 nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
211 if (nb == NULL) {
212 PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num));
213 LINK_STATS_INC(link.memerr);
214 LINK_STATS_INC(link.drop);
215 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
216 pbuf_free(p);
217 return ERR_MEM;
218 }
219  
220 /* Set nb->tot_len to actual payload length */
221 nb->tot_len = p->len;
222  
223 /* If the link has been idle, we'll send a fresh flag character to
224 * flush any noise. */
225 err = ERR_OK;
226 if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) {
227 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
228 }
229  
230 /* Load output buffer. */
231 fcs_out = PPP_INITFCS;
232 s = (u8_t*)p->payload;
233 n = p->len;
234 while (n-- > 0) {
235 err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out);
236 }
237  
238 err = pppos_output_last(pppos, err, nb, &fcs_out);
239 if (err == ERR_OK) {
240 PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len));
241 } else {
242 PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len));
243 }
244 pbuf_free(p);
245 return err;
246 }
247  
248 /* Called by PPP core */
249 static err_t
250 pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol)
251 {
252 pppos_pcb *pppos = (pppos_pcb *)ctx;
253 struct pbuf *nb, *p;
254 u16_t fcs_out;
255 err_t err;
256 LWIP_UNUSED_ARG(ppp);
257  
258 /* Grab an output buffer. */
259 nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
260 if (nb == NULL) {
261 PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num));
262 LINK_STATS_INC(link.memerr);
263 LINK_STATS_INC(link.drop);
264 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
265 return ERR_MEM;
266 }
267  
268 /* Set nb->tot_len to actual payload length */
269 nb->tot_len = pb->tot_len;
270  
271 /* If the link has been idle, we'll send a fresh flag character to
272 * flush any noise. */
273 err = ERR_OK;
274 if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) {
275 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
276 }
277  
278 fcs_out = PPP_INITFCS;
279 if (!pppos->accomp) {
280 err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out);
281 err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out);
282 }
283 if (!pppos->pcomp || protocol > 0xFF) {
284 err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out);
285 }
286 err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out);
287  
288 /* Load packet. */
289 for(p = pb; p; p = p->next) {
290 u16_t n = p->len;
291 u8_t *s = (u8_t*)p->payload;
292  
293 while (n-- > 0) {
294 err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out);
295 }
296 }
297  
298 err = pppos_output_last(pppos, err, nb, &fcs_out);
299 if (err == ERR_OK) {
300 PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len));
301 } else {
302 PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len));
303 }
304 return err;
305 }
306  
307 static void
308 pppos_connect(ppp_pcb *ppp, void *ctx)
309 {
310 pppos_pcb *pppos = (pppos_pcb *)ctx;
311 PPPOS_DECL_PROTECT(lev);
312  
313 #if PPP_INPROC_IRQ_SAFE
314 /* input pbuf left over from last session? */
315 pppos_input_free_current_packet(pppos);
316 #endif /* PPP_INPROC_IRQ_SAFE */
317  
318 /* reset PPPoS control block to its initial state */
319 memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit));
320  
321 /*
322 * Default the in and out accm so that escape and flag characters
323 * are always escaped.
324 */
325 pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */
326 pppos->out_accm[15] = 0x60;
327 PPPOS_PROTECT(lev);
328 pppos->open = 1;
329 PPPOS_UNPROTECT(lev);
330  
331 /*
332 * Start the connection and handle incoming events (packet or timeout).
333 */
334 PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num));
335 ppp_start(ppp); /* notify upper layers */
336 }
337  
338 #if PPP_SERVER
339 static void
340 pppos_listen(ppp_pcb *ppp, void *ctx)
341 {
342 pppos_pcb *pppos = (pppos_pcb *)ctx;
343 PPPOS_DECL_PROTECT(lev);
344  
345 #if PPP_INPROC_IRQ_SAFE
346 /* input pbuf left over from last session? */
347 pppos_input_free_current_packet(pppos);
348 #endif /* PPP_INPROC_IRQ_SAFE */
349  
350 /* reset PPPoS control block to its initial state */
351 memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit));
352  
353 /*
354 * Default the in and out accm so that escape and flag characters
355 * are always escaped.
356 */
357 pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */
358 pppos->out_accm[15] = 0x60;
359 PPPOS_PROTECT(lev);
360 pppos->open = 1;
361 PPPOS_UNPROTECT(lev);
362  
363 /*
364 * Wait for something to happen.
365 */
366 PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num));
367 ppp_start(ppp); /* notify upper layers */
368 }
369 #endif /* PPP_SERVER */
370  
371 static void
372 pppos_disconnect(ppp_pcb *ppp, void *ctx)
373 {
374 pppos_pcb *pppos = (pppos_pcb *)ctx;
375 PPPOS_DECL_PROTECT(lev);
376  
377 PPPOS_PROTECT(lev);
378 pppos->open = 0;
379 PPPOS_UNPROTECT(lev);
380  
381 /* If PPP_INPROC_IRQ_SAFE is used we cannot call
382 * pppos_input_free_current_packet() here because
383 * rx IRQ might still call pppos_input().
384 */
385 #if !PPP_INPROC_IRQ_SAFE
386 /* input pbuf left ? */
387 pppos_input_free_current_packet(pppos);
388 #endif /* !PPP_INPROC_IRQ_SAFE */
389  
390 ppp_link_end(ppp); /* notify upper layers */
391 }
392  
393 static err_t
394 pppos_destroy(ppp_pcb *ppp, void *ctx)
395 {
396 pppos_pcb *pppos = (pppos_pcb *)ctx;
397 LWIP_UNUSED_ARG(ppp);
398  
399 #if PPP_INPROC_IRQ_SAFE
400 /* input pbuf left ? */
401 pppos_input_free_current_packet(pppos);
402 #endif /* PPP_INPROC_IRQ_SAFE */
403  
404 LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos);
405 return ERR_OK;
406 }
407  
408 #if !NO_SYS && !PPP_INPROC_IRQ_SAFE
409 /** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread.
410 *
411 * @param ppp PPP descriptor index, returned by pppos_create()
412 * @param s received data
413 * @param l length of received data
414 */
415 err_t
416 pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l)
417 {
418 struct pbuf *p;
419 err_t err;
420  
421 p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL);
422 if (!p) {
423 return ERR_MEM;
424 }
425 pbuf_take(p, s, l);
426  
427 err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys);
428 if (err != ERR_OK) {
429 pbuf_free(p);
430 }
431 return err;
432 }
433  
434 /* called from TCPIP thread */
435 err_t pppos_input_sys(struct pbuf *p, struct netif *inp) {
436 ppp_pcb *ppp = (ppp_pcb*)inp->state;
437 struct pbuf *n;
438  
439 for (n = p; n; n = n->next) {
440 pppos_input(ppp, (u8_t*)n->payload, n->len);
441 }
442 pbuf_free(p);
443 return ERR_OK;
444 }
445 #endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */
446  
447 /** PPPoS input helper struct, must be packed since it is stored
448 * to pbuf->payload, which might be unaligned. */
449 #if PPP_INPROC_IRQ_SAFE
450 #ifdef PACK_STRUCT_USE_INCLUDES
451 # include "arch/bpstruct.h"
452 #endif
453 PACK_STRUCT_BEGIN
454 struct pppos_input_header {
455 PACK_STRUCT_FIELD(ppp_pcb *ppp);
456 } PACK_STRUCT_STRUCT;
457 PACK_STRUCT_END
458 #ifdef PACK_STRUCT_USE_INCLUDES
459 # include "arch/epstruct.h"
460 #endif
461 #endif /* PPP_INPROC_IRQ_SAFE */
462  
463 /** Pass received raw characters to PPPoS to be decoded.
464 *
465 * @param ppp PPP descriptor index, returned by pppos_create()
466 * @param s received data
467 * @param l length of received data
468 */
469 void
470 pppos_input(ppp_pcb *ppp, u8_t *s, int l)
471 {
472 pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb;
473 struct pbuf *next_pbuf;
474 u8_t cur_char;
475 u8_t escaped;
476 PPPOS_DECL_PROTECT(lev);
477  
478 PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l));
479 while (l-- > 0) {
480 cur_char = *s++;
481  
482 PPPOS_PROTECT(lev);
483 /* ppp_input can disconnect the interface, we need to abort to prevent a memory
484 * leak if there are remaining bytes because pppos_connect and pppos_listen
485 * functions expect input buffer to be free. Furthermore there are no real
486 * reason to continue reading bytes if we are disconnected.
487 */
488 if (!pppos->open) {
489 PPPOS_UNPROTECT(lev);
490 return;
491 }
492 escaped = ESCAPE_P(pppos->in_accm, cur_char);
493 PPPOS_UNPROTECT(lev);
494 /* Handle special characters. */
495 if (escaped) {
496 /* Check for escape sequences. */
497 /* XXX Note that this does not handle an escaped 0x5d character which
498 * would appear as an escape character. Since this is an ASCII ']'
499 * and there is no reason that I know of to escape it, I won't complicate
500 * the code to handle this case. GLL */
501 if (cur_char == PPP_ESCAPE) {
502 pppos->in_escaped = 1;
503 /* Check for the flag character. */
504 } else if (cur_char == PPP_FLAG) {
505 /* If this is just an extra flag character, ignore it. */
506 if (pppos->in_state <= PDADDRESS) {
507 /* ignore it */;
508 /* If we haven't received the packet header, drop what has come in. */
509 } else if (pppos->in_state < PDDATA) {
510 PPPDEBUG(LOG_WARNING,
511 ("pppos_input[%d]: Dropping incomplete packet %d\n",
512 ppp->netif->num, pppos->in_state));
513 LINK_STATS_INC(link.lenerr);
514 pppos_input_drop(pppos);
515 /* If the fcs is invalid, drop the packet. */
516 } else if (pppos->in_fcs != PPP_GOODFCS) {
517 PPPDEBUG(LOG_INFO,
518 ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
519 ppp->netif->num, pppos->in_fcs, pppos->in_protocol));
520 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
521 LINK_STATS_INC(link.chkerr);
522 pppos_input_drop(pppos);
523 /* Otherwise it's a good packet so pass it on. */
524 } else {
525 struct pbuf *inp;
526 /* Trim off the checksum. */
527 if(pppos->in_tail->len > 2) {
528 pppos->in_tail->len -= 2;
529  
530 pppos->in_tail->tot_len = pppos->in_tail->len;
531 if (pppos->in_tail != pppos->in_head) {
532 pbuf_cat(pppos->in_head, pppos->in_tail);
533 }
534 } else {
535 pppos->in_tail->tot_len = pppos->in_tail->len;
536 if (pppos->in_tail != pppos->in_head) {
537 pbuf_cat(pppos->in_head, pppos->in_tail);
538 }
539  
540 pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2);
541 }
542  
543 /* Dispatch the packet thereby consuming it. */
544 inp = pppos->in_head;
545 /* Packet consumed, release our references. */
546 pppos->in_head = NULL;
547 pppos->in_tail = NULL;
548 #if IP_FORWARD || LWIP_IPV6_FORWARD
549 /* hide the room for Ethernet forwarding header */
550 pbuf_remove_header(inp, PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN);
551 #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
552 #if PPP_INPROC_IRQ_SAFE
553 if(tcpip_try_callback(pppos_input_callback, inp) != ERR_OK) {
554 PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num));
555 pbuf_free(inp);
556 LINK_STATS_INC(link.drop);
557 MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards);
558 }
559 #else /* PPP_INPROC_IRQ_SAFE */
560 ppp_input(ppp, inp);
561 #endif /* PPP_INPROC_IRQ_SAFE */
562 }
563  
564 /* Prepare for a new packet. */
565 pppos->in_fcs = PPP_INITFCS;
566 pppos->in_state = PDADDRESS;
567 pppos->in_escaped = 0;
568 /* Other characters are usually control characters that may have
569 * been inserted by the physical layer so here we just drop them. */
570 } else {
571 PPPDEBUG(LOG_WARNING,
572 ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char));
573 }
574 /* Process other characters. */
575 } else {
576 /* Unencode escaped characters. */
577 if (pppos->in_escaped) {
578 pppos->in_escaped = 0;
579 cur_char ^= PPP_TRANS;
580 }
581  
582 /* Process character relative to current state. */
583 switch(pppos->in_state) {
584 case PDIDLE: /* Idle state - waiting. */
585 /* Drop the character if it's not 0xff
586 * we would have processed a flag character above. */
587 if (cur_char != PPP_ALLSTATIONS) {
588 break;
589 }
590 /* no break */
591 /* Fall through */
592  
593 case PDSTART: /* Process start flag. */
594 /* Prepare for a new packet. */
595 pppos->in_fcs = PPP_INITFCS;
596 /* no break */
597 /* Fall through */
598  
599 case PDADDRESS: /* Process address field. */
600 if (cur_char == PPP_ALLSTATIONS) {
601 pppos->in_state = PDCONTROL;
602 break;
603 }
604 /* no break */
605  
606 /* Else assume compressed address and control fields so
607 * fall through to get the protocol... */
608 case PDCONTROL: /* Process control field. */
609 /* If we don't get a valid control code, restart. */
610 if (cur_char == PPP_UI) {
611 pppos->in_state = PDPROTOCOL1;
612 break;
613 }
614 /* no break */
615  
616 #if 0
617 else {
618 PPPDEBUG(LOG_WARNING,
619 ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char));
620 pppos->in_state = PDSTART;
621 }
622 #endif
623 case PDPROTOCOL1: /* Process protocol field 1. */
624 /* If the lower bit is set, this is the end of the protocol
625 * field. */
626 if (cur_char & 1) {
627 pppos->in_protocol = cur_char;
628 pppos->in_state = PDDATA;
629 } else {
630 pppos->in_protocol = (u16_t)cur_char << 8;
631 pppos->in_state = PDPROTOCOL2;
632 }
633 break;
634 case PDPROTOCOL2: /* Process protocol field 2. */
635 pppos->in_protocol |= cur_char;
636 pppos->in_state = PDDATA;
637 break;
638 case PDDATA: /* Process data byte. */
639 /* Make space to receive processed data. */
640 if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) {
641 u16_t pbuf_alloc_len;
642 if (pppos->in_tail != NULL) {
643 pppos->in_tail->tot_len = pppos->in_tail->len;
644 if (pppos->in_tail != pppos->in_head) {
645 pbuf_cat(pppos->in_head, pppos->in_tail);
646 /* give up the in_tail reference now */
647 pppos->in_tail = NULL;
648 }
649 }
650 /* If we haven't started a packet, we need a packet header. */
651 pbuf_alloc_len = 0;
652 #if IP_FORWARD || LWIP_IPV6_FORWARD
653 /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN
654 * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header
655 * space to be forwarded (to Ethernet for example).
656 */
657 if (pppos->in_head == NULL) {
658 pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN;
659 }
660 #endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
661 next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL);
662 if (next_pbuf == NULL) {
663 /* No free buffers. Drop the input packet and let the
664 * higher layers deal with it. Continue processing
665 * the received pbuf chain in case a new packet starts. */
666 PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num));
667 LINK_STATS_INC(link.memerr);
668 pppos_input_drop(pppos);
669 pppos->in_state = PDSTART; /* Wait for flag sequence. */
670 break;
671 }
672 if (pppos->in_head == NULL) {
673 u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len;
674 #if PPP_INPROC_IRQ_SAFE
675 ((struct pppos_input_header*)payload)->ppp = ppp;
676 payload += sizeof(struct pppos_input_header);
677 next_pbuf->len += sizeof(struct pppos_input_header);
678 #endif /* PPP_INPROC_IRQ_SAFE */
679 next_pbuf->len += sizeof(pppos->in_protocol);
680 *(payload++) = pppos->in_protocol >> 8;
681 *(payload) = pppos->in_protocol & 0xFF;
682 pppos->in_head = next_pbuf;
683 }
684 pppos->in_tail = next_pbuf;
685 }
686 /* Load character into buffer. */
687 ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char;
688 break;
689 default:
690 break;
691 }
692  
693 /* update the frame check sequence number. */
694 pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char);
695 }
696 } /* while (l-- > 0), all bytes processed */
697 }
698  
699 #if PPP_INPROC_IRQ_SAFE
700 /* PPPoS input callback using one input pointer
701 */
702 static void pppos_input_callback(void *arg) {
703 struct pbuf *pb = (struct pbuf*)arg;
704 ppp_pcb *ppp;
705  
706 ppp = ((struct pppos_input_header*)pb->payload)->ppp;
707 if(pbuf_remove_header(pb, sizeof(struct pppos_input_header))) {
708 LWIP_ASSERT("pbuf_remove_header failed\n", 0);
709 goto drop;
710 }
711  
712 /* Dispatch the packet thereby consuming it. */
713 ppp_input(ppp, pb);
714 return;
715  
716 drop:
717 LINK_STATS_INC(link.drop);
718 MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards);
719 pbuf_free(pb);
720 }
721 #endif /* PPP_INPROC_IRQ_SAFE */
722  
723 static void
724 pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp)
725 {
726 int i;
727 pppos_pcb *pppos = (pppos_pcb *)ctx;
728 LWIP_UNUSED_ARG(ppp);
729  
730 pppos->pcomp = pcomp;
731 pppos->accomp = accomp;
732  
733 /* Load the ACCM bits for the 32 control codes. */
734 for (i = 0; i < 32/8; i++) {
735 pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF);
736 }
737  
738 PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n",
739 pppos->ppp->netif->num,
740 pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3]));
741 }
742  
743 static void
744 pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp)
745 {
746 int i;
747 pppos_pcb *pppos = (pppos_pcb *)ctx;
748 PPPOS_DECL_PROTECT(lev);
749 LWIP_UNUSED_ARG(ppp);
750 LWIP_UNUSED_ARG(pcomp);
751 LWIP_UNUSED_ARG(accomp);
752  
753 /* Load the ACCM bits for the 32 control codes. */
754 PPPOS_PROTECT(lev);
755 for (i = 0; i < 32 / 8; i++) {
756 pppos->in_accm[i] = (u8_t)(accm >> (i * 8));
757 }
758 PPPOS_UNPROTECT(lev);
759  
760 PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n",
761 pppos->ppp->netif->num,
762 pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3]));
763 }
764  
765 /*
766 * Drop the input packet.
767 */
768 static void
769 pppos_input_free_current_packet(pppos_pcb *pppos)
770 {
771 if (pppos->in_head != NULL) {
772 if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) {
773 pbuf_free(pppos->in_tail);
774 }
775 pbuf_free(pppos->in_head);
776 pppos->in_head = NULL;
777 }
778 pppos->in_tail = NULL;
779 }
780  
781 /*
782 * Drop the input packet and increase error counters.
783 */
784 static void
785 pppos_input_drop(pppos_pcb *pppos)
786 {
787 if (pppos->in_head != NULL) {
788 #if 0
789 PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload));
790 #endif
791 PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head));
792 }
793 pppos_input_free_current_packet(pppos);
794 #if VJ_SUPPORT
795 vj_uncompress_err(&pppos->ppp->vj_comp);
796 #endif /* VJ_SUPPORT */
797  
798 LINK_STATS_INC(link.drop);
799 MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards);
800 }
801  
802 /*
803 * pppos_output_append - append given character to end of given pbuf.
804 * If out_accm is not 0 and the character needs to be escaped, do so.
805 * If pbuf is full, send the pbuf and reuse it.
806 * Return the current pbuf.
807 */
808 static err_t
809 pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs)
810 {
811 if (err != ERR_OK) {
812 return err;
813 }
814  
815 /* Make sure there is room for the character and an escape code.
816 * Sure we don't quite fill the buffer if the character doesn't
817 * get escaped but is one character worth complicating this? */
818 if ((PBUF_POOL_BUFSIZE - nb->len) < 2) {
819 u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb);
820 if (l != nb->len) {
821 return ERR_IF;
822 }
823 nb->len = 0;
824 }
825  
826 /* Update FCS before checking for special characters. */
827 if (fcs) {
828 *fcs = PPP_FCS(*fcs, c);
829 }
830  
831 /* Copy to output buffer escaping special characters. */
832 if (accm && ESCAPE_P(pppos->out_accm, c)) {
833 *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE;
834 *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS;
835 } else {
836 *((u8_t*)nb->payload + nb->len++) = c;
837 }
838  
839 return ERR_OK;
840 }
841  
842 static err_t
843 pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs)
844 {
845 ppp_pcb *ppp = pppos->ppp;
846  
847 /* Add FCS and trailing flag. */
848 err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL);
849 err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL);
850 err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL);
851  
852 if (err != ERR_OK) {
853 goto failed;
854 }
855  
856 /* Send remaining buffer if not empty */
857 if (nb->len > 0) {
858 u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb);
859 if (l != nb->len) {
860 err = ERR_IF;
861 goto failed;
862 }
863 }
864  
865 pppos->last_xmit = sys_now();
866 MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len);
867 MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts);
868 LINK_STATS_INC(link.xmit);
869 pbuf_free(nb);
870 return ERR_OK;
871  
872 failed:
873 pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */
874 LINK_STATS_INC(link.err);
875 LINK_STATS_INC(link.drop);
876 MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards);
877 pbuf_free(nb);
878 return err;
879 }
880  
881 #endif /* PPP_SUPPORT && PPPOS_SUPPORT */