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.1.1.4 2003/10/14 08:09:54 sparq 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>
72 * Right now, mutex is only enabled for Solaris 2.x
79 * intpointer_t and uintpointer_t are signed and unsigned integer types
80 * large enough to hold any data pointer; that is, data pointers can be
81 * assigned into or from these integer types without losing precision.
82 * On recent Solaris releases, these types are defined in sys/int_types.h,
83 * but not on SunOS 4.x or the earlier Solaris versions.
85 #if defined(_LP64) || defined(_I32LPx)
86 typedef long intpointer_t
;
87 typedef unsigned long uintpointer_t
;
89 typedef int intpointer_t
;
90 typedef unsigned int uintpointer_t
;
93 MOD_OPEN_DECL(ahdlc_open
);
94 MOD_CLOSE_DECL(ahdlc_close
);
95 static int ahdlc_wput
__P((queue_t
*, mblk_t
*));
96 static int ahdlc_rput
__P((queue_t
*, mblk_t
*));
97 static void ahdlc_encode
__P((queue_t
*, mblk_t
*));
98 static void ahdlc_decode
__P((queue_t
*, mblk_t
*));
99 static int msg_byte
__P((mblk_t
*, unsigned int));
103 * Don't send HDLC start flag is last transmit is within 1.5 seconds -
104 * FLAG_TIME is defined is microseconds
106 #define FLAG_TIME 1500
107 #define ABS(x) (x >= 0 ? x : (-x))
111 * Extract byte i of message mp
113 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
117 * Is this LCP packet one we have to transmit using LCP defaults?
119 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
122 * Standard STREAMS declarations
124 static struct module_info minfo
= {
125 0x7d23, "ppp_ahdl", 0, INFPSZ
, 32768, 512
128 static struct qinit rinit
= {
129 ahdlc_rput
, NULL
, ahdlc_open
, ahdlc_close
, NULL
, &minfo
, NULL
132 static struct qinit winit
= {
133 ahdlc_wput
, NULL
, NULL
, NULL
, NULL
, &minfo
, NULL
136 #if defined(SVR4) && !defined(SOL2)
138 #define ppp_ahdlcinfo phdlinfo
139 #endif /* defined(SVR4) && !defined(SOL2) */
141 struct streamtab ppp_ahdlcinfo
= {
142 &rinit
, /* ptr to st_rdinit */
143 &winit
, /* ptr to st_wrinit */
144 NULL
, /* ptr to st_muxrinit */
145 NULL
, /* ptr to st_muxwinit */
147 NULL
/* ptr to ptr to st_modlist */
152 int ppp_ahdlc_count
= 0; /* open counter */
156 * Per-stream state structure
158 typedef struct ahdlc_state
{
159 #if defined(USE_MUTEX)
160 kmutex_t lock
; /* lock for this structure */
161 #endif /* USE_MUTEX */
162 int flags
; /* link flags */
163 mblk_t
*rx_buf
; /* ptr to receive buffer */
164 int rx_buf_size
; /* receive buffer size */
165 ushort_t infcs
; /* calculated rx HDLC FCS */
166 u_int32_t xaccm
[8]; /* 256-bit xmit ACCM */
167 u_int32_t raccm
; /* 32-bit rcv ACCM */
168 int mtu
; /* interface MTU */
169 int mru
; /* link MRU */
170 int unit
; /* current PPP unit number */
171 struct pppstat stats
; /* statistic structure */
173 clock_t flag_time
; /* time in usec between flags */
174 clock_t lbolt
; /* last updated lbolt */
181 #define ESCAPED 0x100 /* last saw escape char on input */
182 #define IFLUSH 0x200 /* flushing input due to error */
185 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
187 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
190 * FCS lookup table as calculated by genfcstab.
192 static u_short fcstab
[256] = {
193 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
194 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
195 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
196 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
197 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
198 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
199 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
200 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
201 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
202 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
203 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
204 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
205 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
206 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
207 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
208 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
209 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
210 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
211 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
212 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
213 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
214 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
215 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
216 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
217 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
218 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
219 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
220 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
221 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
222 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
223 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
224 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
227 static u_int32_t paritytab
[8] =
229 0x96696996, 0x69969669, 0x69969669, 0x96696996,
230 0x69969669, 0x96696996, 0x96696996, 0x69969669
234 * STREAMS module open (entry) point
238 ahdlc_state_t
*state
;
241 * Return if it's already opened
248 * This can only be opened as a module
250 if (sflag
!= MODOPEN
) {
254 state
= (ahdlc_state_t
*) ALLOC_NOSLEEP(sizeof(ahdlc_state_t
));
257 bzero((caddr_t
) state
, sizeof(ahdlc_state_t
));
259 q
->q_ptr
= (caddr_t
) state
;
260 WR(q
)->q_ptr
= (caddr_t
) state
;
262 #if defined(USE_MUTEX)
263 mutex_init(&state
->lock
, NULL
, MUTEX_DEFAULT
, NULL
);
264 mutex_enter(&state
->lock
);
265 #endif /* USE_MUTEX */
267 state
->xaccm
[0] = ~0; /* escape 0x00 through 0x1f */
268 state
->xaccm
[3] = 0x60000000; /* escape 0x7d and 0x7e */
269 state
->mru
= PPP_MRU
; /* default of 1500 bytes */
271 state
->flag_time
= drv_usectohz(FLAG_TIME
);
274 #if defined(USE_MUTEX)
275 mutex_exit(&state
->lock
);
276 #endif /* USE_MUTEX */
288 * STREAMS module close (exit) point
290 MOD_CLOSE(ahdlc_close
)
292 ahdlc_state_t
*state
;
296 state
= (ahdlc_state_t
*) q
->q_ptr
;
299 DPRINT("state == 0 in ahdlc_close\n");
303 #if defined(USE_MUTEX)
304 mutex_enter(&state
->lock
);
305 #endif /* USE_MUTEX */
307 if (state
->rx_buf
!= 0) {
308 freemsg(state
->rx_buf
);
312 #if defined(USE_MUTEX)
313 mutex_exit(&state
->lock
);
314 mutex_destroy(&state
->lock
);
315 #endif /* USE_MUTEX */
317 FREE(q
->q_ptr
, sizeof(ahdlc_state_t
));
319 OTHERQ(q
)->q_ptr
= NULL
;
330 * Write side put routine
337 ahdlc_state_t
*state
;
341 struct ppp_stats
*psp
;
343 state
= (ahdlc_state_t
*) q
->q_ptr
;
345 DPRINT("state == 0 in ahdlc_wput\n");
350 switch (mp
->b_datap
->db_type
) {
353 * A data packet - do character-stuffing and FCS, and
361 iop
= (struct iocblk
*) mp
->b_rptr
;
363 switch (iop
->ioc_cmd
) {
365 if ((iop
->ioc_count
< sizeof(u_int32_t
)) ||
366 (iop
->ioc_count
> sizeof(ext_accm
))) {
369 if (mp
->b_cont
== 0) {
370 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state
->unit
);
373 #if defined(USE_MUTEX)
374 mutex_enter(&state
->lock
);
375 #endif /* USE_MUTEX */
376 bcopy((caddr_t
)mp
->b_cont
->b_rptr
, (caddr_t
)state
->xaccm
,
378 state
->xaccm
[2] &= ~0x40000000; /* don't escape 0x5e */
379 state
->xaccm
[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
380 #if defined(USE_MUTEX)
381 mutex_exit(&state
->lock
);
382 #endif /* USE_MUTEX */
388 if (iop
->ioc_count
!= sizeof(u_int32_t
))
390 if (mp
->b_cont
== 0) {
391 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state
->unit
);
394 #if defined(USE_MUTEX)
395 mutex_enter(&state
->lock
);
396 #endif /* USE_MUTEX */
397 bcopy((caddr_t
)mp
->b_cont
->b_rptr
, (caddr_t
)&state
->raccm
,
399 #if defined(USE_MUTEX)
400 mutex_exit(&state
->lock
);
401 #endif /* USE_MUTEX */
407 np
= allocb(sizeof(int), BPRI_HI
);
415 #if defined(USE_MUTEX)
416 mutex_enter(&state
->lock
);
417 #endif /* USE_MUTEX */
418 *(int *)np
->b_wptr
= state
->flags
& RCV_FLAGS
;
419 #if defined(USE_MUTEX)
420 mutex_exit(&state
->lock
);
421 #endif /* USE_MUTEX */
422 np
->b_wptr
+= sizeof(int);
423 iop
->ioc_count
= sizeof(int);
428 np
= allocb(sizeof(struct ppp_stats
), BPRI_HI
);
436 psp
= (struct ppp_stats
*) np
->b_wptr
;
437 np
->b_wptr
+= sizeof(struct ppp_stats
);
438 bzero((caddr_t
)psp
, sizeof(struct ppp_stats
));
439 psp
->p
= state
->stats
;
440 iop
->ioc_count
= sizeof(struct ppp_stats
);
445 /* we knew this anyway */
456 else if (error
== 0) {
457 mp
->b_datap
->db_type
= M_IOCACK
;
460 mp
->b_datap
->db_type
= M_IOCNAK
;
462 iop
->ioc_error
= error
;
468 switch (*mp
->b_rptr
) {
470 #if defined(USE_MUTEX)
471 mutex_enter(&state
->lock
);
472 #endif /* USE_MUTEX */
473 state
->mtu
= ((unsigned short *)mp
->b_rptr
)[1];
474 #if defined(USE_MUTEX)
475 mutex_exit(&state
->lock
);
476 #endif /* USE_MUTEX */
480 #if defined(USE_MUTEX)
481 mutex_enter(&state
->lock
);
482 #endif /* USE_MUTEX */
483 state
->mru
= ((unsigned short *)mp
->b_rptr
)[1];
484 #if defined(USE_MUTEX)
485 mutex_exit(&state
->lock
);
486 #endif /* USE_MUTEX */
490 #if defined(USE_MUTEX)
491 mutex_enter(&state
->lock
);
492 #endif /* USE_MUTEX */
493 state
->unit
= mp
->b_rptr
[1];
494 #if defined(USE_MUTEX)
495 mutex_exit(&state
->lock
);
496 #endif /* USE_MUTEX */
511 * Read side put routine
518 ahdlc_state_t
*state
;
520 state
= (ahdlc_state_t
*) q
->q_ptr
;
522 DPRINT("state == 0 in ahdlc_rput\n");
527 switch (mp
->b_datap
->db_type
) {
534 #if defined(USE_MUTEX)
535 mutex_enter(&state
->lock
);
536 #endif /* USE_MUTEX */
537 if (state
->rx_buf
!= 0) {
538 freemsg(state
->rx_buf
);
541 state
->flags
= IFLUSH
;
542 #if defined(USE_MUTEX)
543 mutex_exit(&state
->lock
);
544 #endif /* USE_MUTEX */
555 * Extract bit c from map m, to determine if c needs to be escaped
557 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
564 ahdlc_state_t
*state
;
565 u_int32_t
*xaccm
, loc_xaccm
[8];
569 uchar_t
*dp
, fcs_val
;
575 if (msgdsize(mp
) < 4) {
579 state
= (ahdlc_state_t
*)q
->q_ptr
;
580 #if defined(USE_MUTEX)
581 mutex_enter(&state
->lock
);
582 #endif /* USE_MUTEX */
585 * Allocate an output buffer large enough to handle a case where all
586 * characters need to be escaped
588 outmp_len
= (msgdsize(mp
) << 1) + /* input block x 2 */
589 (sizeof(fcs
) << 2) + /* HDLC FCS x 4 */
590 (sizeof(uchar_t
) << 1); /* HDLC flags x 2 */
592 outmp
= allocb(outmp_len
, BPRI_MED
);
594 state
->stats
.ppp_oerrors
++;
595 #if defined(USE_MUTEX)
596 mutex_exit(&state
->lock
);
597 #endif /* USE_MUTEX */
598 putctl1(RD(q
)->q_next
, M_CTL
, PPPCTL_OERROR
);
604 * Check if our last transmit happenned within flag_time, using
605 * the system's LBOLT value in clock ticks
607 if (drv_getparm(LBOLT
, &lbolt
) != -1) {
608 if (ABS((clock_t)lbolt
- state
->lbolt
) > state
->flag_time
) {
609 *outmp
->b_wptr
++ = PPP_FLAG
;
611 state
->lbolt
= lbolt
;
613 *outmp
->b_wptr
++ = PPP_FLAG
;
617 * If the driver below still has a message to process, skip the
618 * HDLC flag, otherwise, put one in the beginning
620 if (qsize(q
->q_next
) == 0) {
621 *outmp
->b_wptr
++ = PPP_FLAG
;
626 * All control characters must be escaped for LCP packets with code
627 * values between 1 (Conf-Req) and 7 (Code-Rej).
629 is_lcp
= ((MSG_BYTE(mp
, 0) == PPP_ALLSTATIONS
) &&
630 (MSG_BYTE(mp
, 1) == PPP_UI
) &&
631 (MSG_BYTE(mp
, 2) == (PPP_LCP
>> 8)) &&
632 (MSG_BYTE(mp
, 3) == (PPP_LCP
& 0xff)) &&
635 xaccm
= state
->xaccm
;
637 bcopy((caddr_t
)state
->xaccm
, (caddr_t
)loc_xaccm
, sizeof(loc_xaccm
));
638 loc_xaccm
[0] = ~0; /* force escape on 0x00 through 0x1f */
642 fcs
= PPP_INITFCS
; /* Initial FCS is 0xffff */
645 * Process this block and the rest (if any) attached to the this one
647 for (tmp
= mp
; tmp
; tmp
= tmp
->b_cont
) {
648 if (tmp
->b_datap
->db_type
== M_DATA
) {
649 for (dp
= tmp
->b_rptr
; dp
< tmp
->b_wptr
; dp
++) {
650 fcs
= PPP_FCS(fcs
, *dp
);
651 if (IN_TX_MAP(*dp
, xaccm
)) {
652 *outmp
->b_wptr
++ = PPP_ESCAPE
;
653 *outmp
->b_wptr
++ = *dp
^ PPP_TRANS
;
655 *outmp
->b_wptr
++ = *dp
;
659 continue; /* skip if db_type is something other than M_DATA */
664 * Append the HDLC FCS, making sure that escaping is done on any
667 fcs_val
= (fcs
^ 0xffff) & 0xff;
668 if (IN_TX_MAP(fcs_val
, xaccm
)) {
669 *outmp
->b_wptr
++ = PPP_ESCAPE
;
670 *outmp
->b_wptr
++ = fcs_val
^ PPP_TRANS
;
672 *outmp
->b_wptr
++ = fcs_val
;
675 fcs_val
= ((fcs
^ 0xffff) >> 8) & 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
;
684 * And finally, append the HDLC flag, and send it away
686 *outmp
->b_wptr
++ = PPP_FLAG
;
688 state
->stats
.ppp_obytes
+= msgdsize(outmp
);
689 state
->stats
.ppp_opackets
++;
691 #if defined(USE_MUTEX)
692 mutex_exit(&state
->lock
);
693 #endif /* USE_MUTEX */
700 * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
702 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
707 * Process received characters.
714 ahdlc_state_t
*state
;
724 * In case the driver (or something below) doesn't send
725 * data upstream in one message block, concatenate everything
727 if (!((mp
->b_wptr
- mp
->b_rptr
== msgdsize(mp
)) &&
728 ((intpointer_t
)mp
->b_rptr
% sizeof(intpointer_t
) == 0))) {
730 zmp
= msgpullup(mp
, -1);
738 state
= (ahdlc_state_t
*) q
->q_ptr
;
740 #if defined(USE_MUTEX)
741 mutex_enter(&state
->lock
);
742 #endif /* USE_MUTEX */
744 state
->stats
.ppp_ibytes
+= msgdsize(mp
);
746 for (dp
= mp
->b_rptr
; dp
< mp
->b_wptr
; dp
++) {
749 * This should detect the lack of 8-bit communication channel
750 * which is necessary for PPP to work. In addition, it also
751 * checks on the parity.
754 state
->flags
|= RCV_B7_1
;
756 state
->flags
|= RCV_B7_0
;
758 if (paritytab
[*dp
>> 5] & (1 << (*dp
& 0x1f)))
759 state
->flags
|= RCV_ODDP
;
761 state
->flags
|= RCV_EVNP
;
764 * So we have a HDLC flag ...
766 if (*dp
== PPP_FLAG
) {
769 * If we think that it marks the beginning of the frame,
770 * then continue to process the next octects
772 if ((state
->flags
& IFLUSH
) ||
773 (state
->rx_buf
== 0) ||
774 (msgdsize(state
->rx_buf
) == 0)) {
776 state
->flags
&= ~IFLUSH
;
781 * We get here because the above condition isn't true,
782 * in which case the HDLC flag was there to mark the end
783 * of the frame (or so we think)
787 if (state
->infcs
== PPP_GOODFCS
) {
788 state
->stats
.ppp_ipackets
++;
789 adjmsg(om
, -PPP_FCSLEN
);
792 DPRINT2("ppp%d: bad fcs (len=%d)\n",
793 state
->unit
, msgdsize(state
->rx_buf
));
794 freemsg(state
->rx_buf
);
795 state
->flags
&= ~(IFLUSH
| ESCAPED
);
796 state
->stats
.ppp_ierrors
++;
797 putctl1(q
->q_next
, M_CTL
, PPPCTL_IERROR
);
804 if (state
->flags
& IFLUSH
) {
809 * Allocate a receive buffer, large enough to store a frame (after
810 * un-escaping) of at least 1500 octets. If MRU is negotiated to
811 * be more than the default, then allocate that much. In addition,
812 * we add an extra 32-bytes for a fudge factor
814 if (state
->rx_buf
== 0) {
815 state
->rx_buf_size
= (state
->mru
< PPP_MRU
? PPP_MRU
: state
->mru
);
816 state
->rx_buf_size
+= (sizeof(u_int32_t
) << 3);
817 state
->rx_buf
= allocb(state
->rx_buf_size
, BPRI_MED
);
820 * If allocation fails, try again on the next frame
822 if (state
->rx_buf
== 0) {
823 state
->flags
|= IFLUSH
;
826 state
->flags
&= ~(IFLUSH
| ESCAPED
);
827 state
->infcs
= PPP_INITFCS
;
830 if (*dp
== PPP_ESCAPE
) {
831 state
->flags
|= ESCAPED
;
836 * Make sure we un-escape the necessary characters, as well as the
837 * ones in our receive async control character map
839 if (state
->flags
& ESCAPED
) {
841 state
->flags
&= ~ESCAPED
;
842 } else if (IN_RX_MAP(*dp
, state
->raccm
))
846 * Unless the peer lied to us about the negotiated MRU, we should
847 * never get a frame which is too long. If it happens, toss it away
848 * and grab the next incoming one
850 if (msgdsize(state
->rx_buf
) < state
->rx_buf_size
) {
851 state
->infcs
= PPP_FCS(state
->infcs
, *dp
);
852 *state
->rx_buf
->b_wptr
++ = *dp
;
854 DPRINT2("ppp%d: frame too long (%d)\n",
855 state
->unit
, msgdsize(state
->rx_buf
));
856 freemsg(state
->rx_buf
);
858 state
->flags
|= IFLUSH
;
862 #if defined(USE_MUTEX)
863 mutex_exit(&state
->lock
);
864 #endif /* USE_MUTEX */
872 while (mp
!= 0 && i
>= mp
->b_wptr
- mp
->b_rptr
)
876 return mp
->b_rptr
[i
];