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