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.4 2004/11/15 00:57:54 carlsonj 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/stropts.h>
62 #include <sys/errno.h>
67 #include <sys/cmn_err.h>
72 #include <sys/cmn_err.h>
76 #include <net/ppp_defs.h>
77 #include <net/pppio.h>
81 * Right now, mutex is only enabled for Solaris 2.x
88 * intpointer_t and uintpointer_t are signed and unsigned integer types
89 * large enough to hold any data pointer; that is, data pointers can be
90 * assigned into or from these integer types without losing precision.
91 * On recent Solaris releases, these types are defined in sys/int_types.h,
92 * but not on SunOS 4.x or the earlier Solaris versions.
94 #if defined(_LP64) || defined(_I32LPx)
95 typedef long intpointer_t;
96 typedef unsigned long uintpointer_t;
98 typedef int intpointer_t;
99 typedef unsigned int uintpointer_t;
102 MOD_OPEN_DECL(ahdlc_open);
103 MOD_CLOSE_DECL(ahdlc_close);
104 static int ahdlc_wput __P((queue_t *, mblk_t *));
105 static int ahdlc_rput __P((queue_t *, mblk_t *));
106 static void ahdlc_encode __P((queue_t *, mblk_t *));
107 static void ahdlc_decode __P((queue_t *, mblk_t *));
108 static int msg_byte __P((mblk_t *, unsigned int));
112 * Don't send HDLC start flag is last transmit is within 1.5 seconds -
113 * FLAG_TIME is defined is microseconds
115 #define FLAG_TIME 1500
116 #define ABS(x) (x >= 0 ? x : (-x))
120 * Extract byte i of message mp
122 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
126 * Is this LCP packet one we have to transmit using LCP defaults?
128 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
131 * Standard STREAMS declarations
133 static struct module_info minfo = {
134 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
137 static struct qinit rinit = {
138 ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
141 static struct qinit winit = {
142 ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
145 #if defined(SVR4) && !defined(SOL2)
147 #define ppp_ahdlcinfo phdlinfo
148 #endif /* defined(SVR4) && !defined(SOL2) */
150 struct streamtab ppp_ahdlcinfo = {
151 &rinit, /* ptr to st_rdinit */
152 &winit, /* ptr to st_wrinit */
153 NULL, /* ptr to st_muxrinit */
154 NULL, /* ptr to st_muxwinit */
156 NULL /* ptr to ptr to st_modlist */
161 int ppp_ahdlc_count = 0; /* open counter */
165 * Per-stream state structure
167 typedef struct ahdlc_state {
168 #if defined(USE_MUTEX)
169 kmutex_t lock; /* lock for this structure */
170 #endif /* USE_MUTEX */
171 int flags; /* link flags */
172 mblk_t *rx_buf; /* ptr to receive buffer */
173 int rx_buf_size; /* receive buffer size */
174 ushort_t infcs; /* calculated rx HDLC FCS */
175 u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
176 u_int32_t raccm; /* 32-bit rcv ACCM */
177 int mtu; /* interface MTU */
178 int mru; /* link MRU */
179 int unit; /* current PPP unit number */
180 struct pppstat stats; /* statistic structure */
182 clock_t flag_time; /* time in usec between flags */
183 clock_t lbolt; /* last updated lbolt */
190 #define ESCAPED 0x100 /* last saw escape char on input */
191 #define IFLUSH 0x200 /* flushing input due to error */
194 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
196 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
199 * FCS lookup table as calculated by genfcstab.
201 static u_short fcstab[256] = {
202 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
203 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
204 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
205 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
206 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
207 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
208 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
209 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
210 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
211 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
212 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
213 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
214 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
215 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
216 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
217 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
218 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
219 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
220 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
221 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
222 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
223 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
224 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
225 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
226 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
227 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
228 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
229 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
230 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
231 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
232 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
233 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
236 static u_int32_t paritytab[8] =
238 0x96696996, 0x69969669, 0x69969669, 0x96696996,
239 0x69969669, 0x96696996, 0x96696996, 0x69969669
243 * STREAMS module open (entry) point
247 ahdlc_state_t *state;
251 * Return if it's already opened
258 * This can only be opened as a module
260 if (sflag != MODOPEN) {
264 state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
267 bzero((caddr_t) state, sizeof(ahdlc_state_t));
269 q->q_ptr = (caddr_t) state;
270 WR(q)->q_ptr = (caddr_t) state;
272 #if defined(USE_MUTEX)
273 mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
274 mutex_enter(&state->lock);
275 #endif /* USE_MUTEX */
277 state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
278 state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
279 state->mru = PPP_MRU; /* default of 1500 bytes */
281 state->flag_time = drv_usectohz(FLAG_TIME);
284 #if defined(USE_MUTEX)
285 mutex_exit(&state->lock);
286 #endif /* USE_MUTEX */
294 if ((mp = allocb(1, BPRI_HI)) != NULL) {
295 mp->b_datap->db_type = M_FLUSH;
296 *mp->b_wptr++ = FLUSHR;
304 * STREAMS module close (exit) point
306 MOD_CLOSE(ahdlc_close)
308 ahdlc_state_t *state;
312 state = (ahdlc_state_t *) q->q_ptr;
315 DPRINT("state == 0 in ahdlc_close\n");
319 #if defined(USE_MUTEX)
320 mutex_enter(&state->lock);
321 #endif /* USE_MUTEX */
323 if (state->rx_buf != 0) {
324 freemsg(state->rx_buf);
328 #if defined(USE_MUTEX)
329 mutex_exit(&state->lock);
330 mutex_destroy(&state->lock);
331 #endif /* USE_MUTEX */
333 FREE(q->q_ptr, sizeof(ahdlc_state_t));
335 OTHERQ(q)->q_ptr = NULL;
346 * Write side put routine
353 ahdlc_state_t *state;
357 struct ppp_stats *psp;
359 state = (ahdlc_state_t *) q->q_ptr;
361 DPRINT("state == 0 in ahdlc_wput\n");
366 switch (mp->b_datap->db_type) {
369 * A data packet - do character-stuffing and FCS, and
377 iop = (struct iocblk *) mp->b_rptr;
379 switch (iop->ioc_cmd) {
381 if ((iop->ioc_count < sizeof(u_int32_t)) ||
382 (iop->ioc_count > sizeof(ext_accm))) {
385 if (mp->b_cont == 0) {
386 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
389 #if defined(USE_MUTEX)
390 mutex_enter(&state->lock);
391 #endif /* USE_MUTEX */
392 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
394 state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
395 state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
396 #if defined(USE_MUTEX)
397 mutex_exit(&state->lock);
398 #endif /* USE_MUTEX */
404 if (iop->ioc_count != sizeof(u_int32_t))
406 if (mp->b_cont == 0) {
407 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
410 #if defined(USE_MUTEX)
411 mutex_enter(&state->lock);
412 #endif /* USE_MUTEX */
413 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
415 #if defined(USE_MUTEX)
416 mutex_exit(&state->lock);
417 #endif /* USE_MUTEX */
423 np = allocb(sizeof(int), BPRI_HI);
431 #if defined(USE_MUTEX)
432 mutex_enter(&state->lock);
433 #endif /* USE_MUTEX */
434 *(int *)np->b_wptr = state->flags & RCV_FLAGS;
435 #if defined(USE_MUTEX)
436 mutex_exit(&state->lock);
437 #endif /* USE_MUTEX */
438 np->b_wptr += sizeof(int);
439 iop->ioc_count = sizeof(int);
444 np = allocb(sizeof(struct ppp_stats), BPRI_HI);
452 psp = (struct ppp_stats *) np->b_wptr;
453 np->b_wptr += sizeof(struct ppp_stats);
454 bzero((caddr_t)psp, sizeof(struct ppp_stats));
455 psp->p = state->stats;
456 iop->ioc_count = sizeof(struct ppp_stats);
461 /* we knew this anyway */
472 else if (error == 0) {
473 mp->b_datap->db_type = M_IOCACK;
476 mp->b_datap->db_type = M_IOCNAK;
478 iop->ioc_error = error;
484 switch (*mp->b_rptr) {
486 #if defined(USE_MUTEX)
487 mutex_enter(&state->lock);
488 #endif /* USE_MUTEX */
489 state->mtu = ((unsigned short *)mp->b_rptr)[1];
490 #if defined(USE_MUTEX)
491 mutex_exit(&state->lock);
492 #endif /* USE_MUTEX */
496 #if defined(USE_MUTEX)
497 mutex_enter(&state->lock);
498 #endif /* USE_MUTEX */
499 state->mru = ((unsigned short *)mp->b_rptr)[1];
500 #if defined(USE_MUTEX)
501 mutex_exit(&state->lock);
502 #endif /* USE_MUTEX */
506 #if defined(USE_MUTEX)
507 mutex_enter(&state->lock);
508 #endif /* USE_MUTEX */
509 state->unit = mp->b_rptr[1];
510 #if defined(USE_MUTEX)
511 mutex_exit(&state->lock);
512 #endif /* USE_MUTEX */
527 * Read side put routine
534 ahdlc_state_t *state;
536 state = (ahdlc_state_t *) q->q_ptr;
538 DPRINT("state == 0 in ahdlc_rput\n");
543 switch (mp->b_datap->db_type) {
549 #if defined(USE_MUTEX)
550 mutex_enter(&state->lock);
551 #endif /* USE_MUTEX */
552 if (state->rx_buf != 0) {
553 /* XXX would like to send this up for debugging */
554 freemsg(state->rx_buf);
557 state->flags = IFLUSH;
558 #if defined(USE_MUTEX)
559 mutex_exit(&state->lock);
560 #endif /* USE_MUTEX */
571 * Extract bit c from map m, to determine if c needs to be escaped
573 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
580 ahdlc_state_t *state;
581 u_int32_t *xaccm, loc_xaccm[8];
585 uchar_t *dp, fcs_val;
591 if (msgdsize(mp) < 4) {
595 state = (ahdlc_state_t *)q->q_ptr;
596 #if defined(USE_MUTEX)
597 mutex_enter(&state->lock);
598 #endif /* USE_MUTEX */
601 * Allocate an output buffer large enough to handle a case where all
602 * characters need to be escaped
604 outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
605 (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
606 (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
608 outmp = allocb(outmp_len, BPRI_MED);
610 state->stats.ppp_oerrors++;
611 #if defined(USE_MUTEX)
612 mutex_exit(&state->lock);
613 #endif /* USE_MUTEX */
614 putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
620 * Check if our last transmit happenned within flag_time, using
621 * the system's LBOLT value in clock ticks
623 if (drv_getparm(LBOLT, &lbolt) != -1) {
624 if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
625 *outmp->b_wptr++ = PPP_FLAG;
627 state->lbolt = lbolt;
629 *outmp->b_wptr++ = PPP_FLAG;
633 * If the driver below still has a message to process, skip the
634 * HDLC flag, otherwise, put one in the beginning
636 if (qsize(q->q_next) == 0) {
637 *outmp->b_wptr++ = PPP_FLAG;
642 * All control characters must be escaped for LCP packets with code
643 * values between 1 (Conf-Req) and 7 (Code-Rej).
645 is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
646 (MSG_BYTE(mp, 1) == PPP_UI) &&
647 (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
648 (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
651 xaccm = state->xaccm;
653 bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
654 loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
658 fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
661 * Process this block and the rest (if any) attached to the this one
663 for (tmp = mp; tmp; tmp = tmp->b_cont) {
664 if (tmp->b_datap->db_type == M_DATA) {
665 for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
666 fcs = PPP_FCS(fcs, *dp);
667 if (IN_TX_MAP(*dp, xaccm)) {
668 *outmp->b_wptr++ = PPP_ESCAPE;
669 *outmp->b_wptr++ = *dp ^ PPP_TRANS;
671 *outmp->b_wptr++ = *dp;
675 continue; /* skip if db_type is something other than M_DATA */
680 * Append the HDLC FCS, making sure that escaping is done on any
683 fcs_val = (fcs ^ 0xffff) & 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;
691 fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
692 if (IN_TX_MAP(fcs_val, xaccm)) {
693 *outmp->b_wptr++ = PPP_ESCAPE;
694 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
696 *outmp->b_wptr++ = fcs_val;
700 * And finally, append the HDLC flag, and send it away
702 *outmp->b_wptr++ = PPP_FLAG;
704 state->stats.ppp_obytes += msgdsize(outmp);
705 state->stats.ppp_opackets++;
707 #if defined(USE_MUTEX)
708 mutex_exit(&state->lock);
709 #endif /* USE_MUTEX */
716 * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
718 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
723 * Process received characters.
730 ahdlc_state_t *state;
734 state = (ahdlc_state_t *) q->q_ptr;
736 #if defined(USE_MUTEX)
737 mutex_enter(&state->lock);
738 #endif /* USE_MUTEX */
740 state->stats.ppp_ibytes += msgdsize(mp);
742 for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
743 for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
746 * This should detect the lack of 8-bit communication channel
747 * which is necessary for PPP to work. In addition, it also
748 * checks on the parity.
751 state->flags |= RCV_B7_1;
753 state->flags |= RCV_B7_0;
755 if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
756 state->flags |= RCV_ODDP;
758 state->flags |= RCV_EVNP;
761 * So we have a HDLC flag ...
763 if (*dp == PPP_FLAG) {
766 * If we think that it marks the beginning of the frame,
767 * then continue to process the next octects
769 if ((state->flags & IFLUSH) ||
770 (state->rx_buf == 0) ||
771 (msgdsize(state->rx_buf) == 0)) {
773 state->flags &= ~IFLUSH;
778 * We get here because the above condition isn't true,
779 * in which case the HDLC flag was there to mark the end
780 * of the frame (or so we think)
784 if (state->infcs == PPP_GOODFCS) {
785 state->stats.ppp_ipackets++;
786 adjmsg(om, -PPP_FCSLEN);
789 DPRINT2("ppp%d: bad fcs (len=%d)\n",
790 state->unit, msgdsize(state->rx_buf));
791 freemsg(state->rx_buf);
792 state->flags &= ~(IFLUSH | ESCAPED);
793 state->stats.ppp_ierrors++;
794 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
801 if (state->flags & IFLUSH) {
806 * Allocate a receive buffer, large enough to store a frame (after
807 * un-escaping) of at least 1500 octets. If MRU is negotiated to
808 * be more than the default, then allocate that much. In addition,
809 * we add an extra 32-bytes for a fudge factor
811 if (state->rx_buf == 0) {
812 state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
813 state->rx_buf_size += (sizeof(u_int32_t) << 3);
814 state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
817 * If allocation fails, try again on the next frame
819 if (state->rx_buf == 0) {
820 state->flags |= IFLUSH;
823 state->flags &= ~(IFLUSH | ESCAPED);
824 state->infcs = PPP_INITFCS;
827 if (*dp == PPP_ESCAPE) {
828 state->flags |= ESCAPED;
833 * Make sure we un-escape the necessary characters, as well as the
834 * ones in our receive async control character map
836 if (state->flags & ESCAPED) {
838 state->flags &= ~ESCAPED;
839 } else if (IN_RX_MAP(*dp, state->raccm))
843 * Unless the peer lied to us about the negotiated MRU, we should
844 * never get a frame which is too long. If it happens, toss it away
845 * and grab the next incoming one
847 if (msgdsize(state->rx_buf) < state->rx_buf_size) {
848 state->infcs = PPP_FCS(state->infcs, *dp);
849 *state->rx_buf->b_wptr++ = *dp;
851 DPRINT2("ppp%d: frame too long (%d)\n",
852 state->unit, msgdsize(state->rx_buf));
853 freemsg(state->rx_buf);
855 state->flags |= IFLUSH;
859 #if defined(USE_MUTEX)
860 mutex_exit(&state->lock);
861 #endif /* USE_MUTEX */
869 while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
873 return mp->b_rptr[i];