add -a option to print absolute times (instead of relative)
[mpls-ppp.git] / modules / ppp_ahdlc.c
blob6d0ef485da9fd0af456131f010a76046a0e0ad8c
1 /*
2 * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
4 * Copyright (c) 1994 The Australian National University.
5 * All rights reserved.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies. This software is provided without any
10 * warranty, express or implied. The Australian National University
11 * makes no representations about the suitability of this software for
12 * any purpose.
14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
18 * OF SUCH DAMAGE.
20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25 * OR MODIFICATIONS.
27 * $Id: ppp_ahdlc.c,v 1.10 1999/04/12 06:20:21 paulus Exp $
31 * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/stream.h>
36 #include <sys/errno.h>
38 #ifdef SVR4
39 #include <sys/conf.h>
40 #include <sys/kmem.h>
41 #include <sys/cmn_err.h>
42 #include <sys/ddi.h>
43 #else
44 #include <sys/user.h>
45 #ifdef __osf__
46 #include <sys/cmn_err.h>
47 #endif
48 #endif /* SVR4 */
50 #include <net/ppp_defs.h>
51 #include <net/pppio.h>
52 #include "ppp_mod.h"
54 #define IFRAME_BSIZE 512 /* Block size to allocate for input */
55 #define OFRAME_BSIZE 4096 /* Don't allocb more than this for output */
57 MOD_OPEN_DECL(ahdlc_open);
58 MOD_CLOSE_DECL(ahdlc_close);
59 static int ahdlc_wput __P((queue_t *, mblk_t *));
60 static int ahdlc_rput __P((queue_t *, mblk_t *));
61 static void stuff_frame __P((queue_t *, mblk_t *));
62 static void unstuff_chars __P((queue_t *, mblk_t *));
63 static int msg_byte __P((mblk_t *, unsigned int));
65 /* Extract byte i of message mp. */
66 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
67 msg_byte((mp), (i)))
69 /* Is this LCP packet one we have to transmit using LCP defaults? */
70 #define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
72 #define PPP_AHDL_ID 0x7d23
73 static struct module_info minfo = {
74 #ifdef PRIOQ
75 PPP_AHDL_ID, "ppp_ahdl", 0, INFPSZ, 640, 512
76 #else
77 PPP_AHDL_ID, "ppp_ahdl", 0, INFPSZ, 4096, 128
78 #endif PRIOQ
81 static struct qinit rinit = {
82 ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
85 static struct qinit winit = {
86 ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
89 #if defined(SVR4) && !defined(SOL2)
90 int phdldevflag = 0;
91 #define ppp_ahdlcinfo phdlinfo
92 #endif
93 struct streamtab ppp_ahdlcinfo = {
94 &rinit, &winit, NULL, NULL
97 int ppp_ahdlc_count;
99 typedef struct ahdlc_state {
100 int flags;
101 mblk_t *cur_frame;
102 mblk_t *cur_blk;
103 int inlen;
104 ushort infcs;
105 u_int32_t xaccm[8];
106 u_int32_t raccm;
107 int mtu;
108 int mru;
109 int unit;
110 struct pppstat stats;
111 } ahdlc_state_t;
113 /* Values for flags */
114 #define ESCAPED 0x100 /* last saw escape char on input */
115 #define IFLUSH 0x200 /* flushing input due to error */
117 /* RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also. */
118 #define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
121 * FCS lookup table as calculated by genfcstab.
123 static u_short fcstab[256] = {
124 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
125 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
126 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
127 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
128 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
129 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
130 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
131 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
132 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
133 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
134 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
135 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
136 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
137 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
138 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
139 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
140 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
141 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
142 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
143 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
144 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
145 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
146 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
147 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
148 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
149 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
150 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
151 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
152 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
153 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
154 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
155 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
159 * STREAMS module entry points.
161 MOD_OPEN(ahdlc_open)
163 ahdlc_state_t *sp;
165 if (q->q_ptr == 0) {
166 sp = (ahdlc_state_t *) ALLOC_SLEEP(sizeof(ahdlc_state_t));
167 if (sp == 0)
168 OPEN_ERROR(ENOSR);
169 bzero((caddr_t) sp, sizeof(ahdlc_state_t));
170 q->q_ptr = (caddr_t) sp;
171 WR(q)->q_ptr = (caddr_t) sp;
172 sp->xaccm[0] = ~0;
173 sp->xaccm[3] = 0x60000000;
174 sp->mru = PPP_MRU;
175 ++ppp_ahdlc_count;
176 qprocson(q);
178 return 0;
181 MOD_CLOSE(ahdlc_close)
183 ahdlc_state_t *state;
185 qprocsoff(q);
186 if (q->q_ptr != 0) {
187 state = (ahdlc_state_t *) q->q_ptr;
188 if (state->cur_frame != 0) {
189 freemsg(state->cur_frame);
190 state->cur_frame = 0;
192 FREE(q->q_ptr, sizeof(ahdlc_state_t));
193 q->q_ptr = NULL;
194 OTHERQ(q)->q_ptr = NULL;
195 --ppp_ahdlc_count;
197 return 0;
200 static int
201 ahdlc_wput(q, mp)
202 queue_t *q;
203 mblk_t *mp;
205 ahdlc_state_t *state;
206 struct iocblk *iop;
207 int error;
208 mblk_t *np;
209 struct ppp_stats *psp;
211 state = (ahdlc_state_t *) q->q_ptr;
212 if (state == 0) {
213 DPRINT("state == 0 in ahdlc_wput\n");
214 freemsg(mp);
215 return 0;
218 switch (mp->b_datap->db_type) {
219 case M_DATA:
221 * A data packet - do character-stuffing and FCS, and
222 * send it onwards.
224 stuff_frame(q, mp);
225 freemsg(mp);
226 break;
228 case M_IOCTL:
229 iop = (struct iocblk *) mp->b_rptr;
230 error = EINVAL;
231 switch (iop->ioc_cmd) {
232 case PPPIO_XACCM:
233 if (iop->ioc_count < sizeof(u_int32_t)
234 || iop->ioc_count > sizeof(ext_accm))
235 break;
236 if (mp->b_cont == 0) {
237 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
238 break;
240 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
241 iop->ioc_count);
242 state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
243 state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
244 iop->ioc_count = 0;
245 error = 0;
246 break;
248 case PPPIO_RACCM:
249 if (iop->ioc_count != sizeof(u_int32_t))
250 break;
251 if (mp->b_cont == 0) {
252 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
253 break;
255 bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
256 sizeof(u_int32_t));
257 iop->ioc_count = 0;
258 error = 0;
259 break;
261 case PPPIO_GCLEAN:
262 np = allocb(sizeof(int), BPRI_HI);
263 if (np == 0) {
264 error = ENOSR;
265 break;
267 if (mp->b_cont != 0)
268 freemsg(mp->b_cont);
269 mp->b_cont = np;
270 *(int *)np->b_wptr = state->flags & RCV_FLAGS;
271 np->b_wptr += sizeof(int);
272 iop->ioc_count = sizeof(int);
273 error = 0;
274 break;
276 case PPPIO_GETSTAT:
277 np = allocb(sizeof(struct ppp_stats), BPRI_HI);
278 if (np == 0) {
279 error = ENOSR;
280 break;
282 if (mp->b_cont != 0)
283 freemsg(mp->b_cont);
284 mp->b_cont = np;
285 psp = (struct ppp_stats *) np->b_wptr;
286 np->b_wptr += sizeof(struct ppp_stats);
287 bzero((caddr_t)psp, sizeof(struct ppp_stats));
288 psp->p = state->stats;
289 iop->ioc_count = sizeof(struct ppp_stats);
290 error = 0;
291 break;
293 case PPPIO_LASTMOD:
294 /* we knew this anyway */
295 error = 0;
296 break;
298 default:
299 error = -1;
300 break;
303 if (error < 0)
304 putnext(q, mp);
305 else if (error == 0) {
306 mp->b_datap->db_type = M_IOCACK;
307 qreply(q, mp);
308 } else {
309 mp->b_datap->db_type = M_IOCNAK;
310 iop->ioc_count = 0;
311 iop->ioc_error = error;
312 qreply(q, mp);
314 break;
316 case M_CTL:
317 switch (*mp->b_rptr) {
318 case PPPCTL_MTU:
319 state->mtu = ((unsigned short *)mp->b_rptr)[1];
320 freemsg(mp);
321 break;
322 case PPPCTL_MRU:
323 state->mru = ((unsigned short *)mp->b_rptr)[1];
324 freemsg(mp);
325 break;
326 case PPPCTL_UNIT:
327 state->unit = mp->b_rptr[1];
328 break;
329 default:
330 putnext(q, mp);
332 break;
334 default:
335 putnext(q, mp);
338 return 0;
341 static int
342 ahdlc_rput(q, mp)
343 queue_t *q;
344 mblk_t *mp;
346 mblk_t *np;
347 uchar_t *cp;
348 ahdlc_state_t *state;
350 state = (ahdlc_state_t *) q->q_ptr;
351 if (state == 0) {
352 DPRINT("state == 0 in ahdlc_rput\n");
353 freemsg(mp);
354 return 0;
357 switch (mp->b_datap->db_type) {
358 case M_DATA:
359 unstuff_chars(q, mp);
360 freemsg(mp);
361 break;
363 case M_HANGUP:
364 if (state->cur_frame != 0) {
365 /* XXX would like to send this up for debugging */
366 freemsg(state->cur_frame);
367 state->cur_frame = 0;
368 state->cur_blk = 0;
370 state->inlen = 0;
371 state->flags = IFLUSH;
372 putnext(q, mp);
373 break;
375 default:
376 putnext(q, mp);
378 return 0;
381 /* Extract bit c from map m, to determine if c needs to be escaped. */
382 #define ESCAPE(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
384 static void
385 stuff_frame(q, mp)
386 queue_t *q;
387 mblk_t *mp;
389 ahdlc_state_t *state;
390 int ilen, olen, c, extra, i, code;
391 mblk_t *omsg, *op, *np;
392 uchar_t *sp, *sp0, *dp, *dp0, *spend;
393 ushort_t fcs;
394 u_int32_t *xaccm, lcp_xaccm[8];
395 static uchar_t lcphdr[PPP_HDRLEN] = { 0xff, 0x03, 0xc0, 0x21 };
396 uchar_t ppphdr[PPP_HDRLEN];
398 state = (ahdlc_state_t *) q->q_ptr;
399 ilen = msgdsize(mp);
402 * We estimate the length of the output packet as
403 * 1.25 * input length + 16 (for initial flag, FCS, final flag, slop).
405 olen = ilen + (ilen >> 2) + 16;
406 if (olen > OFRAME_BSIZE)
407 olen = OFRAME_BSIZE;
408 omsg = op = allocb(olen, BPRI_MED);
409 if (omsg == 0)
410 goto bomb;
413 * Put in an initial flag, unless the serial driver currently has
414 * packets still to be transmitted in its queue.
416 dp = op->b_wptr;
417 if (qsize(q->q_next) == 0) {
418 *dp++ = PPP_FLAG;
419 --olen;
423 * For LCP packets with code values between 1 and 7 (Conf-Req
424 * to Code-Rej), we must escape all control characters.
426 xaccm = state->xaccm;
427 if (MSG_BYTE(mp, 0) == PPP_ALLSTATIONS
428 && MSG_BYTE(mp, 1) == PPP_UI
429 && MSG_BYTE(mp, 2) == (PPP_LCP >> 8)
430 && MSG_BYTE(mp, 3) == (PPP_LCP & 0xFF)
431 && LCP_USE_DFLT(mp)) {
432 bcopy((caddr_t) state->xaccm, (caddr_t) lcp_xaccm, sizeof(lcp_xaccm));
433 lcp_xaccm[0] = ~0;
434 xaccm = lcp_xaccm;
437 sp = mp->b_rptr;
438 fcs = PPP_INITFCS;
439 for (;;) {
440 spend = mp->b_wptr;
441 extra = sp + olen - spend;
442 if (extra < 0) {
443 spend = sp + olen;
444 extra = 0;
447 * We can safely process the input up to `spend'
448 * without overrunning the output, provided we don't
449 * hit more than `extra' characters which need to be escaped.
451 sp0 = sp;
452 dp0 = dp;
453 while (sp < spend) {
454 c = *sp;
455 if (ESCAPE(c, xaccm)) {
456 if (extra > 0)
457 --extra;
458 else if (sp < spend - 1)
459 --spend;
460 else
461 break;
462 fcs = PPP_FCS(fcs, c);
463 *dp++ = PPP_ESCAPE;
464 c ^= PPP_TRANS;
465 } else
466 fcs = PPP_FCS(fcs, c);
467 *dp++ = c;
468 ++sp;
470 ilen -= sp - sp0;
471 olen -= dp - dp0;
474 * At this point, we have emptied an input block
475 * and/or filled an output block.
477 if (sp >= mp->b_wptr) {
479 * We've emptied an input block. Advance to the next.
481 mp = mp->b_cont;
482 if (mp == 0)
483 break; /* all done */
484 sp = mp->b_rptr;
486 if (olen < 2) {
488 * The output block is full. Allocate a new one.
490 op->b_wptr = dp;
491 olen = 2 * ilen + 5;
492 if (olen > OFRAME_BSIZE)
493 olen = OFRAME_BSIZE;
494 np = allocb(olen, BPRI_MED);
495 if (np == 0)
496 goto bomb;
497 op->b_cont = np;
498 op = np;
499 dp = op->b_wptr;
504 * Append the FCS and closing flag.
505 * This could require up to 5 characters.
507 if (olen < 5) {
508 /* Sigh. Need another block. */
509 op->b_wptr = dp;
510 np = allocb(5, BPRI_MED);
511 if (np == 0)
512 goto bomb;
513 op->b_cont = np;
514 op = np;
515 dp = op->b_wptr;
517 c = ~fcs & 0xff;
518 if (ESCAPE(c, xaccm)) {
519 *dp++ = PPP_ESCAPE;
520 c ^= PPP_TRANS;
522 *dp++ = c;
523 c = (~fcs >> 8) & 0xff;
524 if (ESCAPE(c, xaccm)) {
525 *dp++ = PPP_ESCAPE;
526 c ^= PPP_TRANS;
528 *dp++ = c;
529 *dp++ = PPP_FLAG;
530 op->b_wptr = dp;
533 * Update statistics.
535 state->stats.ppp_obytes += msgdsize(omsg);
536 state->stats.ppp_opackets++;
539 * Send it on.
541 putnext(q, omsg);
542 return;
544 bomb:
545 if (omsg != 0)
546 freemsg(omsg);
547 state->stats.ppp_oerrors++;
548 putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
551 #define UPDATE_FLAGS(c) { \
552 if ((c) & 0x80) \
553 state->flags |= RCV_B7_1; \
554 else \
555 state->flags |= RCV_B7_0; \
556 if (0x6996 & (1 << ((((c) >> 4) ^ (c)) & 0xf))) \
557 state->flags |= RCV_ODDP; \
558 else \
559 state->flags |= RCV_EVNP; \
563 * Process received characters.
565 static void
566 unstuff_chars(q, mp)
567 queue_t *q;
568 mblk_t *mp;
570 ahdlc_state_t *state;
571 mblk_t *om;
572 uchar_t *cp, *cpend, *dp, *dp0;
573 int c, len, extra, offset;
574 ushort_t fcs;
576 state = (ahdlc_state_t *) q->q_ptr;
577 state->stats.ppp_ibytes += msgdsize(mp);
578 cp = mp->b_rptr;
579 for (;;) {
581 * Advance to next input block if necessary.
583 if (cp >= mp->b_wptr) {
584 mp = mp->b_cont;
585 if (mp == 0)
586 break;
587 cp = mp->b_rptr;
588 continue;
591 if ((state->flags & (IFLUSH|ESCAPED)) == 0
592 && state->inlen > 0 && (om = state->cur_blk) != 0) {
594 * Process bulk chars as quickly as possible.
596 dp = om->b_wptr;
597 len = om->b_datap->db_lim - dp; /* max # output bytes */
598 extra = (mp->b_wptr - cp) - len;/* #input chars - #output bytes */
599 if (extra < 0) {
600 len += extra; /* we'll run out of input first */
601 extra = 0;
603 cpend = cp + len;
604 dp0 = dp;
605 fcs = state->infcs;
606 while (cp < cpend) {
607 c = *cp;
608 if (c == PPP_FLAG)
609 break;
610 ++cp;
611 UPDATE_FLAGS(c);
612 if (c == PPP_ESCAPE) {
613 if (extra > 0) {
614 --extra;
615 ++cpend;
617 if (cp >= cpend || (c = *cp) == PPP_FLAG) {
618 state->flags |= ESCAPED;
619 break;
621 ++cp;
622 UPDATE_FLAGS(c);
623 c ^= PPP_TRANS;
625 *dp++ = c;
626 fcs = PPP_FCS(fcs, c);
628 state->inlen += dp - dp0;
629 state->infcs = fcs;
630 om->b_wptr = dp;
631 if (cp >= mp->b_wptr)
632 continue; /* advance to the next mblk */
635 c = *cp++;
636 UPDATE_FLAGS(c);
637 if (c == PPP_FLAG) {
639 * End of a frame.
640 * If the ESCAPE flag is set, the frame ended with
641 * the frame abort sequence "}~".
643 om = state->cur_frame;
644 len = state->inlen;
645 state->cur_frame = 0;
646 state->inlen = 0;
647 if (len == 0 && (state->flags & IFLUSH) == 0)
648 continue;
649 state->stats.ppp_ipackets++;
650 if (om != 0 && (state->flags & (IFLUSH|ESCAPED)) == 0
651 && len > PPP_FCSLEN) {
652 if (state->infcs == PPP_GOODFCS) {
653 adjmsg(om, -PPP_FCSLEN); /* chop off fcs */
654 putnext(q, om); /* bombs away! */
655 continue;
657 DPRINT2("ppp%d: bad fcs (len=%d)\n", state->unit, len);
659 if (om != 0)
660 freemsg(om);
661 state->flags &= ~(IFLUSH|ESCAPED);
662 state->stats.ppp_ierrors++;
663 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
664 continue;
667 if (state->flags & IFLUSH)
668 continue;
669 if (state->flags & ESCAPED) {
670 c ^= PPP_TRANS;
671 state->flags &= ~ESCAPED;
672 } else if (c == PPP_ESCAPE) {
673 state->flags |= ESCAPED;
674 continue;
676 if (state->inlen == 0) {
678 * First byte of the frame: allocate the first message block.
680 om = allocb(IFRAME_BSIZE, BPRI_MED);
681 if (om == 0) {
682 state->flags |= IFLUSH;
683 continue;
685 state->cur_frame = om;
686 state->cur_blk = om;
687 state->infcs = PPP_INITFCS;
688 } else {
689 om = state->cur_blk;
690 if (om->b_wptr >= om->b_datap->db_lim) {
692 * Current message block is full. Allocate another one,
693 * unless we have run out of MRU.
695 if (state->inlen >= state->mru + PPP_HDRLEN + PPP_FCSLEN) {
696 state->flags |= IFLUSH;
697 DPRINT2("ppp%d: frame too long (%d)\n",
698 state->unit, state->inlen);
699 continue;
701 om = allocb(IFRAME_BSIZE, BPRI_MED);
702 if (om == 0) {
703 state->flags |= IFLUSH;
704 continue;
706 state->cur_blk->b_cont = om;
707 state->cur_blk = om;
711 if (state->inlen == 0) {
713 * We don't do address/control & protocol decompression here,
714 * but we try to put the first byte at an offset such that
715 * the info field starts on a word boundary. The code here
716 * will do this except for packets with protocol compression
717 * but not address/control compression.
719 if (c != PPP_ALLSTATIONS) {
720 om->b_wptr += 2;
721 if (c & 1)
722 ++om->b_wptr;
723 om->b_rptr = om->b_wptr;
727 *om->b_wptr++ = c;
728 ++state->inlen;
729 state->infcs = PPP_FCS(state->infcs, c);
733 static int
734 msg_byte(mp, i)
735 mblk_t *mp;
736 unsigned int i;
738 while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
739 mp = mp->b_cont;
740 if (mp == 0)
741 return -1;
742 return mp->b_rptr[i];