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.1 1995/12/18 23:45:07 paulus Exp $
12 * This file is used under SunOS 4.x, and OSF/1 on DEC Alpha.
14 * Beware that under OSF/1, the ioctl constants (SIOC*) end up
15 * as 64-bit (long) values, so an ioctl constant should be cast to
16 * int (32 bits) before being compared with the ioc_cmd field of
17 * an iocblk structure.
20 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/stream.h>
32 #include <sys/stropts.h>
34 #include <sys/signal.h>
37 #include <sys/socket.h>
39 #include <netinet/in.h>
43 #define NOTSUSER (suser(u.u_procp->p_rcred, &u.u_acflag))
45 #define NOTSUSER (!suser())
48 #include <net/ppp_defs.h>
49 #include <net/ppp_str.h>
51 /* how big of a buffer block to allocate for each chunk of the input chain */
55 #include <sys/syslog.h>
56 #define DLOG(s,a) if (p->pai_flags&PAI_FLAGS_DEBUG) log(LOG_DEBUG, s, a)
58 int ppp_async_max_dump_bytes = 28;
59 #define MAX_DUMP_BYTES 1504
61 static void ppp_dump_frame();
67 static int ppp_async_open(), ppp_async_close(), ppp_async_rput(),
68 ppp_async_wput(), ppp_async_wsrv(), ppp_async_rsrv();
70 static struct module_info minfo ={
71 0xabcd,"ppp_async",0, INFPSZ, 16384, 4096
74 static struct qinit r_init = {
75 ppp_async_rput, ppp_async_rsrv, ppp_async_open, ppp_async_close,
78 static struct qinit w_init = {
79 ppp_async_wput, ppp_async_wsrv, ppp_async_open, ppp_async_close,
82 struct streamtab ppp_asyncinfo = {
83 &r_init, &w_init, NULL, NULL,
87 * FCS lookup table as calculated by genfcstab.
89 static u_short fcstab[256] = {
90 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
91 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
92 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
93 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
94 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
95 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
96 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
97 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
98 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
99 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
100 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
101 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
102 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
103 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
104 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
105 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
106 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
107 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
108 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
109 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
110 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
111 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
112 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
113 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
114 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
115 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
116 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
117 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
118 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
119 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
120 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
121 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
125 struct ppp_async_info {
127 int pai_buffsize; /* how big of an input buffer to alloc */
128 int pai_buffcount; /* how many chars currently in input buffer */
129 u_short pai_fcs; /* the current fcs */
130 mblk_t *pai_buffer; /* pointer to the current buffer list */
131 mblk_t *pai_bufftail; /* pointer to the current input block */
132 ext_accm pai_asyncmap; /* current outgoing asyncmap */
133 u_int32_t pai_rasyncmap; /* current receive asyncmap */
136 /* Values for pai_flags */
137 #define PAI_FLAGS_INUSE 0x1
138 #define PAI_FLAGS_FLUSH 0x2
139 #define PAI_FLAGS_ESCAPED 0x4
140 #define PAI_FLAGS_COMPPROT 0x8
141 #define PAI_FLAGS_COMPAC 0x10
142 #define PAI_FLAGS_RCV_COMPPROT 0x20
143 #define PAI_FLAGS_RCV_COMPAC 0x40
145 #define PAI_FLAGS_DEBUG 0x1000
146 #define PAI_FLAGS_LOG_INPKT 0x2000
147 #define PAI_FLAGS_LOG_OUTPKT 0x4000
148 #define PAI_FLAGS_ALL_DEBUG 0x7000
150 typedef struct ppp_async_info PAI;
152 static PAI pai[NPPP*2]; /* our private cache of async ctrl structs */
154 /* open might fail if we don't have any more pai elements left free */
156 ppp_async_open(q, dev, flag, sflag)
166 /* only let the superuser or setuid root ppl open this module */
174 for (x=0; x < NPPP; x++) /* search for an empty PAI */
175 if (!(pai[x].pai_flags & PAI_FLAGS_INUSE))
177 if (x == NPPP) { /* all buffers in use */
178 splx(s); /* restore processor state */
183 DLOG("ppp_async%d: opening\n",x);
185 /* initialize the unit to default values */
186 WR(q)->q_ptr = q->q_ptr = (caddr_t) p;
187 bzero(p, sizeof(*p));
188 p->pai_flags = PAI_FLAGS_INUSE | PAI_FLAGS_RCV_COMPAC
189 | PAI_FLAGS_RCV_COMPPROT;
190 p->pai_asyncmap[0] = 0xffffffff; /* default async map */
191 p->pai_asyncmap[3] = 0x60000000; /* escape 7d, 7e */
192 p->pai_buffsize = PPP_MTU + PPP_HDRLEN + PPP_FCSLEN;
195 p = (PAI *) q->q_ptr;
196 DLOG("ppp_async%d: reopen\n", p - pai);
205 queue_t *q; /* queue info */
211 if ((p = (PAI *) q->q_ptr) != NULL) {
212 p->pai_flags = 0; /* clear all flags */
214 /* currently receiving some chars, discard the buffer */
215 freemsg(p->pai_buffer);
216 p->pai_buffer = NULL;
218 DLOG("ppp_async%d: closing\n", p - pai);
225 /* M_IOCTL processing is performed at this level. There is some
226 weirdness here, but I couldn't think of an easier way to handle it.
228 SIOC{G,S}IF{,R,X}ASYNCMAP are handled here.
230 SIOCSIFCOMPAC and SIOCSIFCOMPPROT are both handled here.
232 SIOCSIFMRU and SIOCGIFMRU (Max Receive Unit) are both handled here.
233 Rather than using the MTU to set the MRU, we have a seperate IOCTL for it.
237 ppp_async_wput(q, mp)
241 register struct iocblk *i;
245 switch (mp->b_datap->db_type) {
248 switch (*(u_char *)mp->b_rptr) {
250 /* trap this and remove it */
259 if (*mp->b_rptr & FLUSHW)
260 flushq(q, FLUSHDATA);
261 putnext(q, mp); /* send it along too */
265 putq(q, mp); /* queue it for my service routine */
269 i = (struct iocblk *) mp->b_rptr;
270 p = (PAI *) q->q_ptr;
271 switch (i->ioc_cmd) {
273 case SIOCSIFCOMPAC : /* enable or disable AC compression */
274 if (i->ioc_count != sizeof(u_char)) {
275 i->ioc_error = EINVAL;
278 x = *(u_char *) mp->b_cont->b_rptr;
279 DLOG("ppp_async: SIFCOMPAC %d\n", x);
280 flags = (x & 2)? PAI_FLAGS_RCV_COMPAC: PAI_FLAGS_COMPAC;
282 p->pai_flags |= flags;
284 p->pai_flags &= ~flags;
288 case SIOCSIFCOMPPROT: /* enable or disable PROT compression */
289 if (i->ioc_count != sizeof(u_char)) {
290 i->ioc_error = EINVAL;
293 x = *(u_char *) mp->b_cont->b_rptr;
294 DLOG("ppp_async: SIFCOMPPROT %d\n", x);
295 flags = (x & 2)? PAI_FLAGS_RCV_COMPPROT: PAI_FLAGS_COMPPROT;
297 p->pai_flags |= flags;
299 p->pai_flags &= ~flags;
305 if (i->ioc_count != sizeof(int)) {
306 i->ioc_error = EINVAL;
309 x = *(int *) mp->b_cont->b_rptr;
312 x += PPP_HDRLEN + PPP_FCSLEN;
313 if (x > 4096) { /* couldn't allocb something this big */
314 i->ioc_error = EINVAL;
322 if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
323 *(int *) mp->b_cont->b_wptr =
324 p->pai_buffsize - (PPP_HDRLEN + PPP_FCSLEN);
325 mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
328 i->ioc_error = ENOSR;
331 case SIOCGIFASYNCMAP :
332 if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
333 *(u_int32_t *) mp->b_cont->b_wptr = p->pai_asyncmap[0];
334 mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
337 i->ioc_error = ENOSR;
340 case SIOCSIFASYNCMAP :
341 if (i->ioc_count != sizeof(u_int32_t)) {
342 i->ioc_error = EINVAL;
343 goto iocnak; /* ugh, goto */
345 p->pai_asyncmap[0] = *(u_int32_t *) mp->b_cont->b_rptr;
346 DLOG("ppp_async: SIFASYNCMAP %lx\n", p->pai_asyncmap[0]);
350 case SIOCGIFRASYNCMAP :
351 if ((mp->b_cont = allocb(sizeof(u_int32_t), BPRI_MED)) != NULL) {
352 *(u_int32_t *) mp->b_cont->b_wptr = p->pai_rasyncmap;
353 mp->b_cont->b_wptr += i->ioc_count = sizeof(u_int32_t);
356 i->ioc_error = ENOSR;
359 case SIOCSIFRASYNCMAP :
360 if (i->ioc_count != sizeof(u_int32_t)) {
361 i->ioc_error = EINVAL;
362 goto iocnak; /* ugh, goto */
364 p->pai_rasyncmap = *(u_int32_t *) mp->b_cont->b_rptr;
365 DLOG("ppp_async: SIFRASYNCMAP %lx\n", p->pai_rasyncmap);
369 case SIOCGIFXASYNCMAP :
370 if ((mp->b_cont = allocb(sizeof(ext_accm), BPRI_MED)) != NULL) {
371 bcopy(p->pai_asyncmap, mp->b_cont->b_wptr, sizeof(ext_accm));
372 mp->b_cont->b_wptr += i->ioc_count = sizeof(ext_accm);
375 i->ioc_error = ENOSR;
378 case SIOCSIFXASYNCMAP :
379 if (i->ioc_count != sizeof(ext_accm)) {
380 i->ioc_error = EINVAL;
381 goto iocnak; /* ugh, goto */
383 bcopy(mp->b_cont->b_rptr, p->pai_asyncmap, sizeof(ext_accm));
384 p->pai_asyncmap[1] = 0; /* can't escape 20-3f */
385 p->pai_asyncmap[2] &= ~0x40000000; /* can't escape 5e */
386 p->pai_asyncmap[3] |= 0x60000000; /* must escape 7d, 7e */
391 if ((mp->b_cont = allocb(sizeof(int), BPRI_MED)) != NULL) {
392 *(int *)mp->b_cont->b_wptr =
393 (unsigned)(p->pai_flags & PAI_FLAGS_ALL_DEBUG)
395 (p->pai_flags & PAI_FLAGS_HIBITS);
396 mp->b_cont->b_wptr += i->ioc_count = sizeof(int);
399 i->ioc_error = ENOSR;
403 if(i->ioc_count != sizeof(int)) {
404 i->ioc_error = EINVAL;
405 goto iocnak; /* ugh, goto */
407 flags = *(int *)mp->b_cont->b_rptr;
408 DLOG("ppp_async: SIFIFDEBUG %x\n", flags);
409 p->pai_flags &= ~PAI_FLAGS_ALL_DEBUG | PAI_FLAGS_HIBITS;
410 p->pai_flags |= ((unsigned) flags * PAI_FLAGS_DEBUG)
411 & PAI_FLAGS_ALL_DEBUG;
416 mp->b_datap->db_type = M_IOCACK;
421 mp->b_datap->db_type = M_IOCNAK;
424 default: /* unknown IOCTL call */
425 putnext(q,mp); /* pass it along */
430 putnext(q, mp); /* don't know what to do with this, so send it along*/
438 register u_char *cp, *wp;
440 register u_short fcs;
441 register mblk_t *mp, *m0;
442 mblk_t *cop, *outgoing;
443 int proto, len, olen, c;
445 p = (PAI *) q->q_ptr;
447 while ((mp = getq(q)) != NULL) {
449 * we can only get M_DATA types into our Queue,
450 * due to our Put function
452 if (!canput(q->q_next)) {
457 /* at least a header required */
460 || (mp->b_wptr - mp->b_rptr < PPP_HDRLEN
461 && !pullupmsg(mp, PPP_HDRLEN))) {
462 freemsg(mp); /* discard the message */
463 DLOG("ppp_async: short message (%d)\n", len);
464 /* indicate output err */
465 putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
469 /* Do address/control and protocol compression */
470 proto = (mp->b_rptr[2] << 8) + mp->b_rptr[3];
471 if (p->pai_flags & PAI_FLAGS_COMPAC && proto != PPP_LCP
472 && mp->b_rptr[0] == PPP_ALLSTATIONS && mp->b_rptr[1] == PPP_UI) {
474 if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff)
476 } else if (p->pai_flags & PAI_FLAGS_COMPPROT && proto < 0xff) {
477 mp->b_rptr[2] = mp->b_rptr[1];
478 mp->b_rptr[1] = mp->b_rptr[0];
482 m0 = mp; /* remember first message block */
486 * Estimate the required buffer length as 1.25 * message length
487 * to allow for escaped characters. If this isn't enough, we
488 * allocate another buffer later.
490 olen = len + (len >> 2) + 5;
493 else if (olen > 2048)
495 outgoing = cop = allocb(olen, BPRI_MED);
496 if (outgoing == NULL) {
497 DLOG("allocb(%d) failed!\n", olen);
498 /* should do something tricky here */
503 /* Put the initial flag in (we'll take it out later if we don't
508 #define SPECIAL(p, c) (p->pai_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
511 * Copy the message to the output block, escaping characters
515 for (cp = mp->b_rptr; cp < mp->b_wptr; ) {
518 /* grab another message block and put it on the end */
521 cop = allocb(olen, BPRI_MED);
524 linkb(outgoing, cop);
529 *wp++ = c ^ PPP_TRANS;
535 fcs = PPP_FCS(fcs, c);
537 mp = mp->b_cont; /* look at the next block */
538 } /* end while(mp) */
541 * Add the FCS and the trailing flag.
544 /* grab another message block for FCS and trailing flag */
546 cop = allocb(5, BPRI_MED);
549 linkb(outgoing, cop);
552 fcs ^= 0xffff; /* XOR the resulting FCS */
556 *wp++ = c ^ PPP_TRANS;
562 *wp++ = c ^ PPP_TRANS;
565 *wp++ = PPP_FLAG; /* add trailing PPP_FLAG */
571 * now we check to see if the lower queue has entries, if so,
572 * we assume that we don't need a leading PPP_FLAG because
573 * these packets will be sent back to back.
575 if (qsize(q->q_next) > 0) {
576 /* entries in next queue, remove the leading PPP_FLAG */
581 if (p->pai_flags & PAI_FLAGS_LOG_OUTPKT)
582 ppp_dump_frame(p, outgoing, " sent output");
584 putnext(q, outgoing);
587 nobuffs: /* well, we ran out of memory somewhere */
589 freemsg(outgoing); /* throw away what we have already */
590 putbq(q, m0); /* put back the original message */
591 putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
592 qenable(q); /* reschedule ourselves for later */
594 } /* end while(getq()) */
598 ppp_async_rput(q, mp)
602 switch (mp->b_datap->db_type) {
605 if(*mp->b_rptr & FLUSHR)
606 flushq(q, FLUSHDATA);
607 putnext(q, mp); /* send it along too */
611 putq(q, mp); /* queue it for my service routine */
615 putnext(q,mp); /* don't know what to do with this, so send it along */
619 static u_int32_t paritytab[8] = {
620 0x96696996, 0x69969669, 0x69969669, 0x96696996,
621 0x69969669, 0x96696996, 0x96696996, 0x69969669,
628 register mblk_t *mp, *bp;
630 register u_char *cp,c;
632 register u_char *wptr;
635 p = (PAI *) q->q_ptr;
637 #define INPUT_ERROR(q) putctl1(q, M_CTL, IF_INPUT_ERROR)
638 #define STUFF_CHAR(p,c) (*wptr++ = (c), (p)->pai_buffcount++)
639 #define FLUSHEM(q, p) (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
641 while ((mp = getq(q)) != NULL) {
642 /* we can only get M_DATA types into our Queue,
643 due to our Put function */
644 if (!canput(q->q_next)) {
648 m0 = mp; /* remember first message block */
649 for (; mp != NULL; mp = mp->b_cont) { /* for each message block */
651 while (cp < mp->b_wptr) {
654 /* Accumulate info to help with detecting
655 non 8-bit clean links. */
657 p->pai_flags |= PAI_FLAGS_B7_1;
659 p->pai_flags |= PAI_FLAGS_B7_0;
660 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
661 p->pai_flags |= PAI_FLAGS_PAR_ODD;
663 p->pai_flags |= PAI_FLAGS_PAR_EVEN;
665 /* Throw out chars in the receive asyncmap. */
666 if (c < 0x20 && (p->pai_rasyncmap & (1 << c)))
669 /* A flag marks the end of a frame. */
672 bcount = p->pai_buffcount;
673 p->pai_buffer = NULL;
674 p->pai_buffcount = 0;
676 /* if the escape indicator is set, then we have
677 seen the packet abort sequence "}~". */
678 if (p->pai_flags & (PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH)) {
679 if ((p->pai_flags & PAI_FLAGS_FLUSH) == 0)
680 DLOG("ppp_async: packet abort\n", 0);
681 p->pai_flags &= ~(PAI_FLAGS_ESCAPED | PAI_FLAGS_FLUSH);
687 if (bcount > PPP_FCSLEN) { /* discard FCS */
688 adjmsg(bp, -PPP_FCSLEN);
689 bcount -= PPP_FCSLEN;
692 if (bcount < PPP_HDRLEN) {
695 DLOG("ppp_async: short input packet (%d)\n",
704 if (p->pai_fcs == PPP_GOODFCS) {
706 if (p->pai_flags & PAI_FLAGS_LOG_INPKT)
707 ppp_dump_frame(p, bp, " got input");
714 DLOG("ppp_async: FCS Error\n", 0);
720 /* here c != PPP_FLAG */
721 if (p->pai_flags & PAI_FLAGS_FLUSH) {
722 while (cp < mp->b_wptr && *cp != PPP_FLAG)
727 if (p->pai_flags & PAI_FLAGS_ESCAPED) {
728 p->pai_flags &= ~PAI_FLAGS_ESCAPED; /* clear esc flag */
730 } else if (c == PPP_ESCAPE) {
731 if (cp >= mp->b_wptr || (c = *cp) == PPP_FLAG
732 || c < 0x20 && (p->pai_rasyncmap & (1 << c))) {
733 p->pai_flags |= PAI_FLAGS_ESCAPED;
740 /* here we check to see if we have a buffer.
741 If we don't, we assume that this is the first char
742 for the buffer, and we allocb one */
744 if (!p->pai_buffer) {
745 /* we allocate buffer chains in blocks of ALLOCBSIZE */
747 if (!(p->pai_buffer = allocb(ALLOCBSIZE, BPRI_MED))) {
750 /* if we don't get a buffer, is there some way
751 to recover and requeue later? rather than flushing
752 the current packet... ? */
754 p->pai_bufftail = p->pai_buffer;
756 wptr = p->pai_bufftail->b_wptr;
758 if (!p->pai_buffcount) {
759 p->pai_fcs = PPP_INITFCS;
760 if (c != PPP_ALLSTATIONS) {
761 if (p->pai_flags & PAI_FLAGS_RCV_COMPAC) {
762 STUFF_CHAR(p, PPP_ALLSTATIONS);
763 STUFF_CHAR(p, PPP_UI);
766 DLOG("ppp_async: missed ALLSTATIONS (0xff), got 0x%x\n", c);
771 } /* end if !p->pai_buffcount */
773 if (p->pai_buffcount == 1 && c != PPP_UI) {
774 DLOG("ppp_async: missed UI (0x3), got 0x%x\n", c);
779 if (p->pai_buffcount == 2 && (c & 1) == 1) {
780 if (p->pai_flags & PAI_FLAGS_RCV_COMPPROT)
783 DLOG("ppp_async: bad protocol high byte %x\n", c);
789 if (p->pai_buffcount == 3 && (c & 1) == 0) {
790 DLOG("ppp_async: bad protocol low byte %x\n", c);
795 if (p->pai_buffcount >= p->pai_buffsize) { /* overrun */
796 DLOG("ppp_async: too many chars in input buffer %d\n",
802 /* determine if we have enough space in the buffer */
803 if (wptr >= p->pai_bufftail->b_datap->db_lim) {
804 p->pai_bufftail->b_wptr = wptr;
805 if (!(p->pai_bufftail = allocb(ALLOCBSIZE, BPRI_MED))) {
806 DLOG("ppp_async: couldn't get buffer for tail\n", 0);
807 FLUSHEM(q, p); /* discard all of it */
810 linkb(p->pai_buffer, p->pai_bufftail);
811 wptr = p->pai_bufftail->b_wptr;
815 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
817 if (p->pai_buffcount >= PPP_HDRLEN) {
818 while (cp < mp->b_wptr
819 && wptr < p->pai_bufftail->b_datap->db_lim
820 && (c = *cp) != PPP_FLAG && c != PPP_ESCAPE) {
821 if (c >= 0x20 || (p->pai_rasyncmap & (1 << c)) == 0) {
823 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
829 p->pai_bufftail->b_wptr = wptr;
831 } /* end while cp < wptr */
832 } /* end for each block */
833 /* discard this message now */
835 } /* end while getq */
841 * here is where we will dump out a frame in hex using the log()
842 * function if ppp_async_input_debug is non-zero. As this function is
843 * a pig, we only print up to the number of bytes specified by the value of
844 * the ppp_async_max_dump_bytes variable so as to not cause too many
845 * timeouts. <gmc@quotron.com>
849 ppp_dump_frame(p, mptr, msg)
851 register mblk_t *mptr;
854 register u_char *rptr;
855 register u_int i, mlen, frame_length;
856 char buf[2*MAX_DUMP_BYTES+4]; /* tmp buffer */
858 static char digits[] = "0123456789abcdef";
860 frame_length = i = msgdsize(mptr);
861 log(LOG_INFO, "ppp_async%d:%s frame of %d bytes\n", p - pai,
863 rptr = mptr->b_rptr; /* get pointer to beginning */
864 mlen = mptr->b_wptr - rptr; /* get length of this dblock */
866 /* only dump up to MAX_DUMP_BYTES */
867 if (i > ppp_async_max_dump_bytes)
868 i = ppp_async_max_dump_bytes;
870 while (i--) { /* convert to ascii hex */
871 while (mlen == 0) { /* get next dblock */
873 if (mptr) { /* are we done? */
874 rptr = mptr->b_rptr; /* nope, get next dblock */
875 mlen = mptr->b_wptr - rptr;
877 else { /* no more dblocks */
879 log(LOG_ERR, "ppp_async: ran out of data! (this shouldn't happen\n");
884 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
885 *bp++ = digits[*rptr++ & 0xf];
888 /* add a '>' to show that frame was truncated*/
889 if (ppp_async_max_dump_bytes < frame_length)
892 log(LOG_INFO,"ppp_async: %s\n", buf);
896 #endif /* NPPP > 0 */