7eb54ec7cc182ddb70ac97d2ca4a620ce3bb2dd9
[ppp.git] / svr4 / ppp_comp.c
1 /*
2  * ppp_comp.c - STREAMS module for kernel-level compression and CCP support.
3  *
4  * Copyright (c) 1994 The Australian National University.
5  * All rights reserved.
6  *
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.
13  *
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 HAVE BEEN ADVISED OF THE POSSIBILITY
18  * OF SUCH DAMAGE.
19  *
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.
26  *
27  * $Id: ppp_comp.c,v 1.2 1995/05/19 02:18:11 paulus Exp $
28  */
29
30 /*
31  * This file is used under Solaris 2.
32  */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/errno.h>
37 #include <sys/stream.h>
38 #include <sys/modctl.h>
39 #include <sys/conf.h>
40 #include <sys/kmem.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/cmn_err.h>
44 #include <net/ppp_defs.h>
45 #include <net/pppio.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <net/vjcompress.h>
50
51 #define ALLOCATE(n)     kmem_alloc((n), KM_NOSLEEP)
52 #define FREE(p, n)      kmem_free((p), (n))
53
54 #define PACKETPTR       mblk_t *
55 #include <net/ppp-comp.h>
56
57 static int ppp_comp_open __P((queue_t *, dev_t *, int, int, cred_t *));
58 static int ppp_comp_close __P((queue_t *, int, cred_t *));
59 static int ppp_comp_rput __P((queue_t *, mblk_t *));
60 static int ppp_comp_rsrv __P((queue_t *));
61 static int ppp_comp_wput __P((queue_t *, mblk_t *));
62 static int ppp_comp_wsrv __P((queue_t *));
63 static void ppp_comp_ccp __P((queue_t *, mblk_t *, int));
64
65 static struct module_info minfo = {
66     0xbadf, "ppp_comp", 0, INFPSZ, 16384, 4096,
67 };
68
69 static struct qinit r_init = {
70     ppp_comp_rput, ppp_comp_rsrv, ppp_comp_open, ppp_comp_close,
71     NULL, &minfo, NULL
72 };
73
74 static struct qinit w_init = {
75     ppp_comp_wput, ppp_comp_wsrv, NULL, NULL, NULL, &minfo, NULL
76 };
77
78 static struct streamtab ppp_compinfo = {
79     &r_init, &w_init, NULL, NULL
80 };
81
82 static struct fmodsw fsw = {
83     "ppp_comp",
84     &ppp_compinfo,
85     D_NEW | D_MP | D_MTQPAIR
86 };
87
88 extern struct mod_ops mod_strmodops;
89
90 static struct modlstrmod modlstrmod = {
91     &mod_strmodops,
92     "PPP compression module",
93     &fsw
94 };
95
96 static struct modlinkage modlinkage = {
97     MODREV_1,
98     (void *) &modlstrmod,
99     NULL
100 };
101
102 struct ppp_comp_state {
103     int         flags;
104     int         mru;
105     int         mtu;
106     int         unit;
107     int         ierrors;
108     struct compressor *xcomp;
109     void        *xstate;
110     struct compressor *rcomp;
111     void        *rstate;
112     struct vjcompress vj_comp;
113     int         vj_last_ierrors;
114 };
115
116 /* Bits in flags are as defined in pppio.h. */
117 #define CCP_ERR         (CCP_ERROR | CCP_FATALERROR)
118
119 #define MAX_IPHDR       128     /* max TCP/IP header size */
120 #define MAX_VJHDR       20      /* max VJ compressed header size (?) */
121
122 /*
123  * List of compressors we know about.
124  */
125
126 extern struct compressor ppp_bsd_compress;
127
128 struct compressor *ppp_compressors[] = {
129 #if DO_BSD_COMPRESS
130     &ppp_bsd_compress,
131 #endif
132     NULL
133 };
134
135 /*
136  * Entry points for modloading.
137  */
138 int
139 _init(void)
140 {
141     return mod_install(&modlinkage);
142 }
143
144 int
145 _fini(void)
146 {
147     return mod_remove(&modlinkage);
148 }
149
150 int
151 _info(mip)
152     struct modinfo *mip;
153 {
154     return mod_info(&modlinkage, mip);
155 }
156
157 /*
158  * STREAMS module entry points.
159  */
160 static int
161 ppp_comp_open(q, devp, flag, sflag, credp)
162     queue_t *q;
163     dev_t *devp;
164     int flag, sflag;
165     cred_t *credp;
166 {
167     struct ppp_comp_state *cp;
168
169     if (q->q_ptr == NULL) {
170         cp = (struct ppp_comp_state *) ALLOCATE(sizeof(struct ppp_comp_state));
171         if (cp == NULL)
172             return ENOSR;
173         WR(q)->q_ptr = q->q_ptr = cp;
174         bzero((caddr_t)cp, sizeof(struct ppp_comp_state));
175         cp->mru = PPP_MRU;
176         cp->mtu = PPP_MRU;
177         cp->xstate = NULL;
178         cp->rstate = NULL;
179         vj_compress_init(&cp->vj_comp, -1);
180         qprocson(q);
181     }
182     return 0;
183 }
184
185 static int
186 ppp_comp_close(q, flag, credp)
187     queue_t *q;
188     int flag;
189     cred_t *credp;
190 {
191     struct ppp_comp_state *cp;
192
193     qprocsoff(q);
194     cp = (struct ppp_comp_state *) q->q_ptr;
195     if (cp != NULL) {
196         if (cp->xstate != NULL)
197             (*cp->xcomp->comp_free)(cp->xstate);
198         if (cp->rstate != NULL)
199             (*cp->rcomp->decomp_free)(cp->rstate);
200         FREE(cp, sizeof(struct ppp_comp_state));
201         q->q_ptr = NULL;
202         OTHERQ(q)->q_ptr = NULL;
203     }
204     return 0;
205 }
206
207 static int
208 ppp_comp_wput(q, mp)
209     queue_t *q;
210     mblk_t *mp;
211 {
212     struct iocblk *iop;
213     struct ppp_comp_state *cp;
214     int error, len;
215     int flags, mask;
216     struct compressor **comp;
217     struct ppp_comp_stats *pcp;
218     unsigned char *opt_data;
219     int nxslots, nrslots;
220
221     cp = (struct ppp_comp_state *) q->q_ptr;
222     switch (mp->b_datap->db_type) {
223
224     case M_DATA:
225         putq(q, mp);
226         break;
227
228     case M_IOCTL:
229         iop = (struct iocblk *) mp->b_rptr;
230         error = EINVAL;
231         switch (iop->ioc_cmd) {
232
233         case PPPIO_CFLAGS:
234             /* set/get CCP state */
235             if (iop->ioc_count != 2 * sizeof(int))
236                 break;
237             flags = ((int *) mp->b_cont->b_rptr)[0];
238             mask = ((int *) mp->b_cont->b_rptr)[1];
239             cp->flags = (cp->flags & ~mask) | (flags & mask);
240             if ((mask & CCP_ISOPEN) && (flags & CCP_ISOPEN) == 0) {
241                 if (cp->xstate != NULL) {
242                     (*cp->xcomp->comp_free)(cp->xstate);
243                     cp->xstate = NULL;
244                 }
245                 if (cp->rstate != NULL) {
246                     (*cp->rcomp->decomp_free)(cp->rstate);
247                     cp->rstate = NULL;
248                 }
249                 cp->flags &= ~CCP_ISUP;
250             }
251             error = 0;
252             iop->ioc_count = sizeof(int);
253             ((int *) mp->b_cont->b_rptr)[0] = cp->flags;
254             mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
255             break;
256
257         case PPPIO_VJINIT:
258             /*
259              * Initialize VJ compressor/decompressor
260              */
261             if (iop->ioc_count != 2)
262                 break;
263             nxslots = mp->b_cont->b_rptr[0] + 1;
264             nrslots = mp->b_cont->b_rptr[1] + 1;
265             if (nxslots > MAX_STATES || nrslots > MAX_STATES)
266                 break;
267             vj_compress_init(&cp->vj_comp, nxslots);
268             cp->vj_last_ierrors = cp->ierrors;
269             error = 0;
270             iop->ioc_count = 0;
271             break;
272
273         case PPPIO_XCOMP:
274         case PPPIO_RCOMP:
275             if (iop->ioc_count <= 0)
276                 break;
277             opt_data = mp->b_cont->b_rptr;
278             len = mp->b_cont->b_wptr - opt_data;
279             if (len > iop->ioc_count)
280                 len = iop->ioc_count;
281             if (opt_data[1] < 2 || opt_data[1] > len)
282                 break;
283             for (comp = ppp_compressors; *comp != NULL; ++comp)
284                 if ((*comp)->compress_proto == opt_data[0]) {
285                     /* here's the handler! */
286                     error = 0;
287                     if (iop->ioc_cmd == PPPIO_XCOMP) {
288                         if (cp->xstate != NULL)
289                             (*cp->xcomp->comp_free)(cp->xstate);
290                         cp->xcomp = *comp;
291                         cp->xstate = (*comp)->comp_alloc(opt_data, len);
292                         if (cp->xstate == NULL)
293                             error = ENOSR;
294                     } else {
295                         if (cp->rstate != NULL)
296                             (*cp->rcomp->decomp_free)(cp->rstate);
297                         cp->rcomp = *comp;
298                         cp->rstate = (*comp)->decomp_alloc(opt_data, len);
299                         if (cp->rstate == NULL)
300                             error = ENOSR;
301                     }
302                     break;
303                 }
304             iop->ioc_count = 0;
305             break;
306
307         case PPPIO_MRU:
308             /* remember this value */
309             if (iop->ioc_count == sizeof(int)) {
310                 cp->mru = *(int *) mp->b_cont->b_rptr;
311             }
312             error = -1;
313             break;
314
315         default:
316             error = -1;
317             break;
318         }
319
320         if (error < 0)
321             putnext(q, mp);
322         else if (error == 0) {
323             mp->b_datap->db_type = M_IOCACK;
324             qreply(q, mp);
325         } else {
326             mp->b_datap->db_type = M_IOCNAK;
327             iop->ioc_error = error;
328             iop->ioc_count = 0;
329             qreply(q, mp);
330         }
331         break;
332
333     case M_CTL:
334         switch (*mp->b_rptr) {
335         case PPPCTL_MTU:
336             cp->mtu = ((unsigned short *)mp->b_rptr)[1];
337             break;
338         case PPPCTL_MRU:
339             cp->mru = ((unsigned short *)mp->b_rptr)[1];
340             break;
341         case PPPCTL_UNIT:
342             cp->unit = mp->b_rptr[1];
343             break;
344         }
345         putnext(q, mp);
346         break;
347
348     default:
349         putnext(q, mp);
350     }
351 }
352
353 static int
354 ppp_comp_wsrv(q)
355     queue_t *q;
356 {
357     mblk_t *mp, *cmp;
358     struct ppp_comp_state *cp;
359     int len, proto, type;
360     struct ip *ip;
361     unsigned char *vjhdr, *dp;
362
363     cp = (struct ppp_comp_state *) q->q_ptr;
364     while ((mp = getq(q)) != 0) {
365         /* assert(mp->b_datap->db_type == M_DATA) */
366         if (!canputnext(q)) {
367             putbq(q, mp);
368             return;
369         }
370
371         /* first find out what the protocol is */
372         if (mp->b_wptr - mp->b_rptr < PPP_HDRLEN
373             && !pullupmsg(mp, PPP_HDRLEN)) {
374             freemsg(mp);        /* give up on it */
375             continue;
376         }
377         proto = PPP_PROTOCOL(mp->b_rptr);
378
379         /*
380          * Do VJ compression if requested.
381          */
382         if (proto == PPP_IP && (cp->flags & COMP_VJC)) {
383             len = msgdsize(mp);
384             if (len > MAX_IPHDR + PPP_HDRLEN)
385                 len = MAX_IPHDR + PPP_HDRLEN;
386             if (mp->b_wptr - mp->b_rptr >= len || pullupmsg(mp, len)) {
387                 ip = (struct ip *) (mp->b_rptr + PPP_HDRLEN);
388                 if (ip->ip_p == IPPROTO_TCP) {
389                     type = vj_compress_tcp(ip, len - PPP_HDRLEN,
390                                 &cp->vj_comp, (cp->flags & COMP_VJCCID),
391                                 &vjhdr);
392                     switch (type) {
393                     case TYPE_UNCOMPRESSED_TCP:
394                         mp->b_rptr[3] = proto = PPP_VJC_UNCOMP;
395                         break;
396                     case TYPE_COMPRESSED_TCP:
397                         dp = vjhdr - PPP_HDRLEN;
398                         dp[1] = mp->b_rptr[1]; /* copy control field */
399                         dp[0] = mp->b_rptr[0]; /* copy address field */
400                         dp[2] = 0;                 /* set protocol field */
401                         dp[3] = proto = PPP_VJC_COMP;
402                         mp->b_rptr = dp;
403                         break;
404                     }
405                 }
406             }
407         }
408
409         /*
410          * Do packet compression if enabled.
411          */
412         if (proto == PPP_CCP)
413             ppp_comp_ccp(q, mp, 0);
414         else if (proto != PPP_LCP && (cp->flags & CCP_COMP_RUN)
415                  && cp->xstate != NULL) {
416             len = msgdsize(mp);
417             (*cp->xcomp->compress)(cp->xstate, &cmp, mp, len,
418                                    (cp->flags & CCP_ISUP? cp->mtu: 0));
419             if (cmp != NULL) {
420                 freemsg(mp);
421                 mp = cmp;
422             }
423         }
424
425         /*
426          * Do address/control and protocol compression if enabled.
427          */
428         if (proto != PPP_LCP && (cp->flags & COMP_AC)) {
429             mp->b_rptr += 2;    /* drop the address & ctrl fields */
430             if (proto < 0x100 && (cp->flags & COMP_PROT))
431                 ++mp->b_rptr;   /* drop the high protocol byte */
432         } else if (proto < 0x100 && (cp->flags & COMP_PROT)) {
433             /* shuffle up the address & ctrl fields */
434             mp->b_rptr[2] = mp->b_rptr[1];
435             mp->b_rptr[1] = mp->b_rptr[0];
436             ++mp->b_rptr;
437         }
438
439         putnext(q, mp);
440     }
441 }
442
443 static int
444 ppp_comp_rput(q, mp)
445     queue_t *q;
446     mblk_t *mp;
447 {
448     struct ppp_comp_state *cp;
449
450     cp = (struct ppp_comp_state *) q->q_ptr;
451     switch (mp->b_datap->db_type) {
452
453     case M_DATA:
454         putq(q, mp);
455         break;
456
457     case M_CTL:
458         switch (mp->b_rptr[0]) {
459         case PPPCTL_IERROR:
460             ++cp->ierrors;
461             break;
462         }
463         putnext(q, mp);
464         break;
465
466     default:
467         putnext(q, mp);
468     }
469 }
470
471 static int
472 ppp_comp_rsrv(q)
473     queue_t *q;
474 {
475     int proto, rv;
476     mblk_t *mp, *dmp, *np;
477     unsigned char *dp, *iphdr;
478     struct ppp_comp_state *cp;
479     int len, hlen, vjlen, iphlen;
480     int oldierrors;
481
482     cp = (struct ppp_comp_state *) q->q_ptr;
483     oldierrors = cp->ierrors;
484     while ((mp = getq(q)) != 0) {
485         /* assert(mp->b_datap->db_type == M_DATA) */
486         if (!canputnext(q)) {
487             putbq(q, mp);
488             return;
489         }
490
491         /*
492          * First do address/control and protocol "decompression".
493          */
494         len = msgdsize(mp);
495         if (len > PPP_HDRLEN)
496             len = PPP_HDRLEN;
497         if (mp->b_wptr - mp->b_rptr < len && !pullupmsg(mp, len)) {
498             ++cp->ierrors;
499             freemsg(mp);
500             continue;
501         }
502         dp = mp->b_rptr;
503         if (PPP_ADDRESS(dp) == PPP_ALLSTATIONS && PPP_CONTROL(dp) == PPP_UI)
504             dp += 2;                    /* skip address/control */
505         proto = 0;
506         if ((dp[0] & 1) == 0)
507             proto = *dp++ << 8;         /* grab high byte of protocol */
508         proto += *dp++;                 /* grab low byte of protocol */
509         if (dp > mp->b_wptr) {
510             ++cp->ierrors;              /* short/bogus packet */
511             freemsg(mp);
512             continue;
513         }
514         if ((dp -= PPP_HDRLEN) < mp->b_datap->db_base) {
515             /* yucko, need a new message block */
516             mp->b_rptr = dp;
517             np = allocb(PPP_HDRLEN, BPRI_MED);
518             if (np == 0) {
519                 ++cp->ierrors;
520                 freemsg(mp);
521                 continue;
522             }
523             linkb(np, mp);
524             mp = np;
525             dp = mp->b_rptr;
526             mp->b_wptr = dp + PPP_HDRLEN;
527         } else
528             mp->b_rptr = dp;
529         dp[0] = PPP_ALLSTATIONS;
530         dp[1] = PPP_UI;
531         dp[2] = proto >> 8;
532         dp[3] = proto;
533
534         /*
535          * Now see if we have a compressed packet to decompress,
536          * or a CCP packet to take notice of.
537          */
538         proto = PPP_PROTOCOL(mp->b_rptr);
539         if (proto == PPP_CCP)
540             ppp_comp_ccp(q, mp, 1);
541         else if (proto == PPP_COMP) {
542             if ((cp->flags & CCP_ISUP)
543                 && (cp->flags & CCP_DECOMP_RUN) && cp->rstate
544                 && (cp->flags & CCP_ERR) == 0) {
545                 rv = (*cp->rcomp->decompress)(cp->rstate, mp, &dmp);
546                 if (dmp != NULL) {
547                     freemsg(mp);
548                     mp = dmp;
549                 } else {
550                     switch (rv) {
551                     case DECOMP_OK:
552                         /* no error, but no packet returned */
553                         freemsg(mp);
554                         continue;
555                     case DECOMP_ERROR:
556                         cp->flags |= CCP_ERROR;
557                         ++cp->ierrors;
558                         break;
559                     case DECOMP_FATALERROR:
560                         cp->flags |= CCP_FATALERROR;
561                         ++cp->ierrors;
562                         break;
563                     }
564                 }
565             }
566         } else if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
567             (*cp->rcomp->incomp)(cp->rstate, mp);
568         }
569
570         /*
571          * Now do VJ decompression.
572          */
573         proto = PPP_PROTOCOL(mp->b_rptr);
574         if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
575             if ((cp->flags & DECOMP_VJC) == 0) {
576                 ++cp->ierrors;  /* ? */
577                 freemsg(mp);
578                 continue;
579             }
580             if (cp->ierrors != cp->vj_last_ierrors) {
581                 vj_uncompress_err(&cp->vj_comp);
582                 cp->vj_last_ierrors = cp->ierrors;
583             }
584             len = msgdsize(mp);
585             hlen = (proto == PPP_VJC_COMP? MAX_VJHDR: MAX_IPHDR) + PPP_HDRLEN;
586             if (hlen > len)
587                 hlen = len;
588             if (mp->b_wptr - mp->b_rptr < hlen && !pullupmsg(mp, hlen)) {
589                 ++cp->ierrors;
590                 freemsg(mp);
591                 continue;
592             }
593
594             if (proto == PPP_VJC_COMP) {
595                 mp->b_rptr += PPP_HDRLEN;
596                 vjlen = vj_uncompress_tcp(mp->b_rptr, mp->b_wptr - mp->b_rptr,
597                                           len - PPP_HDRLEN, &cp->vj_comp,
598                                           &iphdr, &iphlen);
599                 if (vjlen < 0
600                     || (np = allocb(iphlen + PPP_HDRLEN + 4, BPRI_MED)) == 0) {
601                     ++cp->ierrors;
602                     freemsg(mp);
603                     continue;
604                 }
605
606                 mp->b_rptr += vjlen;    /* drop off VJ header */
607                 dp = np->b_rptr;        /* prepend mblk with TCP/IP hdr */
608                 dp[0] = PPP_ALLSTATIONS; /* reconstruct PPP header */
609                 dp[1] = PPP_UI;
610                 dp[2] = PPP_IP >> 8;
611                 dp[3] = PPP_IP;
612                 bcopy(iphdr, dp + PPP_HDRLEN, iphlen);
613                 np->b_wptr = dp + iphlen + PPP_HDRLEN;
614                 np->b_cont = mp;
615
616                 /* XXX there seems to be a bug which causes panics in strread
617                    if we make an mbuf with only the IP header in it :-( */
618                 if (mp->b_wptr - mp->b_rptr > 4) {
619                     bcopy(mp->b_rptr, np->b_wptr, 4);
620                     mp->b_rptr += 4;
621                     np->b_wptr += 4;
622                 } else {
623                     bcopy(mp->b_rptr, np->b_wptr, mp->b_wptr - mp->b_rptr);
624                     np->b_wptr += mp->b_wptr - mp->b_rptr;
625                     np->b_cont = mp->b_cont;
626                     freeb(mp);
627                 }
628
629                 mp = np;
630
631             } else {
632                 if (!vj_uncompress_uncomp(mp->b_rptr + PPP_HDRLEN,
633                                           &cp->vj_comp)) {
634                     ++cp->ierrors;
635                     freemsg(mp);
636                     continue;
637                 }
638                 mp->b_rptr[3] = PPP_IP; /* fix up the PPP protocol field */
639             }
640         }
641
642         putnext(q, mp);
643     }
644 #if DEBUG
645     if (cp->ierrors != oldierrors)
646         cmn_err(CE_CONT, "ppp_comp_rsrv ierrors now %d\n", cp->ierrors);
647 #endif
648 }
649
650 /*
651  * Handle a CCP packet being sent or received.
652  */
653 static void
654 ppp_comp_ccp(q, mp, rcvd)
655     queue_t *q;
656     mblk_t *mp;
657     int rcvd;
658 {
659     int len, clen;
660     struct ppp_comp_state *cp;
661     unsigned char *dp;
662
663     len = msgdsize(mp);
664     if (len < PPP_HDRLEN + CCP_HDRLEN || !pullupmsg(mp, len))
665         return;
666     cp = (struct ppp_comp_state *) q->q_ptr;
667     dp = mp->b_rptr + PPP_HDRLEN;
668     len -= PPP_HDRLEN;
669     clen = CCP_LENGTH(dp);
670     if (clen > len)
671         return;
672
673     switch (CCP_CODE(dp)) {
674     case CCP_CONFREQ:
675     case CCP_TERMREQ:
676     case CCP_TERMACK:
677         cp->flags &= ~CCP_ISUP;
678         break;
679
680     case CCP_CONFACK:
681         if ((cp->flags & (CCP_ISOPEN | CCP_ISUP)) == CCP_ISOPEN
682             && clen >= CCP_HDRLEN + CCP_OPT_MINLEN
683             && clen >= CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) {
684             if (!rcvd) {
685                 if (cp->xstate != NULL
686                     && (*cp->xcomp->comp_init)
687                         (cp->xstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
688                          cp->unit, 0, 0))
689                     cp->flags |= CCP_COMP_RUN;
690             } else {
691                 if (cp->rstate != NULL
692                     && (*cp->rcomp->decomp_init)
693                         (cp->rstate, dp + CCP_HDRLEN, clen - CCP_HDRLEN,
694                          cp->unit, 0, cp->mru, 0))
695                     cp->flags = (cp->flags & ~CCP_ERR)
696                         | CCP_DECOMP_RUN;
697             }
698         }
699         break;
700
701     case CCP_RESETACK:
702         if (cp->flags & CCP_ISUP) {
703             if (!rcvd) {
704                 if (cp->xstate && (cp->flags & CCP_COMP_RUN))
705                     (*cp->xcomp->comp_reset)(cp->xstate);
706             } else {
707                 if (cp->rstate && (cp->flags & CCP_DECOMP_RUN)) {
708                     (*cp->rcomp->decomp_reset)(cp->rstate);
709                     cp->flags &= ~CCP_ERROR;
710                 }
711             }
712         }
713         break;
714     }
715
716 }
717
718 #if DEBUG
719 dump_msg(mp)
720     mblk_t *mp;
721 {
722     dblk_t *db;
723
724     while (mp != 0) {
725         db = mp->b_datap;
726         cmn_err(CE_CONT, "mp=%x cont=%x rptr=%x wptr=%x datap=%x\n",
727                 mp, mp->b_cont, mp->b_rptr, mp->b_wptr, db);
728         cmn_err(CE_CONT, "  base=%x lim=%x ref=%d type=%d struioflag=%d\n",
729                 db->db_base, db->db_lim, db->db_ref, db->db_type,
730                 db->db_struioflag);
731         mp = mp->b_cont;
732     }
733 }
734 #endif