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 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
55 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
56 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
61 * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/stream.h>
66 #include <sys/errno.h>
71 #include <sys/cmn_err.h>
76 #include <sys/cmn_err.h>
80 #include <net/ppp_defs.h>
81 #include <net/pppio.h>
85 * Right now, mutex is only enabled for Solaris 2.x
92 * intpointer_t and uintpointer_t are signed and unsigned integer types
93 * large enough to hold any data pointer; that is, data pointers can be
94 * assigned into or from these integer types without losing precision.
95 * On recent Solaris releases, these types are defined in sys/int_types.h,
96 * but not on SunOS 4.x or the earlier Solaris versions.
98 #if defined(_LP64) || defined(_I32LPx)
99 typedef long intpointer_t;
100 typedef unsigned long uintpointer_t;
102 typedef int intpointer_t;
103 typedef unsigned int uintpointer_t;
106 MOD_OPEN_DECL(ahdlc_open);
107 MOD_CLOSE_DECL(ahdlc_close);
108 static int ahdlc_wput(queue_t *, mblk_t *);
109 static int ahdlc_rput(queue_t *, mblk_t *);
110 static void ahdlc_encode(queue_t *, mblk_t *);
111 static void ahdlc_decode(queue_t *, mblk_t *);
112 static int msg_byte(mblk_t *, unsigned int);
116 * Don't send HDLC start flag is last transmit is within 1.5 seconds -
117 * FLAG_TIME is defined is microseconds
119 #define FLAG_TIME 1500
120 #define ABS(x) (x >= 0 ? x : (-x))
124 * Extract byte i of message mp
126 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
130 * Is this LCP packet one we have to transmit using LCP defaults?
132 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
135 * Standard STREAMS declarations
137 static struct module_info minfo = {
138 0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
141 static struct qinit rinit = {
142 ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
145 static struct qinit winit = {
146 ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
149 #if defined(SVR4) && !defined(SOL2)
151 #define ppp_ahdlcinfo phdlinfo
152 #endif /* defined(SVR4) && !defined(SOL2) */
154 struct streamtab ppp_ahdlcinfo = {
155 &rinit, /* ptr to st_rdinit */
156 &winit, /* ptr to st_wrinit */
157 NULL, /* ptr to st_muxrinit */
158 NULL, /* ptr to st_muxwinit */
160 NULL /* ptr to ptr to st_modlist */
165 int ppp_ahdlc_count = 0; /* open counter */
169 * Per-stream state structure
171 typedef struct ahdlc_state {
172 #if defined(USE_MUTEX)
173 kmutex_t lock; /* lock for this structure */
174 #endif /* USE_MUTEX */
175 int flags; /* link flags */
176 mblk_t *rx_buf; /* ptr to receive buffer */
177 int rx_buf_size; /* receive buffer size */
178 ushort_t infcs; /* calculated rx HDLC FCS */
179 u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
180 u_int32_t raccm; /* 32-bit rcv ACCM */
181 int mtu; /* interface MTU */
182 int mru; /* link MRU */
183 int unit; /* current PPP unit number */
184 struct pppstat stats; /* statistic structure */
186 clock_t flag_time; /* time in usec between flags */
187 clock_t lbolt; /* last updated lbolt */
194 #define ESCAPED 0x100 /* last saw escape char on input */
195 #define IFLUSH 0x200 /* flushing input due to error */
198 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
200 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
203 * FCS lookup table as calculated by genfcstab.
205 static u_short fcstab[256] = {
206 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
207 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
208 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
209 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
210 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
211 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
212 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
213 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
214 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
215 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
216 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
217 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
218 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
219 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
220 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
221 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
222 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
223 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
224 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
225 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
226 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
227 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
228 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
229 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
230 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
231 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
232 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
233 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
234 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
235 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
236 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
237 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
240 static u_int32_t paritytab[8] =
242 0x96696996, 0x69969669, 0x69969669, 0x96696996,
243 0x69969669, 0x96696996, 0x96696996, 0x69969669
247 * STREAMS module open (entry) point
251 ahdlc_state_t *state;
254 * Return if it's already opened
261 * This can only be opened as a module
263 if (sflag != MODOPEN) {
267 state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
270 bzero((caddr_t) state, sizeof(ahdlc_state_t));
272 q->q_ptr = (caddr_t) state;
273 WR(q)->q_ptr = (caddr_t) state;
275 #if defined(USE_MUTEX)
276 mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
277 mutex_enter(&state->lock);
278 #endif /* USE_MUTEX */
280 state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
281 state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
282 state->mru = PPP_MRU; /* default of 1500 bytes */
284 state->flag_time = drv_usectohz(FLAG_TIME);
287 #if defined(USE_MUTEX)
288 mutex_exit(&state->lock);
289 #endif /* USE_MUTEX */
301 * STREAMS module close (exit) point
303 MOD_CLOSE(ahdlc_close)
305 ahdlc_state_t *state;
309 state = (ahdlc_state_t *) q->q_ptr;
312 DPRINT("state == 0 in ahdlc_close\n");
316 #if defined(USE_MUTEX)
317 mutex_enter(&state->lock);
318 #endif /* USE_MUTEX */
320 if (state->rx_buf != 0) {
321 freemsg(state->rx_buf);
325 #if defined(USE_MUTEX)
326 mutex_exit(&state->lock);
327 mutex_destroy(&state->lock);
328 #endif /* USE_MUTEX */
330 FREE(q->q_ptr, sizeof(ahdlc_state_t));
332 OTHERQ(q)->q_ptr = NULL;
343 * Write side put routine
350 ahdlc_state_t *state;
354 struct ppp_stats *psp;
356 state = (ahdlc_state_t *) q->q_ptr;
358 DPRINT("state == 0 in ahdlc_wput\n");
363 switch (mp->b_datap->db_type) {
366 * A data packet - do character-stuffing and FCS, and
374 iop = (struct iocblk *) mp->b_rptr;
376 switch (iop->ioc_cmd) {
378 if ((iop->ioc_count < sizeof(u_int32_t)) ||
379 (iop->ioc_count > sizeof(ext_accm))) {
382 if (mp->b_cont == 0) {
383 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
386 #if defined(USE_MUTEX)
387 mutex_enter(&state->lock);
388 #endif /* USE_MUTEX */
389 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
391 state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
392 state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
393 #if defined(USE_MUTEX)
394 mutex_exit(&state->lock);
395 #endif /* USE_MUTEX */
401 if (iop->ioc_count != sizeof(u_int32_t))
403 if (mp->b_cont == 0) {
404 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
407 #if defined(USE_MUTEX)
408 mutex_enter(&state->lock);
409 #endif /* USE_MUTEX */
410 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
412 #if defined(USE_MUTEX)
413 mutex_exit(&state->lock);
414 #endif /* USE_MUTEX */
420 np = allocb(sizeof(int), BPRI_HI);
428 #if defined(USE_MUTEX)
429 mutex_enter(&state->lock);
430 #endif /* USE_MUTEX */
431 *(int *)np->b_wptr = state->flags & RCV_FLAGS;
432 #if defined(USE_MUTEX)
433 mutex_exit(&state->lock);
434 #endif /* USE_MUTEX */
435 np->b_wptr += sizeof(int);
436 iop->ioc_count = sizeof(int);
441 np = allocb(sizeof(struct ppp_stats), BPRI_HI);
449 psp = (struct ppp_stats *) np->b_wptr;
450 np->b_wptr += sizeof(struct ppp_stats);
451 bzero((caddr_t)psp, sizeof(struct ppp_stats));
452 psp->p = state->stats;
453 iop->ioc_count = sizeof(struct ppp_stats);
458 /* we knew this anyway */
469 else if (error == 0) {
470 mp->b_datap->db_type = M_IOCACK;
473 mp->b_datap->db_type = M_IOCNAK;
475 iop->ioc_error = error;
481 switch (*mp->b_rptr) {
483 #if defined(USE_MUTEX)
484 mutex_enter(&state->lock);
485 #endif /* USE_MUTEX */
486 state->mtu = ((unsigned short *)mp->b_rptr)[1];
487 #if defined(USE_MUTEX)
488 mutex_exit(&state->lock);
489 #endif /* USE_MUTEX */
493 #if defined(USE_MUTEX)
494 mutex_enter(&state->lock);
495 #endif /* USE_MUTEX */
496 state->mru = ((unsigned short *)mp->b_rptr)[1];
497 #if defined(USE_MUTEX)
498 mutex_exit(&state->lock);
499 #endif /* USE_MUTEX */
503 #if defined(USE_MUTEX)
504 mutex_enter(&state->lock);
505 #endif /* USE_MUTEX */
506 state->unit = mp->b_rptr[1];
507 #if defined(USE_MUTEX)
508 mutex_exit(&state->lock);
509 #endif /* USE_MUTEX */
524 * Read side put routine
531 ahdlc_state_t *state;
533 state = (ahdlc_state_t *) q->q_ptr;
535 DPRINT("state == 0 in ahdlc_rput\n");
540 switch (mp->b_datap->db_type) {
546 #if defined(USE_MUTEX)
547 mutex_enter(&state->lock);
548 #endif /* USE_MUTEX */
549 if (state->rx_buf != 0) {
550 /* XXX would like to send this up for debugging */
551 freemsg(state->rx_buf);
554 state->flags = IFLUSH;
555 #if defined(USE_MUTEX)
556 mutex_exit(&state->lock);
557 #endif /* USE_MUTEX */
568 * Extract bit c from map m, to determine if c needs to be escaped
570 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
577 ahdlc_state_t *state;
578 u_int32_t *xaccm, loc_xaccm[8];
582 uchar_t *dp, fcs_val;
588 if (msgdsize(mp) < 4) {
592 state = (ahdlc_state_t *)q->q_ptr;
593 #if defined(USE_MUTEX)
594 mutex_enter(&state->lock);
595 #endif /* USE_MUTEX */
598 * Allocate an output buffer large enough to handle a case where all
599 * characters need to be escaped
601 outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
602 (sizeof(fcs) << 2) + /* HDLC FCS x 4 */
603 (sizeof(uchar_t) << 1); /* HDLC flags x 2 */
605 outmp = allocb(outmp_len, BPRI_MED);
607 state->stats.ppp_oerrors++;
608 #if defined(USE_MUTEX)
609 mutex_exit(&state->lock);
610 #endif /* USE_MUTEX */
611 putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
617 * Check if our last transmit happenned within flag_time, using
618 * the system's LBOLT value in clock ticks
620 if (drv_getparm(LBOLT, &lbolt) != -1) {
621 if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
622 *outmp->b_wptr++ = PPP_FLAG;
624 state->lbolt = lbolt;
626 *outmp->b_wptr++ = PPP_FLAG;
630 * If the driver below still has a message to process, skip the
631 * HDLC flag, otherwise, put one in the beginning
633 if (qsize(q->q_next) == 0) {
634 *outmp->b_wptr++ = PPP_FLAG;
639 * All control characters must be escaped for LCP packets with code
640 * values between 1 (Conf-Req) and 7 (Code-Rej).
642 is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
643 (MSG_BYTE(mp, 1) == PPP_UI) &&
644 (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
645 (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
648 xaccm = state->xaccm;
650 bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
651 loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
655 fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
658 * Process this block and the rest (if any) attached to the this one
660 for (tmp = mp; tmp; tmp = tmp->b_cont) {
661 if (tmp->b_datap->db_type == M_DATA) {
662 for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
663 fcs = PPP_FCS(fcs, *dp);
664 if (IN_TX_MAP(*dp, xaccm)) {
665 *outmp->b_wptr++ = PPP_ESCAPE;
666 *outmp->b_wptr++ = *dp ^ PPP_TRANS;
668 *outmp->b_wptr++ = *dp;
672 continue; /* skip if db_type is something other than M_DATA */
677 * Append the HDLC FCS, making sure that escaping is done on any
680 fcs_val = (fcs ^ 0xffff) & 0xff;
681 if (IN_TX_MAP(fcs_val, xaccm)) {
682 *outmp->b_wptr++ = PPP_ESCAPE;
683 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
685 *outmp->b_wptr++ = fcs_val;
688 fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
689 if (IN_TX_MAP(fcs_val, xaccm)) {
690 *outmp->b_wptr++ = PPP_ESCAPE;
691 *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
693 *outmp->b_wptr++ = fcs_val;
697 * And finally, append the HDLC flag, and send it away
699 *outmp->b_wptr++ = PPP_FLAG;
701 state->stats.ppp_obytes += msgdsize(outmp);
702 state->stats.ppp_opackets++;
704 #if defined(USE_MUTEX)
705 mutex_exit(&state->lock);
706 #endif /* USE_MUTEX */
713 * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
715 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
720 * Process received characters.
727 ahdlc_state_t *state;
731 state = (ahdlc_state_t *) q->q_ptr;
733 #if defined(USE_MUTEX)
734 mutex_enter(&state->lock);
735 #endif /* USE_MUTEX */
737 state->stats.ppp_ibytes += msgdsize(mp);
739 for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
740 for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
743 * This should detect the lack of 8-bit communication channel
744 * which is necessary for PPP to work. In addition, it also
745 * checks on the parity.
748 state->flags |= RCV_B7_1;
750 state->flags |= RCV_B7_0;
752 if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
753 state->flags |= RCV_ODDP;
755 state->flags |= RCV_EVNP;
758 * So we have a HDLC flag ...
760 if (*dp == PPP_FLAG) {
763 * If we think that it marks the beginning of the frame,
764 * then continue to process the next octects
766 if ((state->flags & IFLUSH) ||
767 (state->rx_buf == 0) ||
768 (msgdsize(state->rx_buf) == 0)) {
770 state->flags &= ~IFLUSH;
775 * We get here because the above condition isn't true,
776 * in which case the HDLC flag was there to mark the end
777 * of the frame (or so we think)
781 if (state->infcs == PPP_GOODFCS) {
782 state->stats.ppp_ipackets++;
783 adjmsg(om, -PPP_FCSLEN);
786 DPRINT2("ppp%d: bad fcs (len=%d)\n",
787 state->unit, msgdsize(state->rx_buf));
788 freemsg(state->rx_buf);
789 state->flags &= ~(IFLUSH | ESCAPED);
790 state->stats.ppp_ierrors++;
791 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
798 if (state->flags & IFLUSH) {
803 * Allocate a receive buffer, large enough to store a frame (after
804 * un-escaping) of at least 1500 octets. If MRU is negotiated to
805 * be more than the default, then allocate that much. In addition,
806 * we add an extra 32-bytes for a fudge factor
808 if (state->rx_buf == 0) {
809 state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
810 state->rx_buf_size += (sizeof(u_int32_t) << 3);
811 state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
814 * If allocation fails, try again on the next frame
816 if (state->rx_buf == 0) {
817 state->flags |= IFLUSH;
820 state->flags &= ~(IFLUSH | ESCAPED);
821 state->infcs = PPP_INITFCS;
824 if (*dp == PPP_ESCAPE) {
825 state->flags |= ESCAPED;
830 * Make sure we un-escape the necessary characters, as well as the
831 * ones in our receive async control character map
833 if (state->flags & ESCAPED) {
835 state->flags &= ~ESCAPED;
836 } else if (IN_RX_MAP(*dp, state->raccm))
840 * Unless the peer lied to us about the negotiated MRU, we should
841 * never get a frame which is too long. If it happens, toss it away
842 * and grab the next incoming one
844 if (msgdsize(state->rx_buf) < state->rx_buf_size) {
845 state->infcs = PPP_FCS(state->infcs, *dp);
846 *state->rx_buf->b_wptr++ = *dp;
848 DPRINT2("ppp%d: frame too long (%d)\n",
849 state->unit, msgdsize(state->rx_buf));
850 freemsg(state->rx_buf);
852 state->flags |= IFLUSH;
856 #if defined(USE_MUTEX)
857 mutex_exit(&state->lock);
858 #endif /* USE_MUTEX */
866 while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
870 return mp->b_rptr[i];