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 Paul Mackerras. All rights reserved.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in
32 * the documentation and/or other materials provided with the
35 * 3. The name(s) of the authors of this software must not be used to
36 * endorse or promote products derived from this software without
37 * prior written permission.
39 * 4. Redistributions of any form whatsoever must retain the following
41 * "This product includes software developed by Paul Mackerras
42 * <paulus@samba.org>".
44 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
45 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
46 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
47 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
49 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
50 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52 * $Id: ppp_ahdlc.c,v 1.3 2002/12/06 09:49:16 paulus Exp $
56 * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/stream.h>
61 #include <sys/errno.h>
66 #include <sys/cmn_err.h>
71 #include <sys/cmn_err.h>
75 #include <net/ppp_defs.h>
76 #include <net/pppio.h>
80 * Right now, mutex is only enabled for Solaris 2.x
87 * intpointer_t and uintpointer_t are signed and unsigned integer types
88 * large enough to hold any data pointer; that is, data pointers can be
89 * assigned into or from these integer types without losing precision.
90 * On recent Solaris releases, these types are defined in sys/int_types.h,
91 * but not on SunOS 4.x or the earlier Solaris versions.
93 #if defined(_LP64) || defined(_I32LPx)
94 typedef long intpointer_t;
95 typedef unsigned long uintpointer_t;
97 typedef int intpointer_t;
98 typedef unsigned int uintpointer_t;
101 MOD_OPEN_DECL(ahdlc_open);
102 MOD_CLOSE_DECL(ahdlc_close);
103 static int ahdlc_wput __P((queue_t *, mblk_t *));
104 static int ahdlc_rput __P((queue_t *, mblk_t *));
105 static void ahdlc_encode __P((queue_t *, mblk_t *));
106 static void ahdlc_decode __P((queue_t *, mblk_t *));
107 static int msg_byte __P((mblk_t *, unsigned int));
111 * Don't send HDLC start flag is last transmit is within 1.5 seconds -
112 * FLAG_TIME is defined is microseconds
114 #define FLAG_TIME 1500
115 #define ABS(x) (x >= 0 ? x : (-x))
119 * Extract byte i of message mp
121 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
125 * Is this LCP packet one we have to transmit using LCP defaults?
127 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
130 * Standard STREAMS declarations
132 static struct module_info minfo = {
133 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
136 static struct qinit rinit = {
137 ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
140 static struct qinit winit = {
141 ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
144 #if defined(SVR4) && !defined(SOL2)
146 #define ppp_ahdlcinfo phdlinfo
147 #endif /* defined(SVR4) && !defined(SOL2) */
149 struct streamtab ppp_ahdlcinfo = {
150 &rinit, /* ptr to st_rdinit */
151 &winit, /* ptr to st_wrinit */
152 NULL, /* ptr to st_muxrinit */
153 NULL, /* ptr to st_muxwinit */
155 NULL /* ptr to ptr to st_modlist */
160 int ppp_ahdlc_count = 0; /* open counter */
164 * Per-stream state structure
166 typedef struct ahdlc_state {
167 #if defined(USE_MUTEX)
168 kmutex_t lock; /* lock for this structure */
169 #endif /* USE_MUTEX */
170 int flags; /* link flags */
171 mblk_t *rx_buf; /* ptr to receive buffer */
172 int rx_buf_size; /* receive buffer size */
173 ushort_t infcs; /* calculated rx HDLC FCS */
174 u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
175 u_int32_t raccm; /* 32-bit rcv ACCM */
176 int mtu; /* interface MTU */
177 int mru; /* link MRU */
178 int unit; /* current PPP unit number */
179 struct pppstat stats; /* statistic structure */
181 clock_t flag_time; /* time in usec between flags */
182 clock_t lbolt; /* last updated lbolt */
189 #define ESCAPED 0x100 /* last saw escape char on input */
190 #define IFLUSH 0x200 /* flushing input due to error */
193 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
195 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
198 * FCS lookup table as calculated by genfcstab.
200 static u_short fcstab[256] = {
201 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
202 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
203 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
204 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
205 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
206 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
207 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
208 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
209 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
210 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
211 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
212 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
213 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
214 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
215 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
216 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
217 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
218 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
219 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
220 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
221 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
222 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
223 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
224 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
225 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
226 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
227 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
228 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
229 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
230 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
231 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
232 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
235 static u_int32_t paritytab[8] =
237 0x96696996, 0x69969669, 0x69969669, 0x96696996,
238 0x69969669, 0x96696996, 0x96696996, 0x69969669
242 * STREAMS module open (entry) point
246 ahdlc_state_t *state;
249 * Return if it's already opened
256 * This can only be opened as a module
258 if (sflag != MODOPEN) {
262 state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
265 bzero((caddr_t) state, sizeof(ahdlc_state_t));
267 q->q_ptr = (caddr_t) state;
268 WR(q)->q_ptr = (caddr_t) state;
270 #if defined(USE_MUTEX)
271 mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
272 mutex_enter(&state->lock);
273 #endif /* USE_MUTEX */
275 state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
276 state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
277 state->mru = PPP_MRU; /* default of 1500 bytes */
279 state->flag_time = drv_usectohz(FLAG_TIME);
282 #if defined(USE_MUTEX)
283 mutex_exit(&state->lock);
284 #endif /* USE_MUTEX */
296 * STREAMS module close (exit) point
298 MOD_CLOSE(ahdlc_close)
300 ahdlc_state_t *state;
304 state = (ahdlc_state_t *) q->q_ptr;
307 DPRINT("state == 0 in ahdlc_close\n");
311 #if defined(USE_MUTEX)
312 mutex_enter(&state->lock);
313 #endif /* USE_MUTEX */
315 if (state->rx_buf != 0) {
316 freemsg(state->rx_buf);
320 #if defined(USE_MUTEX)
321 mutex_exit(&state->lock);
322 mutex_destroy(&state->lock);
323 #endif /* USE_MUTEX */
325 FREE(q->q_ptr, sizeof(ahdlc_state_t));
327 OTHERQ(q)->q_ptr = NULL;
338 * Write side put routine
345 ahdlc_state_t *state;
349 struct ppp_stats *psp;
351 state = (ahdlc_state_t *) q->q_ptr;
353 DPRINT("state == 0 in ahdlc_wput\n");
358 switch (mp->b_datap->db_type) {
361 * A data packet - do character-stuffing and FCS, and
369 iop = (struct iocblk *) mp->b_rptr;
371 switch (iop->ioc_cmd) {
373 if ((iop->ioc_count < sizeof(u_int32_t)) ||
374 (iop->ioc_count > sizeof(ext_accm))) {
377 if (mp->b_cont == 0) {
378 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
381 #if defined(USE_MUTEX)
382 mutex_enter(&state->lock);
383 #endif /* USE_MUTEX */
384 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
386 state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
387 state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
388 #if defined(USE_MUTEX)
389 mutex_exit(&state->lock);
390 #endif /* USE_MUTEX */
396 if (iop->ioc_count != sizeof(u_int32_t))
398 if (mp->b_cont == 0) {
399 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
402 #if defined(USE_MUTEX)
403 mutex_enter(&state->lock);
404 #endif /* USE_MUTEX */
405 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
407 #if defined(USE_MUTEX)
408 mutex_exit(&state->lock);
409 #endif /* USE_MUTEX */
415 np = allocb(sizeof(int), BPRI_HI);
423 #if defined(USE_MUTEX)
424 mutex_enter(&state->lock);
425 #endif /* USE_MUTEX */
426 *(int *)np->b_wptr = state->flags & RCV_FLAGS;
427 #if defined(USE_MUTEX)
428 mutex_exit(&state->lock);
429 #endif /* USE_MUTEX */
430 np->b_wptr += sizeof(int);
431 iop->ioc_count = sizeof(int);
436 np = allocb(sizeof(struct ppp_stats), BPRI_HI);
444 psp = (struct ppp_stats *) np->b_wptr;
445 np->b_wptr += sizeof(struct ppp_stats);
446 bzero((caddr_t)psp, sizeof(struct ppp_stats));
447 psp->p = state->stats;
448 iop->ioc_count = sizeof(struct ppp_stats);
453 /* we knew this anyway */
464 else if (error == 0) {
465 mp->b_datap->db_type = M_IOCACK;
468 mp->b_datap->db_type = M_IOCNAK;
470 iop->ioc_error = error;
476 switch (*mp->b_rptr) {
478 #if defined(USE_MUTEX)
479 mutex_enter(&state->lock);
480 #endif /* USE_MUTEX */
481 state->mtu = ((unsigned short *)mp->b_rptr)[1];
482 #if defined(USE_MUTEX)
483 mutex_exit(&state->lock);
484 #endif /* USE_MUTEX */
488 #if defined(USE_MUTEX)
489 mutex_enter(&state->lock);
490 #endif /* USE_MUTEX */
491 state->mru = ((unsigned short *)mp->b_rptr)[1];
492 #if defined(USE_MUTEX)
493 mutex_exit(&state->lock);
494 #endif /* USE_MUTEX */
498 #if defined(USE_MUTEX)
499 mutex_enter(&state->lock);
500 #endif /* USE_MUTEX */
501 state->unit = mp->b_rptr[1];
502 #if defined(USE_MUTEX)
503 mutex_exit(&state->lock);
504 #endif /* USE_MUTEX */
519 * Read side put routine
526 ahdlc_state_t *state;
528 state = (ahdlc_state_t *) q->q_ptr;
530 DPRINT("state == 0 in ahdlc_rput\n");
535 switch (mp->b_datap->db_type) {
541 #if defined(USE_MUTEX)
542 mutex_enter(&state->lock);
543 #endif /* USE_MUTEX */
544 if (state->rx_buf != 0) {
545 /* XXX would like to send this up for debugging */
546 freemsg(state->rx_buf);
549 state->flags = IFLUSH;
550 #if defined(USE_MUTEX)
551 mutex_exit(&state->lock);
552 #endif /* USE_MUTEX */
563 * Extract bit c from map m, to determine if c needs to be escaped
565 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
572 ahdlc_state_t *state;
573 u_int32_t *xaccm, loc_xaccm[8];
577 uchar_t *dp, fcs_val;
583 if (msgdsize(mp) < 4) {
587 state = (ahdlc_state_t *)q->q_ptr;
588 #if defined(USE_MUTEX)
589 mutex_enter(&state->lock);
590 #endif /* USE_MUTEX */
593 * Allocate an output buffer large enough to handle a case where all
594 * characters need to be escaped
596 outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
597 (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
598 (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
600 outmp = allocb(outmp_len, BPRI_MED);
602 state->stats.ppp_oerrors++;
603 #if defined(USE_MUTEX)
604 mutex_exit(&state->lock);
605 #endif /* USE_MUTEX */
606 putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
612 * Check if our last transmit happenned within flag_time, using
613 * the system's LBOLT value in clock ticks
615 if (drv_getparm(LBOLT, &lbolt) != -1) {
616 if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
617 *outmp->b_wptr++ = PPP_FLAG;
619 state->lbolt = lbolt;
621 *outmp->b_wptr++ = PPP_FLAG;
625 * If the driver below still has a message to process, skip the
626 * HDLC flag, otherwise, put one in the beginning
628 if (qsize(q->q_next) == 0) {
629 *outmp->b_wptr++ = PPP_FLAG;
634 * All control characters must be escaped for LCP packets with code
635 * values between 1 (Conf-Req) and 7 (Code-Rej).
637 is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
638 (MSG_BYTE(mp, 1) == PPP_UI) &&
639 (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
640 (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
643 xaccm = state->xaccm;
645 bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
646 loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
650 fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
653 * Process this block and the rest (if any) attached to the this one
655 for (tmp = mp; tmp; tmp = tmp->b_cont) {
656 if (tmp->b_datap->db_type == M_DATA) {
657 for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
658 fcs = PPP_FCS(fcs, *dp);
659 if (IN_TX_MAP(*dp, xaccm)) {
660 *outmp->b_wptr++ = PPP_ESCAPE;
661 *outmp->b_wptr++ = *dp ^ PPP_TRANS;
663 *outmp->b_wptr++ = *dp;
667 continue; /* skip if db_type is something other than M_DATA */
672 * Append the HDLC FCS, making sure that escaping is done on any
675 fcs_val = (fcs ^ 0xffff) & 0xff;
676 if (IN_TX_MAP(fcs_val, xaccm)) {
677 *outmp->b_wptr++ = PPP_ESCAPE;
678 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
680 *outmp->b_wptr++ = fcs_val;
683 fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
684 if (IN_TX_MAP(fcs_val, xaccm)) {
685 *outmp->b_wptr++ = PPP_ESCAPE;
686 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
688 *outmp->b_wptr++ = fcs_val;
692 * And finally, append the HDLC flag, and send it away
694 *outmp->b_wptr++ = PPP_FLAG;
696 state->stats.ppp_obytes += msgdsize(outmp);
697 state->stats.ppp_opackets++;
699 #if defined(USE_MUTEX)
700 mutex_exit(&state->lock);
701 #endif /* USE_MUTEX */
708 * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
710 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
715 * Process received characters.
722 ahdlc_state_t *state;
726 state = (ahdlc_state_t *) q->q_ptr;
728 #if defined(USE_MUTEX)
729 mutex_enter(&state->lock);
730 #endif /* USE_MUTEX */
732 state->stats.ppp_ibytes += msgdsize(mp);
734 for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
735 for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
738 * This should detect the lack of 8-bit communication channel
739 * which is necessary for PPP to work. In addition, it also
740 * checks on the parity.
743 state->flags |= RCV_B7_1;
745 state->flags |= RCV_B7_0;
747 if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
748 state->flags |= RCV_ODDP;
750 state->flags |= RCV_EVNP;
753 * So we have a HDLC flag ...
755 if (*dp == PPP_FLAG) {
758 * If we think that it marks the beginning of the frame,
759 * then continue to process the next octects
761 if ((state->flags & IFLUSH) ||
762 (state->rx_buf == 0) ||
763 (msgdsize(state->rx_buf) == 0)) {
765 state->flags &= ~IFLUSH;
770 * We get here because the above condition isn't true,
771 * in which case the HDLC flag was there to mark the end
772 * of the frame (or so we think)
776 if (state->infcs == PPP_GOODFCS) {
777 state->stats.ppp_ipackets++;
778 adjmsg(om, -PPP_FCSLEN);
781 DPRINT2("ppp%d: bad fcs (len=%d)\n",
782 state->unit, msgdsize(state->rx_buf));
783 freemsg(state->rx_buf);
784 state->flags &= ~(IFLUSH | ESCAPED);
785 state->stats.ppp_ierrors++;
786 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
793 if (state->flags & IFLUSH) {
798 * Allocate a receive buffer, large enough to store a frame (after
799 * un-escaping) of at least 1500 octets. If MRU is negotiated to
800 * be more than the default, then allocate that much. In addition,
801 * we add an extra 32-bytes for a fudge factor
803 if (state->rx_buf == 0) {
804 state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
805 state->rx_buf_size += (sizeof(u_int32_t) << 3);
806 state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
809 * If allocation fails, try again on the next frame
811 if (state->rx_buf == 0) {
812 state->flags |= IFLUSH;
815 state->flags &= ~(IFLUSH | ESCAPED);
816 state->infcs = PPP_INITFCS;
819 if (*dp == PPP_ESCAPE) {
820 state->flags |= ESCAPED;
825 * Make sure we un-escape the necessary characters, as well as the
826 * ones in our receive async control character map
828 if (state->flags & ESCAPED) {
830 state->flags &= ~ESCAPED;
831 } else if (IN_RX_MAP(*dp, state->raccm))
835 * Unless the peer lied to us about the negotiated MRU, we should
836 * never get a frame which is too long. If it happens, toss it away
837 * and grab the next incoming one
839 if (msgdsize(state->rx_buf) < state->rx_buf_size) {
840 state->infcs = PPP_FCS(state->infcs, *dp);
841 *state->rx_buf->b_wptr++ = *dp;
843 DPRINT2("ppp%d: frame too long (%d)\n",
844 state->unit, msgdsize(state->rx_buf));
845 freemsg(state->rx_buf);
847 state->flags |= IFLUSH;
851 #if defined(USE_MUTEX)
852 mutex_exit(&state->lock);
853 #endif /* USE_MUTEX */
861 while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
865 return mp->b_rptr[i];