kernel: Shuffle some initialization around to avoid forward declarations.
[dragonfly.git] / sys / netgraph / async / ng_async.c
CommitLineData
984263bc
MD
1
2/*
3 * ng_async.c
4 *
5 * Copyright (c) 1996-1999 Whistle Communications, Inc.
6 * All rights reserved.
7 *
8 * Subject to the following obligations and disclaimer of warranty, use and
9 * redistribution of this software, in source or object code forms, with or
10 * without modifications are expressly permitted by Whistle Communications;
11 * provided, however, that:
12 * 1. Any and all reproductions of the source or object code must include the
13 * copyright notice above and the following disclaimer of warranties; and
14 * 2. No rights are granted, in any manner or form, to use Whistle
15 * Communications, Inc. trademarks, including the mark "WHISTLE
16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17 * such appears in the above copyright notice or in the software.
18 *
19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 *
37 * Author: Archie Cobbs <archie@freebsd.org>
38 *
39 * $FreeBSD: src/sys/netgraph/ng_async.c,v 1.6.2.5 2002/07/02 23:44:02 archie Exp $
40 * $Whistle: ng_async.c,v 1.17 1999/11/01 09:24:51 julian Exp $
41 */
42
43/*
44 * This node type implements a PPP style sync <-> async converter.
45 * See RFC 1661 for details of how asynchronous encoding works.
46 */
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#include <sys/mbuf.h>
52#include <sys/malloc.h>
53#include <sys/errno.h>
54
55#include <netgraph/ng_message.h>
56#include <netgraph/netgraph.h>
1f2de5d4 57#include "ng_async.h"
984263bc
MD
58#include <netgraph/ng_parse.h>
59
d2438d69 60#include <net/ppp_layer/ppp_defs.h>
984263bc
MD
61
62/* Async decode state */
63#define MODE_HUNT 0
64#define MODE_NORMAL 1
65#define MODE_ESC 2
66
67/* Private data structure */
68struct ng_async_private {
69 node_p node; /* Our node */
70 hook_p async; /* Asynchronous side */
71 hook_p sync; /* Synchronous side */
72 u_char amode; /* Async hunt/esape mode */
73 u_int16_t fcs; /* Decoded async FCS (so far) */
74 u_char *abuf; /* Buffer to encode sync into */
75 u_char *sbuf; /* Buffer to decode async into */
76 u_int slen; /* Length of data in sbuf */
77 long lasttime; /* Time of last async packet sent */
78 struct ng_async_cfg cfg; /* Configuration */
79 struct ng_async_stat stats; /* Statistics */
80};
81typedef struct ng_async_private *sc_p;
82
83/* Useful macros */
84#define ASYNC_BUF_SIZE(smru) (2 * (smru) + 10)
85#define SYNC_BUF_SIZE(amru) ((amru) + 10)
86#define ERROUT(x) do { error = (x); goto done; } while (0)
87
88/* Netgraph methods */
89static ng_constructor_t nga_constructor;
90static ng_rcvdata_t nga_rcvdata;
91static ng_rcvmsg_t nga_rcvmsg;
92static ng_shutdown_t nga_shutdown;
93static ng_newhook_t nga_newhook;
94static ng_disconnect_t nga_disconnect;
95
96/* Helper stuff */
97static int nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta);
98static int nga_rcv_async(const sc_p sc, struct mbuf *m, meta_p meta);
99
100/* Parse type for struct ng_async_cfg */
101static const struct ng_parse_struct_field nga_config_type_fields[]
102 = NG_ASYNC_CONFIG_TYPE_INFO;
103static const struct ng_parse_type nga_config_type = {
104 &ng_parse_struct_type,
105 &nga_config_type_fields
106};
107
108/* Parse type for struct ng_async_stat */
109static const struct ng_parse_struct_field nga_stats_type_fields[]
110 = NG_ASYNC_STATS_TYPE_INFO;
111static const struct ng_parse_type nga_stats_type = {
112 &ng_parse_struct_type,
113 &nga_stats_type_fields
114};
115
116/* List of commands and how to convert arguments to/from ASCII */
117static const struct ng_cmdlist nga_cmdlist[] = {
118 {
119 NGM_ASYNC_COOKIE,
120 NGM_ASYNC_CMD_SET_CONFIG,
121 "setconfig",
122 &nga_config_type,
123 NULL
124 },
125 {
126 NGM_ASYNC_COOKIE,
127 NGM_ASYNC_CMD_GET_CONFIG,
128 "getconfig",
129 NULL,
130 &nga_config_type
131 },
132 {
133 NGM_ASYNC_COOKIE,
134 NGM_ASYNC_CMD_GET_STATS,
135 "getstats",
136 NULL,
137 &nga_stats_type
138 },
139 {
140 NGM_ASYNC_COOKIE,
141 NGM_ASYNC_CMD_CLR_STATS,
142 "clrstats",
143 &nga_stats_type,
144 NULL
145 },
146 { 0 }
147};
148
149/* Define the netgraph node type */
150static struct ng_type typestruct = {
151 NG_VERSION,
152 NG_ASYNC_NODE_TYPE,
153 NULL,
154 nga_constructor,
155 nga_rcvmsg,
156 nga_shutdown,
157 nga_newhook,
158 NULL,
159 NULL,
160 nga_rcvdata,
161 nga_rcvdata,
162 nga_disconnect,
163 nga_cmdlist
164};
165NETGRAPH_INIT(async, &typestruct);
166
35efc471
SW
167/*
168 * CRC table
169 *
170 * Taken from RFC 1171 Appendix B
171 */
172static const u_int16_t fcstab[256] = {
173 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
174 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
175 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
176 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
177 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
178 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
179 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
180 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
181 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
182 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
183 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
184 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
185 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
186 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
187 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
188 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
189 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
190 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
191 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
192 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
193 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
194 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
195 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
196 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
197 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
198 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
199 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
200 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
201 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
202 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
203 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
204 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
205};
984263bc
MD
206
207/******************************************************************
208 NETGRAPH NODE METHODS
209******************************************************************/
210
211/*
212 * Initialize a new node
213 */
214static int
215nga_constructor(node_p *nodep)
216{
217 sc_p sc;
218 int error;
219
220 if ((error = ng_make_node_common(&typestruct, nodep)))
221 return (error);
884717e1 222 sc = kmalloc(sizeof(*sc), M_NETGRAPH, M_NOWAIT | M_ZERO);
984263bc
MD
223 if (sc == NULL)
224 return (ENOMEM);
984263bc
MD
225 sc->amode = MODE_HUNT;
226 sc->cfg.accm = ~0;
227 sc->cfg.amru = NG_ASYNC_DEFAULT_MRU;
228 sc->cfg.smru = NG_ASYNC_DEFAULT_MRU;
884717e1 229 sc->abuf = kmalloc(ASYNC_BUF_SIZE(sc->cfg.smru), M_NETGRAPH, M_NOWAIT);
984263bc
MD
230 if (sc->abuf == NULL)
231 goto fail;
884717e1 232 sc->sbuf = kmalloc(SYNC_BUF_SIZE(sc->cfg.amru), M_NETGRAPH, M_NOWAIT);
984263bc 233 if (sc->sbuf == NULL) {
884717e1 234 kfree(sc->abuf, M_NETGRAPH);
984263bc 235fail:
884717e1 236 kfree(sc, M_NETGRAPH);
984263bc
MD
237 return (ENOMEM);
238 }
239 (*nodep)->private = sc;
240 sc->node = *nodep;
241 return (0);
242}
243
244/*
245 * Reserve a hook for a pending connection
246 */
247static int
248nga_newhook(node_p node, hook_p hook, const char *name)
249{
250 const sc_p sc = node->private;
251 hook_p *hookp;
252
253 if (!strcmp(name, NG_ASYNC_HOOK_ASYNC))
254 hookp = &sc->async;
255 else if (!strcmp(name, NG_ASYNC_HOOK_SYNC))
256 hookp = &sc->sync;
257 else
258 return (EINVAL);
259 if (*hookp)
260 return (EISCONN);
261 *hookp = hook;
262 return (0);
263}
264
265/*
266 * Receive incoming data
267 */
268static int
269nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
270{
271 const sc_p sc = hook->node->private;
272
273 if (hook == sc->sync)
274 return (nga_rcv_sync(sc, m, meta));
275 if (hook == sc->async)
276 return (nga_rcv_async(sc, m, meta));
5e2195bf 277 panic(__func__);
984263bc
MD
278}
279
280/*
281 * Receive incoming control message
282 */
283static int
284nga_rcvmsg(node_p node, struct ng_mesg *msg,
285 const char *rtn, struct ng_mesg **rptr)
286{
287 const sc_p sc = (sc_p) node->private;
288 struct ng_mesg *resp = NULL;
289 int error = 0;
290
291 switch (msg->header.typecookie) {
292 case NGM_ASYNC_COOKIE:
293 switch (msg->header.cmd) {
294 case NGM_ASYNC_CMD_GET_STATS:
295 NG_MKRESPONSE(resp, msg, sizeof(sc->stats), M_NOWAIT);
296 if (resp == NULL)
297 ERROUT(ENOMEM);
298 *((struct ng_async_stat *) resp->data) = sc->stats;
299 break;
300 case NGM_ASYNC_CMD_CLR_STATS:
301 bzero(&sc->stats, sizeof(sc->stats));
302 break;
303 case NGM_ASYNC_CMD_SET_CONFIG:
304 {
305 struct ng_async_cfg *const cfg =
306 (struct ng_async_cfg *) msg->data;
307 u_char *buf;
308
309 if (msg->header.arglen != sizeof(*cfg))
310 ERROUT(EINVAL);
311 if (cfg->amru < NG_ASYNC_MIN_MRU
312 || cfg->amru > NG_ASYNC_MAX_MRU
313 || cfg->smru < NG_ASYNC_MIN_MRU
314 || cfg->smru > NG_ASYNC_MAX_MRU)
315 ERROUT(EINVAL);
316 cfg->enabled = !!cfg->enabled; /* normalize */
317 if (cfg->smru > sc->cfg.smru) { /* reallocate buffer */
884717e1
SW
318 buf = kmalloc(ASYNC_BUF_SIZE(cfg->smru),
319 M_NETGRAPH, M_NOWAIT);
984263bc
MD
320 if (!buf)
321 ERROUT(ENOMEM);
884717e1 322 kfree(sc->abuf, M_NETGRAPH);
984263bc
MD
323 sc->abuf = buf;
324 }
325 if (cfg->amru > sc->cfg.amru) { /* reallocate buffer */
884717e1
SW
326 buf = kmalloc(SYNC_BUF_SIZE(cfg->amru),
327 M_NETGRAPH, M_NOWAIT);
984263bc
MD
328 if (!buf)
329 ERROUT(ENOMEM);
884717e1 330 kfree(sc->sbuf, M_NETGRAPH);
984263bc
MD
331 sc->sbuf = buf;
332 sc->amode = MODE_HUNT;
333 sc->slen = 0;
334 }
335 if (!cfg->enabled) {
336 sc->amode = MODE_HUNT;
337 sc->slen = 0;
338 }
339 sc->cfg = *cfg;
340 break;
341 }
342 case NGM_ASYNC_CMD_GET_CONFIG:
343 NG_MKRESPONSE(resp, msg, sizeof(sc->cfg), M_NOWAIT);
344 if (!resp)
345 ERROUT(ENOMEM);
346 *((struct ng_async_cfg *) resp->data) = sc->cfg;
347 break;
348 default:
349 ERROUT(EINVAL);
350 }
351 break;
352 default:
353 ERROUT(EINVAL);
354 }
355 if (rptr)
356 *rptr = resp;
357 else if (resp)
884717e1 358 kfree(resp, M_NETGRAPH);
984263bc
MD
359
360done:
884717e1 361 kfree(msg, M_NETGRAPH);
984263bc
MD
362 return (error);
363}
364
365/*
366 * Shutdown this node
367 */
368static int
369nga_shutdown(node_p node)
370{
371 const sc_p sc = node->private;
372
373 ng_cutlinks(node);
374 ng_unname(node);
884717e1
SW
375 kfree(sc->abuf, M_NETGRAPH);
376 kfree(sc->sbuf, M_NETGRAPH);
984263bc 377 bzero(sc, sizeof(*sc));
884717e1 378 kfree(sc, M_NETGRAPH);
984263bc
MD
379 node->private = NULL;
380 ng_unref(node);
381 return (0);
382}
383
384/*
385 * Lose a hook. When both hooks go away, we disappear.
386 */
387static int
388nga_disconnect(hook_p hook)
389{
390 const sc_p sc = hook->node->private;
391 hook_p *hookp;
392
393 if (hook == sc->async)
394 hookp = &sc->async;
395 else if (hook == sc->sync)
396 hookp = &sc->sync;
397 else
5e2195bf 398 panic(__func__);
984263bc 399 if (!*hookp)
5e2195bf 400 panic("%s2", __func__);
984263bc
MD
401 *hookp = NULL;
402 bzero(&sc->stats, sizeof(sc->stats));
403 sc->lasttime = 0;
404 if (hook->node->numhooks == 0)
405 ng_rmnode(hook->node);
406 return (0);
407}
408
409/******************************************************************
410 INTERNAL HELPER STUFF
411******************************************************************/
412
413/*
414 * Encode a byte into the async buffer
415 */
416static __inline__ void
417nga_async_add(const sc_p sc, u_int16_t *fcs, u_int32_t accm, int *len, u_char x)
418{
419 *fcs = PPP_FCS(*fcs, x);
420 if ((x < 32 && ((1 << x) & accm))
421 || (x == PPP_ESCAPE)
422 || (x == PPP_FLAG)) {
423 sc->abuf[(*len)++] = PPP_ESCAPE;
424 x ^= PPP_TRANS;
425 }
426 sc->abuf[(*len)++] = x;
427}
428
429/*
430 * Receive incoming synchronous data.
431 */
432static int
433nga_rcv_sync(const sc_p sc, struct mbuf *m, meta_p meta)
434{
435 struct ifnet *const rcvif = m->m_pkthdr.rcvif;
436 int alen, error = 0;
437 struct timeval time;
438 u_int16_t fcs, fcs0;
439 u_int32_t accm;
440
441#define ADD_BYTE(x) nga_async_add(sc, &fcs, accm, &alen, (x))
442
443 /* Check for bypass mode */
444 if (!sc->cfg.enabled) {
445 NG_SEND_DATA(error, sc->async, m, meta);
446 return (error);
447 }
448
449 /* Get ACCM; special case LCP frames, which use full ACCM */
450 accm = sc->cfg.accm;
451 if (m->m_pkthdr.len >= 4) {
452 static const u_char lcphdr[4] = {
453 PPP_ALLSTATIONS,
454 PPP_UI,
455 (u_char)(PPP_LCP >> 8),
456 (u_char)(PPP_LCP & 0xff)
457 };
458 u_char buf[4];
459
460 m_copydata(m, 0, 4, (caddr_t)buf);
461 if (bcmp(buf, &lcphdr, 4) == 0)
462 accm = ~0;
463 }
464
465 /* Check for overflow */
466 if (m->m_pkthdr.len > sc->cfg.smru) {
467 sc->stats.syncOverflows++;
468 NG_FREE_DATA(m, meta);
469 return (EMSGSIZE);
470 }
471
472 /* Update stats */
473 sc->stats.syncFrames++;
474 sc->stats.syncOctets += m->m_pkthdr.len;
475
476 /* Initialize async encoded version of input mbuf */
477 alen = 0;
478 fcs = PPP_INITFCS;
479
480 /* Add beginning sync flag if it's been long enough to need one */
481 getmicrotime(&time);
482 if (time.tv_sec >= sc->lasttime + 1) {
483 sc->abuf[alen++] = PPP_FLAG;
484 sc->lasttime = time.tv_sec;
485 }
486
487 /* Add packet payload */
488 while (m != NULL) {
489 while (m->m_len > 0) {
490 ADD_BYTE(*mtod(m, u_char *));
491 m->m_data++;
492 m->m_len--;
493 }
494 m = m_free(m);
495 }
496
497 /* Add checksum and final sync flag */
498 fcs0 = fcs;
499 ADD_BYTE(~fcs0 & 0xff);
500 ADD_BYTE(~fcs0 >> 8);
501 sc->abuf[alen++] = PPP_FLAG;
502
503 /* Put frame in an mbuf and ship it off */
504 if (!(m = m_devget(sc->abuf, alen, 0, rcvif, NULL))) {
505 NG_FREE_META(meta);
506 error = ENOBUFS;
507 } else
508 NG_SEND_DATA(error, sc->async, m, meta);
509 return (error);
510}
511
512/*
513 * Receive incoming asynchronous data
514 * XXX Technically, we should strip out incoming characters
515 * that are in our ACCM. Not sure if this is good or not.
516 */
517static int
518nga_rcv_async(const sc_p sc, struct mbuf * m, meta_p meta)
519{
520 struct ifnet *const rcvif = m->m_pkthdr.rcvif;
521 int error;
522
523 if (!sc->cfg.enabled) {
524 NG_SEND_DATA(error, sc->sync, m, meta);
525 return (error);
526 }
527 NG_FREE_META(meta);
528 while (m) {
529 struct mbuf *n;
530
531 for (; m->m_len > 0; m->m_data++, m->m_len--) {
532 u_char ch = *mtod(m, u_char *);
533
534 sc->stats.asyncOctets++;
535 if (ch == PPP_FLAG) { /* Flag overrides everything */
536 int skip = 0;
537
538 /* Check for runts */
539 if (sc->slen < 2) {
540 if (sc->slen > 0)
541 sc->stats.asyncRunts++;
542 goto reset;
543 }
544
545 /* Verify CRC */
546 if (sc->fcs != PPP_GOODFCS) {
547 sc->stats.asyncBadCheckSums++;
548 goto reset;
549 }
550 sc->slen -= 2;
551
552 /* Strip address and control fields */
553 if (sc->slen >= 2
554 && sc->sbuf[0] == PPP_ALLSTATIONS
555 && sc->sbuf[1] == PPP_UI)
556 skip = 2;
557
558 /* Check for frame too big */
559 if (sc->slen - skip > sc->cfg.amru) {
560 sc->stats.asyncOverflows++;
561 goto reset;
562 }
563
564 /* OK, ship it out */
565 if ((n = m_devget(sc->sbuf + skip,
566 sc->slen - skip, 0, rcvif, NULL)))
567 NG_SEND_DATA(error, sc->sync, n, meta);
568 sc->stats.asyncFrames++;
569reset:
570 sc->amode = MODE_NORMAL;
571 sc->fcs = PPP_INITFCS;
572 sc->slen = 0;
573 continue;
574 }
575 switch (sc->amode) {
576 case MODE_NORMAL:
577 if (ch == PPP_ESCAPE) {
578 sc->amode = MODE_ESC;
579 continue;
580 }
581 break;
582 case MODE_ESC:
583 ch ^= PPP_TRANS;
584 sc->amode = MODE_NORMAL;
585 break;
586 case MODE_HUNT:
587 default:
588 continue;
589 }
590
591 /* Add byte to frame */
592 if (sc->slen >= SYNC_BUF_SIZE(sc->cfg.amru)) {
593 sc->stats.asyncOverflows++;
594 sc->amode = MODE_HUNT;
595 sc->slen = 0;
596 } else {
597 sc->sbuf[sc->slen++] = ch;
598 sc->fcs = PPP_FCS(sc->fcs, ch);
599 }
600 }
601 m = m_free(m);
602 }
603 return (0);
604}