2 * ppp_deflate.c - interface the zlib procedures for Deflate compression
3 * and decompression (as used by gzip) to the PPP code.
5 * Copyright (c) 1994 The Australian National University.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation is hereby granted, provided that the above copyright
10 * notice appears in all copies. This software is provided without any
11 * warranty, express or implied. The Australian National University
12 * makes no representations about the suitability of this software for
15 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
16 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
17 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
18 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
21 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
24 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
25 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
28 * $Id: deflate.c,v 1.1 1999/03/23 03:21:57 paulus Exp $
31 #include <sys/types.h>
39 #define DEFLATE_DEBUG 1
42 * State for a Deflate (de)compressor.
44 struct deflate_state {
52 struct compstat stats;
55 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
57 static void *z_alloc __P((void *, u_int items, u_int size));
58 static void z_free __P((void *, void *ptr, u_int nb));
59 static void *z_decomp_alloc __P((u_char *options, int opt_len));
60 static void z_decomp_free __P((void *state));
61 static int z_decomp_init __P((void *state, u_char *options, int opt_len,
62 int unit, int hdrlen, int mru, int debug));
63 static void z_incomp __P((void *state, u_char *dmsg, int len));
64 static int z_decompress __P((void *state, u_char *cmp, int inlen,
65 u_char *dmp, int *outlenp));
66 static void z_decomp_reset __P((void *state));
67 static void z_comp_stats __P((void *state, struct compstat *stats));
70 * Procedures exported to if_ppp.c.
72 struct compressor ppp_deflate = {
73 CI_DEFLATE, /* compress_proto */
74 z_decomp_alloc, /* decomp_alloc */
75 z_decomp_free, /* decomp_free */
76 z_decomp_init, /* decomp_init */
77 z_decomp_reset, /* decomp_reset */
78 z_decompress, /* decompress */
79 z_incomp, /* incomp */
80 z_comp_stats, /* decomp_stat */
84 * Space allocation and freeing routines for use by zlib routines.
87 z_alloc(notused, items, size)
91 return malloc(items * size);
95 z_free(notused, ptr, nbytes)
104 z_comp_stats(arg, stats)
106 struct compstat *stats;
108 struct deflate_state *state = (struct deflate_state *) arg;
111 *stats = state->stats;
112 stats->ratio = stats->unc_bytes;
113 out = stats->comp_bytes + stats->unc_bytes;
114 if (stats->ratio <= 0x7ffffff)
123 * Allocate space for a decompressor.
126 z_decomp_alloc(options, opt_len)
130 struct deflate_state *state;
133 if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
134 || options[1] != CILEN_DEFLATE
135 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
136 || options[3] != DEFLATE_CHK_SEQUENCE)
138 w_size = DEFLATE_SIZE(options[2]);
139 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
142 state = (struct deflate_state *) malloc(sizeof(*state));
146 state->strm.next_out = NULL;
147 state->strm.zalloc = (alloc_func) z_alloc;
148 state->strm.zfree = (free_func) z_free;
149 if (inflateInit2(&state->strm, -w_size) != Z_OK) {
154 state->w_size = w_size;
155 bzero(&state->stats, sizeof(state->stats));
156 return (void *) state;
163 struct deflate_state *state = (struct deflate_state *) arg;
165 inflateEnd(&state->strm);
170 z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
173 int opt_len, unit, hdrlen, mru, debug;
175 struct deflate_state *state = (struct deflate_state *) arg;
177 if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
178 || options[1] != CILEN_DEFLATE
179 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
180 || DEFLATE_SIZE(options[2]) != state->w_size
181 || options[3] != DEFLATE_CHK_SEQUENCE)
186 state->hdrlen = hdrlen;
187 state->debug = debug;
190 inflateReset(&state->strm);
199 struct deflate_state *state = (struct deflate_state *) arg;
202 inflateReset(&state->strm);
206 * Decompress a Deflate-compressed packet.
208 * Because of patent problems, we return DECOMP_ERROR for errors
209 * found by inspecting the input data and for system problems, but
210 * DECOMP_FATALERROR for any errors which could possibly be said to
211 * be being detected "after" decompression. For DECOMP_ERROR,
212 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
213 * infringing a patent of Motorola's if we do, so we take CCP down
216 * Given that the frame has the correct sequence number and a good FCS,
217 * errors such as invalid codes in the input most likely indicate a
218 * bug, so we return DECOMP_FATALERROR for them in order to turn off
219 * compression, even though they are detected by inspecting the input.
222 z_decompress(arg, mi, inlen, mo, outlenp)
227 struct deflate_state *state = (struct deflate_state *) arg;
229 int rlen, olen, ospace;
230 int seq, i, flush, r, decode_proto;
237 /* Check the sequence number. */
238 seq = (rptr[0] << 8) + rptr[1];
240 if (seq != state->seqno) {
244 printf("z_decompress%d: bad seq # %d, expected %d\n",
245 state->unit, seq, state->seqno);
251 * Set up to call inflate.
254 state->strm.next_in = rptr;
255 state->strm.avail_in = mi + inlen - rptr;
256 rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
257 state->strm.next_out = wptr;
258 state->strm.avail_out = state->mru + 2;
260 r = inflate(&state->strm, Z_PACKET_FLUSH);
265 printf("z_decompress%d: inflate returned %d (%s)\n",
266 state->unit, r, (state->strm.msg? state->strm.msg: ""));
267 return DECOMP_FATALERROR;
269 olen = state->mru + 2 - state->strm.avail_out;
272 if ((wptr[0] & 1) != 0)
273 ++olen; /* for suppressed protocol high byte */
274 olen += 2; /* for address, control */
277 if (olen > state->mru + PPP_HDRLEN)
278 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
279 state->unit, olen, state->mru + PPP_HDRLEN);
282 state->stats.unc_bytes += olen;
283 state->stats.unc_packets++;
284 state->stats.comp_bytes += rlen;
285 state->stats.comp_packets++;
291 * Incompressible data has arrived - add it to the history.
294 z_incomp(arg, mi, mlen)
299 struct deflate_state *state = (struct deflate_state *) arg;
304 * Check that the protocol is one we handle.
308 if ((proto & 1) == 0)
309 proto = (proto << 8) + rptr[1];
310 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
317 rlen = mi + mlen - rptr;
318 state->strm.next_in = rptr;
319 state->strm.avail_in = rlen;
320 r = inflateIncomp(&state->strm);
326 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
327 state->unit, r, (state->strm.msg? state->strm.msg: ""));
337 state->stats.inc_bytes += rlen;
338 state->stats.inc_packets++;
339 state->stats.unc_bytes += rlen;
340 state->stats.unc_packets++;
343 #endif /* DO_DEFLATE */