2 * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
4 * Re-written by Adi Masputra <adi.masputra@sun.com>, based on
5 * the original ppp_ahdlc.c
7 * Copyright (c) 2000 by Sun Microsystems, Inc.
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation is hereby granted, provided that the above copyright
12 * notice appears in all copies.
14 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
15 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
16 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
18 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
19 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
21 * Copyright (c) 1994 The Australian National University.
22 * All rights reserved.
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, provided that the above copyright
26 * notice appears in all copies. This software is provided without any
27 * warranty, express or implied. The Australian National University
28 * makes no representations about the suitability of this software for
31 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
32 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
33 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
34 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
37 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
38 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
40 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
41 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
44 * $Id: ppp_ahdlc.c,v 1.14 2000/02/16 20:39:24 masputra Exp $
48 * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/stream.h>
53 #include <sys/errno.h>
58 #include <sys/cmn_err.h>
63 #include <sys/cmn_err.h>
67 #include <net/ppp_defs.h>
68 #include <net/pppio.h>
71 #if !defined(clock32_t)
72 typedef clock_t clock32_t;
73 #endif /* clock32_t */
76 * Right now, mutex is only enabled for Solaris 2.x
82 MOD_OPEN_DECL(ahdlc_open);
83 MOD_CLOSE_DECL(ahdlc_close);
84 static int ahdlc_wput __P((queue_t *, mblk_t *));
85 static int ahdlc_rput __P((queue_t *, mblk_t *));
86 static void ahdlc_encode __P((queue_t *, mblk_t *));
87 static void ahdlc_decode __P((queue_t *, mblk_t *));
88 static int msg_byte __P((mblk_t *, unsigned int));
92 * Don't send HDLC start flag is last transmit is within 1.5 seconds -
93 * FLAG_TIME is defined is microseconds
95 #define FLAG_TIME 1500
96 #define ABS(x) (x >= 0 ? x : (-x))
100 * Extract byte i of message mp
102 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
106 * Is this LCP packet one we have to transmit using LCP defaults?
108 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
111 * Standard STREAMS declarations
113 static struct module_info minfo = {
114 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
117 static struct qinit rinit = {
118 ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
121 static struct qinit winit = {
122 ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
125 #if defined(SVR4) && !defined(SOL2)
127 #define ppp_ahdlcinfo phdlinfo
128 #endif /* defined(SVR4) && !defined(SOL2) */
130 struct streamtab ppp_ahdlcinfo = {
131 &rinit, /* ptr to st_rdinit */
132 &winit, /* ptr to st_wrinit */
133 NULL, /* ptr to st_muxrinit */
134 NULL, /* ptr to st_muxwinit */
136 NULL /* ptr to ptr to st_modlist */
141 int ppp_ahdlc_count = 0; /* open counter */
145 * Per-stream state structure
147 typedef struct ahdlc_state {
148 #if defined(USE_MUTEX)
149 kmutex_t lock; /* lock for this structure */
150 #endif /* USE_MUTEX */
151 int flags; /* link flags */
152 mblk_t *rx_buf; /* ptr to receive buffer */
153 int rx_buf_size; /* receive buffer size */
154 ushort_t infcs; /* calculated rx HDLC FCS */
155 u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
156 u_int32_t raccm; /* 32-bit rcv ACCM */
157 int mtu; /* interface MTU */
158 int mru; /* link MRU */
159 int unit; /* current PPP unit number */
160 struct pppstat stats; /* statistic structure */
162 clock_t flag_time; /* time in usec between flags */
163 clock_t lbolt; /* last updated lbolt */
170 #define ESCAPED 0x100 /* last saw escape char on input */
171 #define IFLUSH 0x200 /* flushing input due to error */
174 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
176 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
179 * FCS lookup table as calculated by genfcstab.
181 static u_short fcstab[256] = {
182 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
183 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
184 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
185 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
186 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
187 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
188 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
189 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
190 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
191 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
192 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
193 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
194 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
195 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
196 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
197 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
198 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
199 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
200 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
201 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
202 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
203 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
204 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
205 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
206 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
207 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
208 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
209 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
210 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
211 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
212 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
213 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
216 static u_int32_t paritytab[8] =
218 0x96696996, 0x69969669, 0x69969669, 0x96696996,
219 0x69969669, 0x96696996, 0x96696996, 0x69969669
223 * STREAMS module open (entry) point
227 ahdlc_state_t *state;
230 * Return if it's already opened
237 * This can only be opened as a module
239 if (sflag != MODOPEN) {
243 state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
246 bzero((caddr_t) state, sizeof(ahdlc_state_t));
248 q->q_ptr = (caddr_t) state;
249 WR(q)->q_ptr = (caddr_t) state;
251 #if defined(USE_MUTEX)
252 mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
253 mutex_enter(&state->lock);
254 #endif /* USE_MUTEX */
256 state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
257 state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
258 state->mru = PPP_MRU; /* default of 1500 bytes */
260 state->flag_time = drv_usectohz(FLAG_TIME);
263 #if defined(USE_MUTEX)
264 mutex_exit(&state->lock);
265 #endif /* USE_MUTEX */
277 * STREAMS module close (exit) point
279 MOD_CLOSE(ahdlc_close)
281 ahdlc_state_t *state;
285 state = (ahdlc_state_t *) q->q_ptr;
288 DPRINT("state == 0 in ahdlc_close\n");
292 #if defined(USE_MUTEX)
293 mutex_enter(&state->lock);
294 #endif /* USE_MUTEX */
296 if (state->rx_buf != 0) {
297 freemsg(state->rx_buf);
301 #if defined(USE_MUTEX)
302 mutex_exit(&state->lock);
303 mutex_destroy(&state->lock);
304 #endif /* USE_MUTEX */
306 FREE(q->q_ptr, sizeof(ahdlc_state_t));
308 OTHERQ(q)->q_ptr = NULL;
319 * Write side put routine
326 ahdlc_state_t *state;
330 struct ppp_stats *psp;
332 state = (ahdlc_state_t *) q->q_ptr;
334 DPRINT("state == 0 in ahdlc_wput\n");
339 switch (mp->b_datap->db_type) {
342 * A data packet - do character-stuffing and FCS, and
350 iop = (struct iocblk *) mp->b_rptr;
352 switch (iop->ioc_cmd) {
354 if ((iop->ioc_count < sizeof(u_int32_t)) ||
355 (iop->ioc_count > sizeof(ext_accm))) {
358 if (mp->b_cont == 0) {
359 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
362 #if defined(USE_MUTEX)
363 mutex_enter(&state->lock);
364 #endif /* USE_MUTEX */
365 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
367 state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
368 state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
369 #if defined(USE_MUTEX)
370 mutex_exit(&state->lock);
371 #endif /* USE_MUTEX */
377 if (iop->ioc_count != sizeof(u_int32_t))
379 if (mp->b_cont == 0) {
380 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
383 #if defined(USE_MUTEX)
384 mutex_enter(&state->lock);
385 #endif /* USE_MUTEX */
386 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
388 #if defined(USE_MUTEX)
389 mutex_exit(&state->lock);
390 #endif /* USE_MUTEX */
396 np = allocb(sizeof(int), BPRI_HI);
404 #if defined(USE_MUTEX)
405 mutex_enter(&state->lock);
406 #endif /* USE_MUTEX */
407 *(int *)np->b_wptr = state->flags & RCV_FLAGS;
408 #if defined(USE_MUTEX)
409 mutex_exit(&state->lock);
410 #endif /* USE_MUTEX */
411 np->b_wptr += sizeof(int);
412 iop->ioc_count = sizeof(int);
417 np = allocb(sizeof(struct ppp_stats), BPRI_HI);
425 psp = (struct ppp_stats *) np->b_wptr;
426 np->b_wptr += sizeof(struct ppp_stats);
427 bzero((caddr_t)psp, sizeof(struct ppp_stats));
428 psp->p = state->stats;
429 iop->ioc_count = sizeof(struct ppp_stats);
434 /* we knew this anyway */
445 else if (error == 0) {
446 mp->b_datap->db_type = M_IOCACK;
449 mp->b_datap->db_type = M_IOCNAK;
451 iop->ioc_error = error;
457 switch (*mp->b_rptr) {
459 #if defined(USE_MUTEX)
460 mutex_enter(&state->lock);
461 #endif /* USE_MUTEX */
462 state->mtu = ((unsigned short *)mp->b_rptr)[1];
463 #if defined(USE_MUTEX)
464 mutex_exit(&state->lock);
465 #endif /* USE_MUTEX */
469 #if defined(USE_MUTEX)
470 mutex_enter(&state->lock);
471 #endif /* USE_MUTEX */
472 state->mru = ((unsigned short *)mp->b_rptr)[1];
473 #if defined(USE_MUTEX)
474 mutex_exit(&state->lock);
475 #endif /* USE_MUTEX */
479 #if defined(USE_MUTEX)
480 mutex_enter(&state->lock);
481 #endif /* USE_MUTEX */
482 state->unit = mp->b_rptr[1];
483 #if defined(USE_MUTEX)
484 mutex_exit(&state->lock);
485 #endif /* USE_MUTEX */
500 * Read side put routine
507 ahdlc_state_t *state;
509 state = (ahdlc_state_t *) q->q_ptr;
511 DPRINT("state == 0 in ahdlc_rput\n");
516 switch (mp->b_datap->db_type) {
523 #if defined(USE_MUTEX)
524 mutex_enter(&state->lock);
525 #endif /* USE_MUTEX */
526 if (state->rx_buf != 0) {
527 /* XXX would like to send this up for debugging */
528 freemsg(state->rx_buf);
531 state->flags = IFLUSH;
532 #if defined(USE_MUTEX)
533 mutex_exit(&state->lock);
534 #endif /* USE_MUTEX */
545 * Extract bit c from map m, to determine if c needs to be escaped
547 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
554 ahdlc_state_t *state;
555 u_int32_t *xaccm, loc_xaccm[8];
559 uchar_t *dp, fcs_val;
565 if (msgdsize(mp) < 4) {
569 state = (ahdlc_state_t *)q->q_ptr;
570 #if defined(USE_MUTEX)
571 mutex_enter(&state->lock);
572 #endif /* USE_MUTEX */
575 * Allocate an output buffer large enough to handle a case where all
576 * characters need to be escaped
578 outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
579 (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
580 (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
582 outmp = allocb(outmp_len, BPRI_MED);
584 state->stats.ppp_oerrors++;
585 #if defined(USE_MUTEX)
586 mutex_exit(&state->lock);
587 #endif /* USE_MUTEX */
588 putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
594 * Check if our last transmit happenned within flag_time, using
595 * the system's LBOLT value in clock ticks
597 if (drv_getparm(LBOLT, &lbolt) != -1) {
598 if (ABS((clock32_t)lbolt - state->lbolt) > state->flag_time) {
599 *outmp->b_wptr++ = PPP_FLAG;
601 state->lbolt = lbolt;
603 *outmp->b_wptr++ = PPP_FLAG;
607 * If the driver below still has a message to process, skip the
608 * HDLC flag, otherwise, put one in the beginning
610 if (qsize(q->q_next) == 0) {
611 *outmp->b_wptr++ = PPP_FLAG;
616 * All control characters must be escaped for LCP packets with code
617 * values between 1 (Conf-Req) and 7 (Code-Rej).
619 is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
620 (MSG_BYTE(mp, 1) == PPP_UI) &&
621 (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
622 (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
625 xaccm = state->xaccm;
627 bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
628 loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
632 fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
635 * Process this block and the rest (if any) attached to the this one
637 for (tmp = mp; tmp; tmp = tmp->b_cont) {
638 if (tmp->b_datap->db_type == M_DATA) {
639 for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
640 fcs = PPP_FCS(fcs, *dp);
641 if (IN_TX_MAP(*dp, xaccm)) {
642 *outmp->b_wptr++ = PPP_ESCAPE;
643 *outmp->b_wptr++ = *dp ^ PPP_TRANS;
645 *outmp->b_wptr++ = *dp;
649 continue; /* skip if db_type is something other than M_DATA */
654 * Append the HDLC FCS, making sure that escaping is done on any
657 fcs_val = (fcs ^ 0xffff) & 0xff;
658 if (IN_TX_MAP(fcs_val, xaccm)) {
659 *outmp->b_wptr++ = PPP_ESCAPE;
660 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
662 *outmp->b_wptr++ = fcs_val;
665 fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
666 if (IN_TX_MAP(fcs_val, xaccm)) {
667 *outmp->b_wptr++ = PPP_ESCAPE;
668 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
670 *outmp->b_wptr++ = fcs_val;
674 * And finally, append the HDLC flag, and send it away
676 *outmp->b_wptr++ = PPP_FLAG;
678 state->stats.ppp_obytes += msgdsize(outmp);
679 state->stats.ppp_opackets++;
681 #if defined(USE_MUTEX)
682 mutex_exit(&state->lock);
683 #endif /* USE_MUTEX */
690 * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
692 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
696 * SunOS 4.x does not have intptr_t or uintptr_t defined, so
700 typedef int intptr_t;
701 typedef unsigned int uintptr_t;
705 * Process received characters.
712 ahdlc_state_t *state;
722 * In case the driver (or something below) doesn't send
723 * data upstream in one message block, concatenate everything
725 if (!((mp->b_wptr - mp->b_rptr == msgdsize(mp)) &&
726 ((intptr_t)mp->b_rptr % sizeof(intptr_t) == 0))) {
728 zmp = msgpullup(mp, -1);
736 state = (ahdlc_state_t *) q->q_ptr;
738 #if defined(USE_MUTEX)
739 mutex_enter(&state->lock);
740 #endif /* USE_MUTEX */
742 state->stats.ppp_ibytes += msgdsize(mp);
744 for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
747 * This should detect the lack of 8-bit communication channel
748 * which is necessary for PPP to work. In addition, it also
749 * checks on the parity.
752 state->flags |= RCV_B7_1;
754 state->flags |= RCV_B7_0;
756 if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
757 state->flags |= RCV_ODDP;
759 state->flags |= RCV_EVNP;
762 * So we have a HDLC flag ...
764 if (*dp == PPP_FLAG) {
767 * If we think that it marks the beginning of the frame,
768 * then continue to process the next octects
770 if ((state->flags & IFLUSH) ||
771 (state->rx_buf == 0) ||
772 (msgdsize(state->rx_buf) == 0)) {
774 state->flags &= ~IFLUSH;
779 * We get here because the above condition isn't true,
780 * in which case the HDLC flag was there to mark the end
781 * of the frame (or so we think)
785 if (state->infcs == PPP_GOODFCS) {
786 state->stats.ppp_ipackets++;
787 adjmsg(om, -PPP_FCSLEN);
790 DPRINT2("ppp%d: bad fcs (len=%d)\n",
791 state->unit, msgdsize(state->rx_buf));
792 freemsg(state->rx_buf);
793 state->flags &= ~(IFLUSH | ESCAPED);
794 state->stats.ppp_ierrors++;
795 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
802 if (state->flags & IFLUSH) {
807 * Allocate a receive buffer, large enough to store a frame (after
808 * un-escaping) of at least 1500 octets. If MRU is negotiated to
809 * be more than the default, then allocate that much. In addition,
810 * we add an extra 32-bytes for a fudge factor
812 if (state->rx_buf == 0) {
813 state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
814 state->rx_buf_size += (sizeof(u_int32_t) << 3);
815 state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
818 * If allocation fails, try again on the next frame
820 if (state->rx_buf == 0) {
821 state->flags |= IFLUSH;
824 state->flags &= ~(IFLUSH | ESCAPED);
825 state->infcs = PPP_INITFCS;
828 if (*dp == PPP_ESCAPE) {
829 state->flags |= ESCAPED;
834 * Make sure we un-escape the necessary characters, as well as the
835 * ones in our receive async control character map
837 if (state->flags & ESCAPED) {
839 state->flags &= ~ESCAPED;
840 } else if (IN_RX_MAP(*dp, state->raccm))
844 * Unless the peer lied to us about the negotiated MRU, we should
845 * never get a frame which is too long. If it happens, toss it away
846 * and grab the next incoming one
848 if (msgdsize(state->rx_buf) < state->rx_buf_size) {
849 state->infcs = PPP_FCS(state->infcs, *dp);
850 *state->rx_buf->b_wptr++ = *dp;
852 DPRINT2("ppp%d: frame too long (%d)\n",
853 state->unit, msgdsize(state->rx_buf));
854 freemsg(state->rx_buf);
856 state->flags |= IFLUSH;
860 #if defined(USE_MUTEX)
861 mutex_exit(&state->lock);
862 #endif /* USE_MUTEX */
870 while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
874 return mp->b_rptr[i];