]> git.ozlabs.org Git - ppp.git/blob - modules/deflate.c
Update README and patchlevel for 2.4.7 release
[ppp.git] / modules / deflate.c
1 /*
2  * ppp_deflate.c - interface the zlib procedures for Deflate compression
3  * and decompression (as used by gzip) to the PPP code.
4  * This version is for use with STREAMS under SunOS 4.x, Solaris 2,
5  * SVR4, OSF/1 and AIX 4.x.
6  *
7  * Copyright (c) 1994 Paul Mackerras. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. The name(s) of the authors of this software must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission.
24  *
25  * 4. Redistributions of any form whatsoever must retain the following
26  *    acknowledgment:
27  *    "This product includes software developed by Paul Mackerras
28  *     <paulus@samba.org>".
29  *
30  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
31  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
32  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
33  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
35  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
36  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37  *
38  * $Id: deflate.c,v 1.12 2004/01/17 05:47:55 carlsonj Exp $
39  */
40
41 #ifdef AIX4
42 #include <net/net_globals.h>
43 #endif
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/stream.h>
47 #include <net/ppp_defs.h>
48 #include "ppp_mod.h"
49
50 #define PACKETPTR       mblk_t *
51 #include <net/ppp-comp.h>
52
53 #ifdef __osf__
54 #include "zlib.h"
55 #else
56 #include "../common/zlib.h"
57 #endif
58
59 #ifdef SOL2
60 #include <sys/sunddi.h>
61 #endif
62
63 #if DO_DEFLATE
64
65 #define DEFLATE_DEBUG   1
66
67 /*
68  * State for a Deflate (de)compressor.
69  */
70 struct deflate_state {
71     int         seqno;
72     int         w_size;
73     int         unit;
74     int         hdrlen;
75     int         mru;
76     int         debug;
77     z_stream    strm;
78     struct compstat stats;
79 };
80
81 #define DEFLATE_OVHD    2               /* Deflate overhead/packet */
82
83 static void     *z_alloc __P((void *, u_int items, u_int size));
84 static void     *z_alloc_init __P((void *, u_int items, u_int size));
85 static void     z_free __P((void *, void *ptr));
86 static void     *z_comp_alloc __P((u_char *options, int opt_len));
87 static void     *z_decomp_alloc __P((u_char *options, int opt_len));
88 static void     z_comp_free __P((void *state));
89 static void     z_decomp_free __P((void *state));
90 static int      z_comp_init __P((void *state, u_char *options, int opt_len,
91                                  int unit, int hdrlen, int debug));
92 static int      z_decomp_init __P((void *state, u_char *options, int opt_len,
93                                      int unit, int hdrlen, int mru, int debug));
94 static int      z_compress __P((void *state, mblk_t **mret,
95                                   mblk_t *mp, int slen, int maxolen));
96 static void     z_incomp __P((void *state, mblk_t *dmsg));
97 static int      z_decompress __P((void *state, mblk_t *cmp,
98                                     mblk_t **dmpp));
99 static void     z_comp_reset __P((void *state));
100 static void     z_decomp_reset __P((void *state));
101 static void     z_comp_stats __P((void *state, struct compstat *stats));
102
103 /*
104  * Procedures exported to ppp_comp.c.
105  */
106 struct compressor ppp_deflate = {
107     CI_DEFLATE,                 /* compress_proto */
108     z_comp_alloc,               /* comp_alloc */
109     z_comp_free,                /* comp_free */
110     z_comp_init,                /* comp_init */
111     z_comp_reset,               /* comp_reset */
112     z_compress,                 /* compress */
113     z_comp_stats,               /* comp_stat */
114     z_decomp_alloc,             /* decomp_alloc */
115     z_decomp_free,              /* decomp_free */
116     z_decomp_init,              /* decomp_init */
117     z_decomp_reset,             /* decomp_reset */
118     z_decompress,               /* decompress */
119     z_incomp,                   /* incomp */
120     z_comp_stats,               /* decomp_stat */
121 };
122
123 struct compressor ppp_deflate_draft = {
124     CI_DEFLATE_DRAFT,           /* compress_proto */
125     z_comp_alloc,               /* comp_alloc */
126     z_comp_free,                /* comp_free */
127     z_comp_init,                /* comp_init */
128     z_comp_reset,               /* comp_reset */
129     z_compress,                 /* compress */
130     z_comp_stats,               /* comp_stat */
131     z_decomp_alloc,             /* decomp_alloc */
132     z_decomp_free,              /* decomp_free */
133     z_decomp_init,              /* decomp_init */
134     z_decomp_reset,             /* decomp_reset */
135     z_decompress,               /* decompress */
136     z_incomp,                   /* incomp */
137     z_comp_stats,               /* decomp_stat */
138 };
139
140 #define DECOMP_CHUNK    512
141
142 /*
143  * Space allocation and freeing routines for use by zlib routines.
144  */
145 struct zchunk {
146     u_int       size;
147     u_int       guard;
148 };
149
150 #define GUARD_MAGIC     0x77a6011a
151
152 static void *
153 z_alloc_init(notused, items, size)
154     void *notused;
155     u_int items, size;
156 {
157     struct zchunk *z;
158
159     size = items * size + sizeof(struct zchunk);
160 #ifdef __osf__
161     z = (struct zchunk *) ALLOC_SLEEP(size);
162 #else
163     z = (struct zchunk *) ALLOC_NOSLEEP(size);
164 #endif
165     z->size = size;
166     z->guard = GUARD_MAGIC;
167     return (void *) (z + 1);
168 }
169
170 static void *
171 z_alloc(notused, items, size)
172     void *notused;
173     u_int items, size;
174 {
175     struct zchunk *z;
176
177     size = items * size + sizeof(struct zchunk);
178     z = (struct zchunk *) ALLOC_NOSLEEP(size);
179     z->size = size;
180     z->guard = GUARD_MAGIC;
181     return (void *) (z + 1);
182 }
183
184 static void
185 z_free(notused, ptr)
186     void *notused;
187     void *ptr;
188 {
189     struct zchunk *z = ((struct zchunk *) ptr) - 1;
190
191     if (z->guard != GUARD_MAGIC) {
192         printf("ppp: z_free of corrupted chunk at %x (%x, %x)\n",
193                z, z->size, z->guard);
194         return;
195     }
196     FREE(z, z->size);
197 }
198
199 /*
200  * Allocate space for a compressor.
201  */
202 static void *
203 z_comp_alloc(options, opt_len)
204     u_char *options;
205     int opt_len;
206 {
207     struct deflate_state *state;
208     int w_size;
209
210     if (opt_len != CILEN_DEFLATE
211         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
212         || options[1] != CILEN_DEFLATE
213         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
214         || options[3] != DEFLATE_CHK_SEQUENCE)
215         return NULL;
216     w_size = DEFLATE_SIZE(options[2]);
217     /*
218      * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
219      * 8 will cause kernel crashes because of a bug in zlib.
220      */
221     if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
222         return NULL;
223
224
225 #ifdef __osf__
226     state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
227 #else
228     state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
229 #endif
230
231     if (state == NULL)
232         return NULL;
233
234     state->strm.next_in = NULL;
235     state->strm.zalloc = (alloc_func) z_alloc_init;
236     state->strm.zfree = (free_func) z_free;
237     if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
238                      -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
239         FREE(state, sizeof(*state));
240         return NULL;
241     }
242
243     state->strm.zalloc = (alloc_func) z_alloc;
244     state->w_size = w_size;
245     bzero(&state->stats, sizeof(state->stats));
246     return (void *) state;
247 }
248
249 static void
250 z_comp_free(arg)
251     void *arg;
252 {
253     struct deflate_state *state = (struct deflate_state *) arg;
254
255     deflateEnd(&state->strm);
256     FREE(state, sizeof(*state));
257 }
258
259 static int
260 z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
261     void *arg;
262     u_char *options;
263     int opt_len, unit, hdrlen, debug;
264 {
265     struct deflate_state *state = (struct deflate_state *) arg;
266
267     if (opt_len < CILEN_DEFLATE
268         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
269         || options[1] != CILEN_DEFLATE
270         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
271         || DEFLATE_SIZE(options[2]) != state->w_size
272         || options[3] != DEFLATE_CHK_SEQUENCE)
273         return 0;
274
275     state->seqno = 0;
276     state->unit = unit;
277     state->hdrlen = hdrlen;
278     state->debug = debug;
279
280     deflateReset(&state->strm);
281
282     return 1;
283 }
284
285 static void
286 z_comp_reset(arg)
287     void *arg;
288 {
289     struct deflate_state *state = (struct deflate_state *) arg;
290
291     state->seqno = 0;
292     deflateReset(&state->strm);
293 }
294
295 static int
296 z_compress(arg, mret, mp, orig_len, maxolen)
297     void *arg;
298     mblk_t **mret;              /* compressed packet (out) */
299     mblk_t *mp;         /* uncompressed packet (in) */
300     int orig_len, maxolen;
301 {
302     struct deflate_state *state = (struct deflate_state *) arg;
303     u_char *rptr, *wptr;
304     int proto, olen, wspace, r, flush;
305     mblk_t *m;
306
307     /*
308      * Check that the protocol is in the range we handle.
309      */
310     *mret = NULL;
311     rptr = mp->b_rptr;
312     if (rptr + PPP_HDRLEN > mp->b_wptr) {
313         if (!pullupmsg(mp, PPP_HDRLEN))
314             return 0;
315         rptr = mp->b_rptr;
316     }
317     proto = PPP_PROTOCOL(rptr);
318     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
319         return orig_len;
320
321     /* Allocate one mblk initially. */
322     if (maxolen > orig_len)
323         maxolen = orig_len;
324     if (maxolen <= PPP_HDRLEN + 2) {
325         wspace = 0;
326         m = NULL;
327     } else {
328         wspace = maxolen + state->hdrlen;
329         if (wspace > 4096)
330             wspace = 4096;
331         m = allocb(wspace, BPRI_MED);
332     }
333     if (m != NULL) {
334         *mret = m;
335         if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
336             m->b_rptr += state->hdrlen;
337             m->b_wptr = m->b_rptr;
338             wspace -= state->hdrlen;
339         }
340         wptr = m->b_wptr;
341
342         /*
343          * Copy over the PPP header and store the 2-byte sequence number.
344          */
345         wptr[0] = PPP_ADDRESS(rptr);
346         wptr[1] = PPP_CONTROL(rptr);
347         wptr[2] = PPP_COMP >> 8;
348         wptr[3] = PPP_COMP;
349         wptr += PPP_HDRLEN;
350         wptr[0] = state->seqno >> 8;
351         wptr[1] = state->seqno;
352         wptr += 2;
353         state->strm.next_out = wptr;
354         state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
355     } else {
356         state->strm.next_out = NULL;
357         state->strm.avail_out = 1000000;
358     }
359     ++state->seqno;
360
361     rptr += (proto > 0xff)? 2: 3;       /* skip 1st proto byte if 0 */
362     state->strm.next_in = rptr;
363     state->strm.avail_in = mp->b_wptr - rptr;
364     mp = mp->b_cont;
365     flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
366     olen = 0;
367     for (;;) {
368         r = deflate(&state->strm, flush);
369         if (r != Z_OK) {
370             printf("z_compress: deflate returned %d (%s)\n",
371                    r, (state->strm.msg? state->strm.msg: ""));
372             break;
373         }
374         if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
375             break;              /* all done */
376         if (state->strm.avail_in == 0 && mp != NULL) {
377             state->strm.next_in = mp->b_rptr;
378             state->strm.avail_in = mp->b_wptr - mp->b_rptr;
379             mp = mp->b_cont;
380             if (mp == NULL)
381                 flush = Z_PACKET_FLUSH;
382         }
383         if (state->strm.avail_out == 0) {
384             if (m != NULL) {
385                 m->b_wptr += wspace;
386                 olen += wspace;
387                 wspace = maxolen - olen;
388                 if (wspace <= 0) {
389                     wspace = 0;
390                     m->b_cont = NULL;
391                 } else {
392                     if (wspace < 32)
393                         wspace = 32;
394                     else if (wspace > 4096)
395                         wspace = 4096;
396                     m->b_cont = allocb(wspace, BPRI_MED);
397                 }
398                 m = m->b_cont;
399                 if (m != NULL) {
400                     state->strm.next_out = m->b_wptr;
401                     state->strm.avail_out = wspace;
402                 }
403             }
404             if (m == NULL) {
405                 state->strm.next_out = NULL;
406                 state->strm.avail_out = 1000000;
407             }
408         }
409     }
410     if (m != NULL) {
411         m->b_wptr += wspace - state->strm.avail_out;
412         olen += wspace - state->strm.avail_out;
413     }
414
415     /*
416      * See if we managed to reduce the size of the packet.
417      */
418     if (olen < orig_len && m != NULL) {
419         state->stats.comp_bytes += olen;
420         state->stats.comp_packets++;
421     } else {
422         if (*mret != NULL) {
423             freemsg(*mret);
424             *mret = NULL;
425         }
426         state->stats.inc_bytes += orig_len;
427         state->stats.inc_packets++;
428         olen = orig_len;
429     }
430     state->stats.unc_bytes += orig_len;
431     state->stats.unc_packets++;
432
433     return olen;
434 }
435
436 static void
437 z_comp_stats(arg, stats)
438     void *arg;
439     struct compstat *stats;
440 {
441     struct deflate_state *state = (struct deflate_state *) arg;
442     u_int out;
443
444     *stats = state->stats;
445     stats->ratio = stats->unc_bytes;
446     out = stats->comp_bytes + stats->unc_bytes;
447     if (stats->ratio <= 0x7ffffff)
448         stats->ratio <<= 8;
449     else
450         out >>= 8;
451     if (out != 0)
452         stats->ratio /= out;
453 }
454
455 /*
456  * Allocate space for a decompressor.
457  */
458 static void *
459 z_decomp_alloc(options, opt_len)
460     u_char *options;
461     int opt_len;
462 {
463     struct deflate_state *state;
464     int w_size;
465
466     if (opt_len != CILEN_DEFLATE
467         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
468         || options[1] != CILEN_DEFLATE
469         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
470         || options[3] != DEFLATE_CHK_SEQUENCE)
471         return NULL;
472     w_size = DEFLATE_SIZE(options[2]);
473     /*
474      * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
475      * 8 will cause kernel crashes because of a bug in zlib.
476      */
477     if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
478         return NULL;
479
480 #ifdef __osf__
481     state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
482 #else
483     state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
484 #endif
485     if (state == NULL)
486         return NULL;
487
488     state->strm.next_out = NULL;
489     state->strm.zalloc = (alloc_func) z_alloc_init;
490     state->strm.zfree = (free_func) z_free;
491     if (inflateInit2(&state->strm, -w_size) != Z_OK) {
492         FREE(state, sizeof(*state));
493         return NULL;
494     }
495
496     state->strm.zalloc = (alloc_func) z_alloc;
497     state->w_size = w_size;
498     bzero(&state->stats, sizeof(state->stats));
499     return (void *) state;
500 }
501
502 static void
503 z_decomp_free(arg)
504     void *arg;
505 {
506     struct deflate_state *state = (struct deflate_state *) arg;
507
508     inflateEnd(&state->strm);
509     FREE(state, sizeof(*state));
510 }
511
512 static int
513 z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
514     void *arg;
515     u_char *options;
516     int opt_len, unit, hdrlen, mru, debug;
517 {
518     struct deflate_state *state = (struct deflate_state *) arg;
519
520     if (opt_len < CILEN_DEFLATE
521         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
522         || options[1] != CILEN_DEFLATE
523         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
524         || DEFLATE_SIZE(options[2]) != state->w_size
525         || options[3] != DEFLATE_CHK_SEQUENCE)
526         return 0;
527
528     state->seqno = 0;
529     state->unit = unit;
530     state->hdrlen = hdrlen;
531     state->debug = debug;
532     state->mru = mru;
533
534     inflateReset(&state->strm);
535
536     return 1;
537 }
538
539 static void
540 z_decomp_reset(arg)
541     void *arg;
542 {
543     struct deflate_state *state = (struct deflate_state *) arg;
544
545     state->seqno = 0;
546     inflateReset(&state->strm);
547 }
548
549 /*
550  * Decompress a Deflate-compressed packet.
551  *
552  * Because of patent problems, we return DECOMP_ERROR for errors
553  * found by inspecting the input data and for system problems, but
554  * DECOMP_FATALERROR for any errors which could possibly be said to
555  * be being detected "after" decompression.  For DECOMP_ERROR,
556  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
557  * infringing a patent of Motorola's if we do, so we take CCP down
558  * instead.
559  *
560  * Given that the frame has the correct sequence number and a good FCS,
561  * errors such as invalid codes in the input most likely indicate a
562  * bug, so we return DECOMP_FATALERROR for them in order to turn off
563  * compression, even though they are detected by inspecting the input.
564  */
565 static int
566 z_decompress(arg, mi, mop)
567     void *arg;
568     mblk_t *mi, **mop;
569 {
570     struct deflate_state *state = (struct deflate_state *) arg;
571     mblk_t *mo, *mo_head;
572     u_char *rptr, *wptr;
573     int rlen, olen, ospace;
574     int seq, i, flush, r, decode_proto;
575     u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
576
577     *mop = NULL;
578     rptr = mi->b_rptr;
579     for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
580         while (rptr >= mi->b_wptr) {
581             mi = mi->b_cont;
582             if (mi == NULL)
583                 return DECOMP_ERROR;
584             rptr = mi->b_rptr;
585         }
586         hdr[i] = *rptr++;
587     }
588
589     /* Check the sequence number. */
590     seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
591     if (seq != state->seqno) {
592 #if !DEFLATE_DEBUG
593         if (state->debug)
594 #endif
595             printf("z_decompress%d: bad seq # %d, expected %d\n",
596                    state->unit, seq, state->seqno);
597         return DECOMP_ERROR;
598     }
599     ++state->seqno;
600
601     /* Allocate an output message block. */
602     mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
603     if (mo == NULL)
604         return DECOMP_ERROR;
605     mo_head = mo;
606     mo->b_cont = NULL;
607     mo->b_rptr += state->hdrlen;
608     mo->b_wptr = wptr = mo->b_rptr;
609     ospace = DECOMP_CHUNK;
610     olen = 0;
611
612     /*
613      * Fill in the first part of the PPP header.  The protocol field
614      * comes from the decompressed data.
615      */
616     wptr[0] = PPP_ADDRESS(hdr);
617     wptr[1] = PPP_CONTROL(hdr);
618     wptr[2] = 0;
619
620     /*
621      * Set up to call inflate.  We set avail_out to 1 initially so we can
622      * look at the first byte of the output and decide whether we have
623      * a 1-byte or 2-byte protocol field.
624      */
625     state->strm.next_in = rptr;
626     state->strm.avail_in = mi->b_wptr - rptr;
627     mi = mi->b_cont;
628     flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
629     rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
630     state->strm.next_out = wptr + 3;
631     state->strm.avail_out = 1;
632     decode_proto = 1;
633
634     /*
635      * Call inflate, supplying more input or output as needed.
636      */
637     for (;;) {
638         r = inflate(&state->strm, flush);
639         if (r != Z_OK) {
640 #if !DEFLATE_DEBUG
641             if (state->debug)
642 #endif
643                 printf("z_decompress%d: inflate returned %d (%s)\n",
644                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
645             freemsg(mo_head);
646             return DECOMP_FATALERROR;
647         }
648         if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
649             break;              /* all done */
650         if (state->strm.avail_in == 0 && mi != NULL) {
651             state->strm.next_in = mi->b_rptr;
652             state->strm.avail_in = mi->b_wptr - mi->b_rptr;
653             rlen += state->strm.avail_in;
654             mi = mi->b_cont;
655             if (mi == NULL)
656                 flush = Z_PACKET_FLUSH;
657         }
658         if (state->strm.avail_out == 0) {
659             if (decode_proto) {
660                 state->strm.avail_out = ospace - PPP_HDRLEN;
661                 if ((wptr[3] & 1) == 0) {
662                     /* 2-byte protocol field */
663                     wptr[2] = wptr[3];
664                     --state->strm.next_out;
665                     ++state->strm.avail_out;
666                 }
667                 decode_proto = 0;
668             } else {
669                 mo->b_wptr += ospace;
670                 olen += ospace;
671                 mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
672                 mo = mo->b_cont;
673                 if (mo == NULL) {
674                     freemsg(mo_head);
675                     return DECOMP_ERROR;
676                 }
677                 state->strm.next_out = mo->b_rptr;
678                 state->strm.avail_out = ospace = DECOMP_CHUNK;
679             }
680         }
681     }
682     if (decode_proto) {
683         freemsg(mo_head);
684         return DECOMP_ERROR;
685     }
686     mo->b_wptr += ospace - state->strm.avail_out;
687     olen += ospace - state->strm.avail_out;
688
689 #if DEFLATE_DEBUG
690     if (olen > state->mru + PPP_HDRLEN)
691         printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
692                state->unit, olen, state->mru + PPP_HDRLEN);
693 #endif
694
695     state->stats.unc_bytes += olen;
696     state->stats.unc_packets++;
697     state->stats.comp_bytes += rlen;
698     state->stats.comp_packets++;
699
700     *mop = mo_head;
701     return DECOMP_OK;
702 }
703
704 /*
705  * Incompressible data has arrived - add it to the history.
706  */
707 static void
708 z_incomp(arg, mi)
709     void *arg;
710     mblk_t *mi;
711 {
712     struct deflate_state *state = (struct deflate_state *) arg;
713     u_char *rptr;
714     int rlen, proto, r;
715
716     /*
717      * Check that the protocol is one we handle.
718      */
719     rptr = mi->b_rptr;
720     if (rptr + PPP_HDRLEN > mi->b_wptr) {
721         if (!pullupmsg(mi, PPP_HDRLEN))
722             return;
723         rptr = mi->b_rptr;
724     }
725     proto = PPP_PROTOCOL(rptr);
726     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
727         return;
728
729     ++state->seqno;
730
731     /*
732      * Iterate through the message blocks, adding the characters in them
733      * to the decompressor's history.  For the first block, we start
734      * at the either the 1st or 2nd byte of the protocol field,
735      * depending on whether the protocol value is compressible.
736      */
737     rlen = mi->b_wptr - mi->b_rptr;
738     state->strm.next_in = rptr + 3;
739     state->strm.avail_in = rlen - 3;
740     if (proto > 0xff) {
741         --state->strm.next_in;
742         ++state->strm.avail_in;
743     }
744     for (;;) {
745         r = inflateIncomp(&state->strm);
746         if (r != Z_OK) {
747             /* gak! */
748 #if !DEFLATE_DEBUG
749             if (state->debug)
750 #endif
751                 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
752                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
753             return;
754         }
755         mi = mi->b_cont;
756         if (mi == NULL)
757             break;
758         state->strm.next_in = mi->b_rptr;
759         state->strm.avail_in = mi->b_wptr - mi->b_rptr;
760         rlen += state->strm.avail_in;
761     }
762
763     /*
764      * Update stats.
765      */
766     state->stats.inc_bytes += rlen;
767     state->stats.inc_packets++;
768     state->stats.unc_bytes += rlen;
769     state->stats.unc_packets++;
770 }
771
772 #endif /* DO_DEFLATE */