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.3 1995/04/26 04:15:48 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 switch (*(u_char
*)mp
->b_rptr
) {
251 /* trap this and remove it */
260 if (*mp
->b_rptr
& FLUSHW
)
261 flushq(q
, FLUSHDATA
);
262 putnext(q
, mp
); /* send it along too */
266 putq(q
, mp
); /* queue it for my service routine */
270 i
= (struct iocblk
*) mp
->b_rptr
;
271 p
= (PAI
*) q
->q_ptr
;
272 switch ((unsigned int)i
->ioc_cmd
) {
274 case SIOCSIFCOMPAC
: /* enable or disable AC compression */
275 if (i
->ioc_count
!= TRANSPARENT
) {
276 i
->ioc_error
= EINVAL
;
279 x
= *(u_int
*) mp
->b_cont
->b_rptr
;
280 DLOG("ppp_async: SIFCOMPAC %d\n", x
);
281 flags
= (x
& 2)? PAI_FLAGS_RCV_COMPAC
: PAI_FLAGS_COMPAC
;
283 p
->pai_flags
|= flags
;
285 p
->pai_flags
&= ~flags
;
289 case SIOCSIFCOMPPROT
: /* enable or disable PROT compression */
290 if (i
->ioc_count
!= TRANSPARENT
) {
291 i
->ioc_error
= EINVAL
;
294 x
= *(u_int
*) mp
->b_cont
->b_rptr
;
295 DLOG("ppp_async: SIFCOMPPROT %d\n", x
);
296 flags
= (x
& 2)? PAI_FLAGS_RCV_COMPPROT
: PAI_FLAGS_COMPPROT
;
298 p
->pai_flags
|= flags
;
300 p
->pai_flags
&= ~flags
;
306 if ((i
->ioc_count
!= TRANSPARENT
) &&
307 (i
->ioc_count
!= sizeof(int))) {
308 i
->ioc_error
= EINVAL
;
311 x
= *(int *) mp
->b_cont
->b_rptr
;
314 x
+= PPP_HDRLEN
+ PPP_FCSLEN
;
315 if (x
> 4096) { /* couldn't allocb something this big */
316 i
->ioc_error
= EINVAL
;
324 if ((mp
->b_cont
= allocb(sizeof(int), BPRI_MED
)) != NULL
) {
325 *(int *) mp
->b_cont
->b_wptr
=
326 p
->pai_buffsize
- (PPP_HDRLEN
+ PPP_FCSLEN
);
327 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(int);
330 i
->ioc_error
= ENOSR
;
333 case SIOCGIFASYNCMAP
:
334 if ((mp
->b_cont
= allocb(sizeof(u_int32_t
), BPRI_MED
)) != NULL
) {
335 *(u_int32_t
*) mp
->b_cont
->b_wptr
= p
->pai_asyncmap
[0];
336 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(u_int32_t
);
339 i
->ioc_error
= ENOSR
;
342 case SIOCSIFASYNCMAP
:
343 if ((i
->ioc_count
!= TRANSPARENT
) &&
344 (i
->ioc_count
!= sizeof(u_int32_t
))) {
345 i
->ioc_error
= EINVAL
;
346 goto iocnak
; /* ugh, goto */
348 p
->pai_asyncmap
[0] = *(u_int32_t
*) mp
->b_cont
->b_rptr
;
349 DLOG("ppp_async: SIFASYNCMAP %lx\n", p
->pai_asyncmap
[0]);
353 case SIOCGIFRASYNCMAP
:
354 if ((mp
->b_cont
= allocb(sizeof(u_int32_t
), BPRI_MED
)) != NULL
) {
355 *(u_int32_t
*) mp
->b_cont
->b_wptr
= p
->pai_rasyncmap
;
356 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(u_int32_t
);
359 i
->ioc_error
= ENOSR
;
362 case SIOCSIFRASYNCMAP
:
363 if ((i
->ioc_count
!= TRANSPARENT
) &&
364 (i
->ioc_count
!= sizeof(u_int32_t
))) {
365 i
->ioc_error
= EINVAL
;
366 goto iocnak
; /* ugh, goto */
368 p
->pai_rasyncmap
= *(u_int32_t
*) mp
->b_cont
->b_rptr
;
369 DLOG("ppp_async: SIFRASYNCMAP %lx\n", p
->pai_rasyncmap
);
373 case SIOCGIFXASYNCMAP
:
374 if ((mp
->b_cont
= allocb(sizeof(ext_accm
), BPRI_MED
)) != NULL
) {
375 bcopy(p
->pai_asyncmap
, mp
->b_cont
->b_wptr
, sizeof(ext_accm
));
376 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(ext_accm
);
379 i
->ioc_error
= ENOSR
;
382 case SIOCSIFXASYNCMAP
:
383 if ((i
->ioc_count
!= TRANSPARENT
) &&
384 (i
->ioc_count
!= sizeof(ext_accm
))) {
385 i
->ioc_error
= EINVAL
;
386 goto iocnak
; /* ugh, goto */
388 bcopy(*mp
->b_cont
->b_rptr
, p
->pai_asyncmap
, sizeof(ext_accm
));
389 p
->pai_asyncmap
[1] = 0; /* can't escape 20-3f */
390 p
->pai_asyncmap
[2] &= ~0x40000000; /* can't escape 5e */
391 p
->pai_asyncmap
[3] |= 0x60000000; /* must escape 7d, 7e */
396 if ((mp
->b_cont
= allocb(sizeof(int), BPRI_MED
)) != NULL
) {
397 *(int *)mp
->b_cont
->b_wptr
=
398 (unsigned)(p
->pai_flags
& PAI_FLAGS_ALL_DEBUG
)
400 (p
->pai_flags
& PAI_FLAGS_HIBITS
);
401 mp
->b_cont
->b_wptr
+= i
->ioc_count
= sizeof(int);
404 i
->ioc_error
= ENOSR
;
408 if ((i
->ioc_count
!= TRANSPARENT
) &&
409 (i
->ioc_count
!= sizeof(int))) {
410 i
->ioc_error
= EINVAL
;
411 goto iocnak
; /* ugh, goto */
413 flags
= *(int *)mp
->b_cont
->b_rptr
;
414 DLOG("ppp_async: SIFIFDEBUG %x\n", flags
);
415 p
->pai_flags
&= ~PAI_FLAGS_ALL_DEBUG
| PAI_FLAGS_HIBITS
;
416 p
->pai_flags
|= ((unsigned) flags
* PAI_FLAGS_DEBUG
)
417 & PAI_FLAGS_ALL_DEBUG
;
422 mp
->b_datap
->db_type
= M_IOCACK
;
427 mp
->b_datap
->db_type
= M_IOCNAK
;
430 default: /* unknown IOCTL call */
431 putnext(q
,mp
); /* pass it along */
436 putnext(q
, mp
); /* don't know what to do with this, so send it along*/
444 register u_char
*cp
, *wp
;
446 register u_short fcs
;
447 register mblk_t
*mp
, *m0
;
448 mblk_t
*cop
, *outgoing
;
449 int proto
, len
, olen
, c
;
451 p
= (PAI
*) q
->q_ptr
;
453 while ((mp
= getq(q
)) != NULL
) {
455 * we can only get M_DATA types into our Queue,
456 * due to our Put function
458 if (!canput(q
->q_next
)) {
463 /* at least a header required */
466 || (mp
->b_wptr
- mp
->b_rptr
< PPP_HDRLEN
467 && !pullupmsg(mp
, PPP_HDRLEN
))) {
468 freemsg(mp
); /* discard the message */
469 DLOG("ppp_async: short message (%d)\n", len
);
470 /* indicate output err */
471 putctl1(OTHERQ(q
), M_CTL
, IF_OUTPUT_ERROR
);
475 /* Do address/control and protocol compression */
476 proto
= (mp
->b_rptr
[2] << 8) + mp
->b_rptr
[3];
477 if (p
->pai_flags
& PAI_FLAGS_COMPAC
&& proto
!= PPP_LCP
478 && mp
->b_rptr
[0] == PPP_ALLSTATIONS
&& mp
->b_rptr
[1] == PPP_UI
) {
480 if (p
->pai_flags
& PAI_FLAGS_COMPPROT
&& proto
< 0xff)
482 } else if (p
->pai_flags
& PAI_FLAGS_COMPPROT
&& proto
< 0xff) {
483 mp
->b_rptr
[2] = mp
->b_rptr
[1];
484 mp
->b_rptr
[1] = mp
->b_rptr
[0];
488 m0
= mp
; /* remember first message block */
492 * Estimate the required buffer length as 1.25 * message length
493 * to allow for escaped characters. If this isn't enough, we
494 * allocate another buffer later.
496 olen
= len
+ (len
>> 2) + 5;
499 else if (olen
> 2048)
501 outgoing
= cop
= allocb(olen
, BPRI_MED
);
502 if (outgoing
== NULL
) {
503 DLOG("allocb(%d) failed!\n", olen
);
504 /* should do something tricky here */
509 /* Put the initial flag in (we'll take it out later if we don't
514 #define SPECIAL(p, c) (p->pai_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
517 * Copy the message to the output block, escaping characters
521 for (cp
= mp
->b_rptr
; cp
< mp
->b_wptr
; ) {
524 /* grab another message block and put it on the end */
527 cop
= allocb(olen
, BPRI_MED
);
530 linkb(outgoing
, cop
);
535 *wp
++ = c
^ PPP_TRANS
;
541 fcs
= PPP_FCS(fcs
, c
);
543 mp
= mp
->b_cont
; /* look at the next block */
544 } /* end while(mp) */
547 * Add the FCS and the trailing flag.
550 /* grab another message block for FCS and trailing flag */
552 cop
= allocb(5, BPRI_MED
);
555 linkb(outgoing
, cop
);
558 fcs
^= 0xffff; /* XOR the resulting FCS */
562 *wp
++ = c
^ PPP_TRANS
;
568 *wp
++ = c
^ PPP_TRANS
;
571 *wp
++ = PPP_FLAG
; /* add trailing PPP_FLAG */
577 * now we check to see if the lower queue has entries, if so,
578 * we assume that we don't need a leading PPP_FLAG because
579 * these packets will be sent back to back.
581 if (qsize(q
->q_next
) > 0) {
582 /* entries in next queue, remove the leading PPP_FLAG */
587 if (p
->pai_flags
& PAI_FLAGS_LOG_OUTPKT
)
588 ppp_dump_frame(p
, outgoing
, " sent output");
590 putnext(q
, outgoing
);
593 nobuffs
: /* well, we ran out of memory somewhere */
595 freemsg(outgoing
); /* throw away what we have already */
596 putbq(q
, m0
); /* put back the original message */
597 putctl1(OTHERQ(q
), M_CTL
, IF_OUTPUT_ERROR
);
598 qenable(q
); /* reschedule ourselves for later */
600 } /* end while(getq()) */
604 ppp_async_rput(q
, mp
)
608 switch (mp
->b_datap
->db_type
) {
611 if(*mp
->b_rptr
& FLUSHR
)
612 flushq(q
, FLUSHDATA
);
613 putnext(q
, mp
); /* send it along too */
617 putq(q
, mp
); /* queue it for my service routine */
621 putnext(q
,mp
); /* don't know what to do with this, so send it along */
625 static u_int32_t paritytab
[8] = {
626 0x96696996, 0x69969669, 0x69969669, 0x96696996,
627 0x69969669, 0x96696996, 0x96696996, 0x69969669,
634 register mblk_t
*mp
, *bp
;
636 register u_char
*cp
,c
;
638 register u_char
*wptr
;
641 p
= (PAI
*) q
->q_ptr
;
643 #define INPUT_ERROR(q) putctl1(q, M_CTL, IF_INPUT_ERROR)
644 #define STUFF_CHAR(p,c) (*wptr++ = (c), (p)->pai_buffcount++)
645 #define FLUSHEM(q, p) (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
647 while ((mp
= getq(q
)) != NULL
) {
648 /* we can only get M_DATA types into our Queue,
649 due to our Put function */
650 if (!canput(q
->q_next
)) {
654 m0
= mp
; /* remember first message block */
655 for (; mp
!= NULL
; mp
= mp
->b_cont
) { /* for each message block */
657 while (cp
< mp
->b_wptr
) {
660 /* Accumulate info to help with detecting
661 non 8-bit clean links. */
663 p
->pai_flags
|= PAI_FLAGS_B7_1
;
665 p
->pai_flags
|= PAI_FLAGS_B7_0
;
666 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
667 p
->pai_flags
|= PAI_FLAGS_PAR_ODD
;
669 p
->pai_flags
|= PAI_FLAGS_PAR_EVEN
;
671 /* Throw out chars in the receive asyncmap. */
672 if (c
< 0x20 && (p
->pai_rasyncmap
& (1 << c
)))
675 /* A flag marks the end of a frame. */
678 bcount
= p
->pai_buffcount
;
679 p
->pai_buffer
= NULL
;
680 p
->pai_buffcount
= 0;
682 /* if the escape indicator is set, then we have
683 seen the packet abort sequence "}~". */
684 if (p
->pai_flags
& (PAI_FLAGS_ESCAPED
| PAI_FLAGS_FLUSH
)) {
685 if ((p
->pai_flags
& PAI_FLAGS_FLUSH
) == 0)
686 DLOG("ppp_async: packet abort\n", 0);
687 p
->pai_flags
&= ~(PAI_FLAGS_ESCAPED
| PAI_FLAGS_FLUSH
);
693 if (bcount
> PPP_FCSLEN
) { /* discard FCS */
694 adjmsg(bp
, -PPP_FCSLEN
);
695 bcount
-= PPP_FCSLEN
;
698 if (bcount
< PPP_HDRLEN
) {
701 DLOG("ppp_async: short input packet (%d)\n",
710 if (p
->pai_fcs
== PPP_GOODFCS
) {
712 if (p
->pai_flags
& PAI_FLAGS_LOG_INPKT
)
713 ppp_dump_frame(p
, bp
, " got input");
720 DLOG("ppp_async: FCS Error\n", 0);
726 /* here c != PPP_FLAG */
727 if (p
->pai_flags
& PAI_FLAGS_FLUSH
) {
728 while (cp
< mp
->b_wptr
&& *cp
!= PPP_FLAG
)
733 if (p
->pai_flags
& PAI_FLAGS_ESCAPED
) {
734 p
->pai_flags
&= ~PAI_FLAGS_ESCAPED
; /* clear esc flag */
736 } else if (c
== PPP_ESCAPE
) {
737 if (cp
>= mp
->b_wptr
|| (c
= *cp
) == PPP_FLAG
738 || c
< 0x20 && (p
->pai_rasyncmap
& (1 << c
))) {
739 p
->pai_flags
|= PAI_FLAGS_ESCAPED
;
746 /* here we check to see if we have a buffer.
747 If we don't, we assume that this is the first char
748 for the buffer, and we allocb one */
750 if (!p
->pai_buffer
) {
751 /* we allocate buffer chains in blocks of ALLOCBSIZE */
753 if (!(p
->pai_buffer
= allocb(ALLOCBSIZE
, BPRI_MED
))) {
756 /* if we don't get a buffer, is there some way
757 to recover and requeue later? rather than flushing
758 the current packet... ? */
760 p
->pai_bufftail
= p
->pai_buffer
;
762 wptr
= p
->pai_bufftail
->b_wptr
;
764 if (!p
->pai_buffcount
) {
765 p
->pai_fcs
= PPP_INITFCS
;
766 if (c
!= PPP_ALLSTATIONS
) {
767 if (p
->pai_flags
& PAI_FLAGS_RCV_COMPAC
) {
768 STUFF_CHAR(p
, PPP_ALLSTATIONS
);
769 STUFF_CHAR(p
, PPP_UI
);
772 DLOG("ppp_async: missed ALLSTATIONS (0xff), got 0x%x\n", c
);
777 } /* end if !p->pai_buffcount */
779 if (p
->pai_buffcount
== 1 && c
!= PPP_UI
) {
780 DLOG("ppp_async: missed UI (0x3), got 0x%x\n", c
);
785 if (p
->pai_buffcount
== 2 && (c
& 1) == 1) {
786 if (p
->pai_flags
& PAI_FLAGS_RCV_COMPPROT
)
789 DLOG("ppp_async: bad protocol high byte %x\n", c
);
795 if (p
->pai_buffcount
== 3 && (c
& 1) == 0) {
796 DLOG("ppp_async: bad protocol low byte %x\n", c
);
801 if (p
->pai_buffcount
>= p
->pai_buffsize
) { /* overrun */
802 DLOG("ppp_async: too many chars in input buffer %d\n",
808 /* determine if we have enough space in the buffer */
809 if (wptr
>= p
->pai_bufftail
->b_datap
->db_lim
) {
810 p
->pai_bufftail
->b_wptr
= wptr
;
811 if (!(p
->pai_bufftail
= allocb(ALLOCBSIZE
, BPRI_MED
))) {
812 DLOG("ppp_async: couldn't get buffer for tail\n", 0);
813 FLUSHEM(q
, p
); /* discard all of it */
816 linkb(p
->pai_buffer
, p
->pai_bufftail
);
817 wptr
= p
->pai_bufftail
->b_wptr
;
821 p
->pai_fcs
= PPP_FCS(p
->pai_fcs
, c
);
823 if (p
->pai_buffcount
>= PPP_HDRLEN
) {
824 while (cp
< mp
->b_wptr
825 && wptr
< p
->pai_bufftail
->b_datap
->db_lim
826 && (c
= *cp
) != PPP_FLAG
&& c
!= PPP_ESCAPE
) {
827 if (c
>= 0x20 || (p
->pai_rasyncmap
& (1 << c
)) == 0) {
829 p
->pai_fcs
= PPP_FCS(p
->pai_fcs
, c
);
835 p
->pai_bufftail
->b_wptr
= wptr
;
837 } /* end while cp < wptr */
838 } /* end for each block */
839 /* discard this message now */
841 } /* end while getq */
847 * here is where we will dump out a frame in hex using the log()
848 * function if ppp_async_input_debug is non-zero. As this function is
849 * a pig, we only print up to the number of bytes specified by the value of
850 * the ppp_async_max_dump_bytes variable so as to not cause too many
851 * timeouts. <gmc@quotron.com>
855 ppp_dump_frame(p
, mptr
, msg
)
857 register mblk_t
*mptr
;
860 register u_char
*rptr
;
861 register u_int i
, mlen
, frame_length
;
862 char buf
[2*MAX_DUMP_BYTES
+4]; /* tmp buffer */
864 static char digits
[] = "0123456789abcdef";
866 frame_length
= i
= msgdsize(mptr
);
867 bsdlog(LOG_INFO
, "ppp_async%d:%s frame of %d bytes\n", p
- pai
,
869 rptr
= mptr
->b_rptr
; /* get pointer to beginning */
870 mlen
= mptr
->b_wptr
- rptr
; /* get length of this dblock */
872 /* only dump up to MAX_DUMP_BYTES */
873 if (i
> ppp_async_max_dump_bytes
)
874 i
= ppp_async_max_dump_bytes
;
876 while (i
--) { /* convert to ascii hex */
877 while (mlen
== 0) { /* get next dblock */
879 if (mptr
) { /* are we done? */
880 rptr
= mptr
->b_rptr
; /* nope, get next dblock */
881 mlen
= mptr
->b_wptr
- rptr
;
883 else { /* no more dblocks */
885 bsdlog(LOG_ERR
, "ppp_async: ran out of data! (this shouldn't happen\n");
890 *bp
++ = digits
[*rptr
>> 4]; /* convert byte to ascii hex */
891 *bp
++ = digits
[*rptr
++ & 0xf];
894 /* add a '>' to show that frame was truncated*/
895 if (ppp_async_max_dump_bytes
< frame_length
)
898 bsdlog(LOG_INFO
,"ppp_async: %s\n", buf
);
902 #endif /* NUM_PPP > 0 */