2 ppp_async.c - Streams async functions Also does FCS
4 Copyright (C) 1990 Brad K. Clements, All Rights Reserved
5 fcstab and some ideas nicked from if_ppp.c from cmu.
6 See copyright notice in if_ppp.h and NOTES
8 $Id: ppp_async.c,v 1.2 1994/12/05 00:54:58 paulus Exp $
11 #include <sys/types.h>
21 #include <net/net_globals.h>
22 #include <sys/param.h>
23 #include <sys/stream.h>
24 #include <sys/stropts.h>
25 #include <sys/strconf.h>
26 #include <sys/device.h>
28 #include <sys/signal.h>
31 #include <sys/socket.h>
33 #include <netinet/in.h>
35 #include <net/ppp_defs.h>
36 #include <net/ppp_str.h>
38 /* how big of a buffer block to allocate for each chunk of the input chain */
42 #include <sys/syslog.h>
43 #define DLOG(s,a) if (p->pai_flags&PAI_FLAGS_DEBUG) bsdlog(LOG_INFO, s, a)
45 int ppp_async_max_dump_bytes = 28;
46 #define MAX_DUMP_BYTES 1504
48 static void ppp_dump_frame();
54 static int ppp_async_open(), ppp_async_close(), ppp_async_rput(),
55 ppp_async_wput(), ppp_async_wsrv(), ppp_async_rsrv();
57 static struct module_info minfo ={
58 0xabcd,"ppp_async",0, INFPSZ, 16384, 4096
61 static struct qinit r_init = {
62 ppp_async_rput, ppp_async_rsrv, ppp_async_open, ppp_async_close,
65 static struct qinit w_init = {
66 ppp_async_wput, ppp_async_wsrv, ppp_async_open, ppp_async_close,
69 struct streamtab ppp_asyncinfo = {
70 &r_init, &w_init, NULL, NULL
74 * FCS lookup table as calculated by genfcstab.
76 static u_short fcstab[256] = {
77 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
78 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
79 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
80 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
81 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
82 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
83 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
84 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
85 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
86 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
87 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
88 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
89 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
90 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
91 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
92 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
93 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
94 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
95 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
96 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
97 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
98 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
99 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
100 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
101 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
102 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
103 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
104 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
105 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
106 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
107 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
108 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
112 struct ppp_async_info {
114 int pai_buffsize; /* how big of an input buffer to alloc */
115 int pai_buffcount; /* how many chars currently in input buffer */
116 u_short pai_fcs; /* the current fcs */
117 mblk_t *pai_buffer; /* pointer to the current buffer list */
118 mblk_t *pai_bufftail; /* pointer to the current input block */
119 ext_accm pai_asyncmap; /* current outgoing asyncmap */
120 u_int32_t pai_rasyncmap; /* current receive asyncmap */
123 /* Values for pai_flags */
124 #define PAI_FLAGS_INUSE 0x1
125 #define PAI_FLAGS_FLUSH 0x2
126 #define PAI_FLAGS_ESCAPED 0x4
127 #define PAI_FLAGS_COMPPROT 0x8
128 #define PAI_FLAGS_COMPAC 0x10
129 #define PAI_FLAGS_RCV_COMPPROT 0x20
130 #define PAI_FLAGS_RCV_COMPAC 0x40
132 #define PAI_FLAGS_DEBUG 0x1000
133 #define PAI_FLAGS_LOG_INPKT 0x2000
134 #define PAI_FLAGS_LOG_OUTPKT 0x4000
135 #define PAI_FLAGS_ALL_DEBUG 0x7000
137 typedef struct ppp_async_info PAI;
139 static PAI pai[NUM_PPP*2]; /* our private cache of async ctrl structs */
141 static strconf_t pppasync_conf = {
142 "pppasync", &ppp_asyncinfo, STR_NEW_OPEN, 0, SQLVL_DEFAULT, (void *) 0
145 int ppp_async_load(int cmd, struct uio *uiop)
151 rc = str_install(STR_LOAD_MOD, &pppasync_conf);
154 rc = str_install(STR_UNLOAD_MOD, &pppasync_conf);
163 /* open might fail if we don't have any more pai elements left free */
165 ppp_async_open(q, dev, flag, sflag)
175 /* only let the superuser or setuid root ppl open this module */
181 for (x=0; x < NUM_PPP; x++) /* search for an empty PAI */
182 if (!(pai[x].pai_flags & PAI_FLAGS_INUSE))
184 if (x == NUM_PPP) { /* all buffers in use */
188 DLOG("ppp_async%d: opening\n",x);
190 /* initialize the unit to default values */
191 WR(q)->q_ptr = q->q_ptr = (caddr_t) p;
192 bzero(p, sizeof(*p));
193 p->pai_flags = PAI_FLAGS_INUSE | PAI_FLAGS_RCV_COMPAC
194 | PAI_FLAGS_RCV_COMPPROT;
195 p->pai_asyncmap[0] = 0xffffffff; /* default async map */
196 p->pai_asyncmap[3] = 0x60000000; /* escape 7d, 7e */
197 p->pai_buffsize = PPP_MTU + PPP_HDRLEN + PPP_FCSLEN;
200 p = (PAI *) q->q_ptr;
201 DLOG("ppp_async%d: reopen\n", p - pai);
208 queue_t *q; /* queue info */
213 if ((p = (PAI *) q->q_ptr) != NULL) {
214 p->pai_flags = 0; /* clear all flags */
216 /* currently receiving some chars, discard the buffer */
217 freemsg(p->pai_buffer);
218 p->pai_buffer = NULL;
220 DLOG("ppp_async%d: closing\n", p - pai);
226 /* M_IOCTL processing is performed at this level. There is some
227 weirdness here, but I couldn't think of an easier way to handle it.
229 SIOC{G,S}IF{,R,X}ASYNCMAP are handled here.
231 SIOCSIFCOMPAC and SIOCSIFCOMPPROT are both handled here.
233 SIOCSIFMRU and SIOCGIFMRU (Max Receive Unit) are both handled here.
234 Rather than using the MTU to set the MRU, we have a seperate IOCTL for it.
238 ppp_async_wput(q, mp)
242 register struct iocblk *i;
246 switch (mp->b_datap->db_type) {
249 if (*mp->b_rptr & FLUSHW)
250 flushq(q, FLUSHDATA);
251 putnext(q, mp); /* send it along too */
255 putq(q, mp); /* queue it for my service routine */
259 i = (struct iocblk *) mp->b_rptr;
260 p = (PAI *) q->q_ptr;
261 switch ((unsigned int)i->ioc_cmd) {
263 case SIOCSIFCOMPAC : /* enable or disable AC compression */
264 if (i->ioc_count != TRANSPARENT) {
265 i->ioc_error = EINVAL;
268 x = *(u_int *) mp->b_cont->b_rptr;
269 DLOG("ppp_async: SIFCOMPAC %d\n", x);
270 flags = (x & 2)? PAI_FLAGS_RCV_COMPAC: PAI_FLAGS_COMPAC;
272 p->pai_flags |= flags;
274 p->pai_flags &= ~flags;
278 case SIOCSIFCOMPPROT: /* enable or disable PROT compression */
279 if (i->ioc_count != TRANSPARENT) {
280 i->ioc_error = EINVAL;
283 x = *(u_int *) mp->b_cont->b_rptr;
284 DLOG("ppp_async: SIFCOMPPROT %d\n", x);
285 flags = (x & 2)? PAI_FLAGS_RCV_COMPPROT: PAI_FLAGS_COMPPROT;
287 p->pai_flags |= flags;
289 p->pai_flags &= ~flags;
295 if ((i->ioc_count != TRANSPARENT) &&
296 (i->ioc_count != sizeof(int))) {
297 i->ioc_error = EINVAL;
300 x = *(int *) mp->b_cont->b_rptr;
303 x += PPP_HDRLEN + PPP_FCSLEN;
304 if (x > 4096) { /* couldn't allocb something this big */
305 i->ioc_error = EINVAL;
313 if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
314 *(int *) mp->b_cont->b_wptr =
315 p->pai_buffsize - (PPP_HDRLEN + PPP_FCSLEN);
316 mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
319 i->ioc_error = ENOSR;
322 case SIOCGIFASYNCMAP :
323 if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
324 *(u_int32_t *) mp->b_cont->b_wptr = p->pai_asyncmap[0];
325 mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
328 i->ioc_error = ENOSR;
331 case SIOCSIFASYNCMAP :
332 if ((i->ioc_count != TRANSPARENT) &&
333 (i->ioc_count != sizeof(u_int32_t))) {
334 i->ioc_error = EINVAL;
335 goto iocnak; /* ugh, goto */
337 p->pai_asyncmap[0] = *(u_int32_t *) mp->b_cont->b_rptr;
338 DLOG("ppp_async: SIFASYNCMAP %lx\n", p->pai_asyncmap[0]);
342 case SIOCGIFRASYNCMAP :
343 if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
344 *(u_int32_t *) mp->b_cont->b_wptr = p->pai_rasyncmap;
345 mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
348 i->ioc_error = ENOSR;
351 case SIOCSIFRASYNCMAP :
352 if ((i->ioc_count != TRANSPARENT) &&
353 (i->ioc_count != sizeof(u_int32_t))) {
354 i->ioc_error = EINVAL;
355 goto iocnak; /* ugh, goto */
357 p->pai_rasyncmap = *(u_int32_t *) mp->b_cont->b_rptr;
358 DLOG("ppp_async: SIFRASYNCMAP %lx\n", p->pai_rasyncmap);
362 case SIOCGIFXASYNCMAP :
363 if ((mp->b_cont = allocb(sizeof(ext_accm), BPRI_MED)) != NULL) {
364 bcopy(p->pai_asyncmap, mp->b_cont->b_wptr, sizeof(ext_accm));
365 mp->b_cont->b_wptr += i->ioc_count = sizeof(ext_accm);
368 i->ioc_error = ENOSR;
371 case SIOCSIFXASYNCMAP :
372 if ((i->ioc_count != TRANSPARENT) &&
373 (i->ioc_count != sizeof(ext_accm))) {
374 i->ioc_error = EINVAL;
375 goto iocnak; /* ugh, goto */
377 bcopy(*mp->b_cont->b_rptr, p->pai_asyncmap, sizeof(ext_accm));
378 p->pai_asyncmap[1] = 0; /* can't escape 20-3f */
379 p->pai_asyncmap[2] &= ~0x40000000; /* can't escape 5e */
380 p->pai_asyncmap[3] |= 0x60000000; /* must escape 7d, 7e */
385 if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
386 *(int *)mp->b_cont->b_wptr =
387 (unsigned)(p->pai_flags & PAI_FLAGS_ALL_DEBUG)
389 (p->pai_flags & PAI_FLAGS_HIBITS);
390 mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
393 i->ioc_error = ENOSR;
397 if ((i->ioc_count != TRANSPARENT) &&
398 (i->ioc_count != sizeof(int))) {
399 i->ioc_error = EINVAL;
400 goto iocnak; /* ugh, goto */
402 flags = *(int *)mp->b_cont->b_rptr;
403 DLOG("ppp_async: SIFIFDEBUG %x\n", flags);
404 p->pai_flags &= ~PAI_FLAGS_ALL_DEBUG | PAI_FLAGS_HIBITS;
405 p->pai_flags |= ((unsigned) flags * PAI_FLAGS_DEBUG)
406 & PAI_FLAGS_ALL_DEBUG;
411 mp->b_datap->db_type = M_IOCACK;
416 mp->b_datap->db_type = M_IOCNAK;
419 default: /* unknown IOCTL call */
420 putnext(q,mp); /* pass it along */
425 putnext(q, mp); /* don't know what to do with this, so send it along*/
433 register u_char *cp, *wp;
435 register u_short fcs;
436 register mblk_t *mp, *m0;
437 mblk_t *cop, *outgoing;
438 int proto, len, olen, c;
440 p = (PAI *) q->q_ptr;
442 while ((mp = getq(q)) != NULL) {
444 * we can only get M_DATA types into our Queue,
445 * due to our Put function
447 if (!canput(q->q_next)) {
452 /* at least a header required */
455 || (mp->b_wptr - mp->b_rptr < PPP_HDRLEN
456 && !pullupmsg(mp, PPP_HDRLEN))) {
457 freemsg(mp); /* discard the message */
458 DLOG("ppp_async: short message (%d)\n", len);
459 /* indicate output err */
460 putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
464 /* Do address/control and protocol compression */
465 proto = (mp->b_rptr[2] << 8) + mp->b_rptr[3];
466 if (p->pai_flags & PAI_FLAGS_COMPAC && proto != PPP_LCP
467 && mp->b_rptr[0] == PPP_ALLSTATIONS && mp->b_rptr[1] == PPP_UI) {
469 if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff)
471 } else if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff) {
472 mp->b_rptr[2] = mp->b_rptr[1];
473 mp->b_rptr[1] = mp->b_rptr[0];
477 m0 = mp; /* remember first message block */
481 * Estimate the required buffer length as 1.25 * message length
482 * to allow for escaped characters. If this isn't enough, we
483 * allocate another buffer later.
485 olen = len + (len >> 2) + 5;
488 else if (olen > 2048)
490 outgoing = cop = allocb(olen, BPRI_MED);
491 if (outgoing == NULL) {
492 DLOG("allocb(%d) failed!\n", olen);
493 /* should do something tricky here */
498 /* Put the initial flag in (we'll take it out later if we don't
503 #define SPECIAL(p, c) (p->pai_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
506 * Copy the message to the output block, escaping characters
510 for (cp = mp->b_rptr; cp < mp->b_wptr; ) {
513 /* grab another message block and put it on the end */
516 cop = allocb(olen, BPRI_MED);
519 linkb(outgoing, cop);
524 *wp++ = c ^ PPP_TRANS;
530 fcs = PPP_FCS(fcs, c);
532 mp = mp->b_cont; /* look at the next block */
533 } /* end while(mp) */
536 * Add the FCS and the trailing flag.
539 /* grab another message block for FCS and trailing flag */
541 cop = allocb(5, BPRI_MED);
544 linkb(outgoing, cop);
547 fcs ^= 0xffff; /* XOR the resulting FCS */
551 *wp++ = c ^ PPP_TRANS;
557 *wp++ = c ^ PPP_TRANS;
560 *wp++ = PPP_FLAG; /* add trailing PPP_FLAG */
566 * now we check to see if the lower queue has entries, if so,
567 * we assume that we don't need a leading PPP_FLAG because
568 * these packets will be sent back to back.
570 if (qsize(q->q_next) > 0) {
571 /* entries in next queue, remove the leading PPP_FLAG */
576 if (p->pai_flags & PAI_FLAGS_LOG_OUTPKT)
577 ppp_dump_frame(p, outgoing, " sent output");
579 putnext(q, outgoing);
582 nobuffs: /* well, we ran out of memory somewhere */
584 freemsg(outgoing); /* throw away what we have already */
585 putbq(q, m0); /* put back the original message */
586 putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
587 qenable(q); /* reschedule ourselves for later */
589 } /* end while(getq()) */
593 ppp_async_rput(q, mp)
597 switch (mp->b_datap->db_type) {
600 if(*mp->b_rptr & FLUSHR)
601 flushq(q, FLUSHDATA);
602 putnext(q, mp); /* send it along too */
606 putq(q, mp); /* queue it for my service routine */
610 putnext(q,mp); /* don't know what to do with this, so send it along */
614 static u_int32_t paritytab[8] = {
615 0x96696996, 0x69969669, 0x69969669, 0x96696996,
616 0x69969669, 0x96696996, 0x96696996, 0x69969669,
623 register mblk_t *mp, *bp;
625 register u_char *cp,c;
627 register u_char *wptr;
630 p = (PAI *) q->q_ptr;
632 #define INPUT_ERROR(q) putctl1(q, M_CTL, IF_INPUT_ERROR)
633 #define STUFF_CHAR(p,c) (*wptr++ = (c), (p)->pai_buffcount++)
634 #define FLUSHEM(q, p) (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
636 while ((mp = getq(q)) != NULL) {
637 /* we can only get M_DATA types into our Queue,
638 due to our Put function */
639 if (!canput(q->q_next)) {
643 m0 = mp; /* remember first message block */
644 for (; mp != NULL; mp = mp->b_cont) { /* for each message block */
646 while (cp < mp->b_wptr) {
649 /* Accumulate info to help with detecting
650 non 8-bit clean links. */
652 p->pai_flags |= PAI_FLAGS_B7_1;
654 p->pai_flags |= PAI_FLAGS_B7_0;
655 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
656 p->pai_flags |= PAI_FLAGS_PAR_ODD;
658 p->pai_flags |= PAI_FLAGS_PAR_EVEN;
660 /* Throw out chars in the receive asyncmap. */
661 if (c < 0x20 && (p->pai_rasyncmap & (1 << c)))
664 /* A flag marks the end of a frame. */
667 bcount = p->pai_buffcount;
668 p->pai_buffer = NULL;
669 p->pai_buffcount = 0;
671 /* if the escape indicator is set, then we have
672 seen the packet abort sequence "}~". */
673 if (p->pai_flags & (PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH)) {
674 if ((p->pai_flags & PAI_FLAGS_FLUSH) == 0)
675 DLOG("ppp_async: packet abort\n", 0);
676 p->pai_flags &= ~(PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH);
682 if (bcount > PPP_FCSLEN) { /* discard FCS */
683 adjmsg(bp, -PPP_FCSLEN);
684 bcount -= PPP_FCSLEN;
687 if (bcount < PPP_HDRLEN) {
690 DLOG("ppp_async: short input packet (%d)\n",
699 if (p->pai_fcs == PPP_GOODFCS) {
701 if (p->pai_flags & PAI_FLAGS_LOG_INPKT)
702 ppp_dump_frame(p, bp, " got input");
709 DLOG("ppp_async: FCS Error\n", 0);
715 /* here c != PPP_FLAG */
716 if (p->pai_flags & PAI_FLAGS_FLUSH) {
717 while (cp < mp->b_wptr && *cp != PPP_FLAG)
722 if (p->pai_flags & PAI_FLAGS_ESCAPED) {
723 p->pai_flags &= ~PAI_FLAGS_ESCAPED; /* clear esc flag */
725 } else if (c == PPP_ESCAPE) {
726 if (cp >= mp->b_wptr || (c = *cp) == PPP_FLAG
727 || c < 0x20 && (p->pai_rasyncmap & (1 << c))) {
728 p->pai_flags |= PAI_FLAGS_ESCAPED;
735 /* here we check to see if we have a buffer.
736 If we don't, we assume that this is the first char
737 for the buffer, and we allocb one */
739 if (!p->pai_buffer) {
740 /* we allocate buffer chains in blocks of ALLOCBSIZE */
742 if (!(p->pai_buffer = allocb(ALLOCBSIZE, BPRI_MED))) {
745 /* if we don't get a buffer, is there some way
746 to recover and requeue later? rather than flushing
747 the current packet... ? */
749 p->pai_bufftail = p->pai_buffer;
751 wptr = p->pai_bufftail->b_wptr;
753 if (!p->pai_buffcount) {
754 p->pai_fcs = PPP_INITFCS;
755 if (c != PPP_ALLSTATIONS) {
756 if (p->pai_flags & PAI_FLAGS_RCV_COMPAC) {
757 STUFF_CHAR(p, PPP_ALLSTATIONS);
758 STUFF_CHAR(p, PPP_UI);
761 DLOG("ppp_async: missed ALLSTATIONS (0xff), got 0x%x\n", c);
766 } /* end if !p->pai_buffcount */
768 if (p->pai_buffcount == 1 && c != PPP_UI) {
769 DLOG("ppp_async: missed UI (0x3), got 0x%x\n", c);
774 if (p->pai_buffcount == 2 && (c & 1) == 1) {
775 if (p->pai_flags & PAI_FLAGS_RCV_COMPPROT)
778 DLOG("ppp_async: bad protocol high byte %x\n", c);
784 if (p->pai_buffcount == 3 && (c & 1) == 0) {
785 DLOG("ppp_async: bad protocol low byte %x\n", c);
790 if (p->pai_buffcount >= p->pai_buffsize) { /* overrun */
791 DLOG("ppp_async: too many chars in input buffer %d\n",
797 /* determine if we have enough space in the buffer */
798 if (wptr >= p->pai_bufftail->b_datap->db_lim) {
799 p->pai_bufftail->b_wptr = wptr;
800 if (!(p->pai_bufftail = allocb(ALLOCBSIZE, BPRI_MED))) {
801 DLOG("ppp_async: couldn't get buffer for tail\n", 0);
802 FLUSHEM(q, p); /* discard all of it */
805 linkb(p->pai_buffer, p->pai_bufftail);
806 wptr = p->pai_bufftail->b_wptr;
810 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
812 if (p->pai_buffcount >= PPP_HDRLEN) {
813 while (cp < mp->b_wptr
814 && wptr < p->pai_bufftail->b_datap->db_lim
815 && (c = *cp) != PPP_FLAG && c != PPP_ESCAPE) {
816 if (c >= 0x20 || (p->pai_rasyncmap & (1 << c)) == 0) {
818 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
824 p->pai_bufftail->b_wptr = wptr;
826 } /* end while cp < wptr */
827 } /* end for each block */
828 /* discard this message now */
830 } /* end while getq */
836 * here is where we will dump out a frame in hex using the log()
837 * function if ppp_async_input_debug is non-zero. As this function is
838 * a pig, we only print up to the number of bytes specified by the value of
839 * the ppp_async_max_dump_bytes variable so as to not cause too many
840 * timeouts. <gmc@quotron.com>
844 ppp_dump_frame(p, mptr, msg)
846 register mblk_t *mptr;
849 register u_char *rptr;
850 register u_int i, mlen, frame_length;
851 char buf[2*MAX_DUMP_BYTES+4]; /* tmp buffer */
853 static char digits[] = "0123456789abcdef";
855 frame_length = i = msgdsize(mptr);
856 bsdlog(LOG_INFO, "ppp_async%d:%s frame of %d bytes\n", p - pai,
858 rptr = mptr->b_rptr; /* get pointer to beginning */
859 mlen = mptr->b_wptr - rptr; /* get length of this dblock */
861 /* only dump up to MAX_DUMP_BYTES */
862 if (i > ppp_async_max_dump_bytes)
863 i = ppp_async_max_dump_bytes;
865 while (i--) { /* convert to ascii hex */
866 while (mlen == 0) { /* get next dblock */
868 if (mptr) { /* are we done? */
869 rptr = mptr->b_rptr; /* nope, get next dblock */
870 mlen = mptr->b_wptr - rptr;
872 else { /* no more dblocks */
874 bsdlog(LOG_ERR, "ppp_async: ran out of data! (this shouldn't happen\n");
879 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
880 *bp++ = digits[*rptr++ & 0xf];
883 /* add a '>' to show that frame was truncated*/
884 if (ppp_async_max_dump_bytes < frame_length)
887 bsdlog(LOG_INFO,"ppp_async: %s\n", buf);
891 #endif /* NUM_PPP > 0 */