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 Paul Mackerras. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The name(s) of the authors of this software must not be used to
20 * endorse or promote products derived from this software without
21 * prior written permission.
23 * 4. Redistributions of any form whatsoever must retain the following
25 * "This product includes software developed by Paul Mackerras
26 * <paulus@samba.org>".
28 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
29 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
31 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
32 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
33 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
34 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36 * $Id: deflate.c,v 1.5 2004/01/17 05:47:55 carlsonj Exp $
39 #include <sys/types.h>
44 #include <net/ppp_defs.h>
51 #define DEFLATE_DEBUG 1
54 * State for a Deflate (de)compressor.
56 struct deflate_state {
64 struct compstat stats;
67 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
69 static void *z_alloc(void *, u_int items, u_int size);
70 static void z_free(void *, void *ptr, u_int nb);
71 static void *z_decomp_alloc(u_char *options, int opt_len);
72 static void z_decomp_free(void *state);
73 static int z_decomp_init(void *state, u_char *options, int opt_len,
74 int unit, int hdrlen, int mru, int debug);
75 static void z_incomp(void *state, u_char *dmsg, int len);
76 static int z_decompress(void *state, u_char *cmp, int inlen,
77 u_char *dmp, int *outlenp);
78 static void z_decomp_reset(void *state);
79 static void z_comp_stats(void *state, struct compstat *stats);
82 * Procedures exported to if_ppp.c.
84 struct compressor ppp_deflate = {
85 CI_DEFLATE, /* compress_proto */
86 z_decomp_alloc, /* decomp_alloc */
87 z_decomp_free, /* decomp_free */
88 z_decomp_init, /* decomp_init */
89 z_decomp_reset, /* decomp_reset */
90 z_decompress, /* decompress */
91 z_incomp, /* incomp */
92 z_comp_stats, /* decomp_stat */
96 * Space allocation and freeing routines for use by zlib routines.
99 z_alloc(void *notused, u_int items, u_int size)
101 return malloc(items * size);
105 z_free(void *notused, void *ptr, u_int nbytes)
111 z_comp_stats(void *arg, struct compstat *stats)
113 struct deflate_state *state = (struct deflate_state *) arg;
116 *stats = state->stats;
117 stats->ratio = stats->unc_bytes;
118 out = stats->comp_bytes + stats->unc_bytes;
119 u_int ratio = stats->ratio;
120 if (ratio <= 0x7ffffff)
125 stats->ratio = ratio / out;
129 * Allocate space for a decompressor.
132 z_decomp_alloc(u_char *options, int opt_len)
134 struct deflate_state *state;
137 if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
138 || options[1] != CILEN_DEFLATE
139 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
140 || options[3] != DEFLATE_CHK_SEQUENCE)
142 w_size = DEFLATE_SIZE(options[2]);
143 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
146 state = (struct deflate_state *) malloc(sizeof(*state));
150 state->strm.next_out = NULL;
151 state->strm.zalloc = (alloc_func) z_alloc;
152 state->strm.zfree = (free_func) z_free;
153 if (inflateInit2(&state->strm, -w_size) != Z_OK) {
158 state->w_size = w_size;
159 memset(&state->stats, 0, sizeof(state->stats));
160 return (void *) state;
164 z_decomp_free(void *arg)
166 struct deflate_state *state = (struct deflate_state *) arg;
168 inflateEnd(&state->strm);
173 z_decomp_init(void *arg, u_char *options, int opt_len,
174 int unit, int hdrlen, int mru, int debug)
176 struct deflate_state *state = (struct deflate_state *) arg;
178 if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
179 || options[1] != CILEN_DEFLATE
180 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
181 || DEFLATE_SIZE(options[2]) != state->w_size
182 || options[3] != DEFLATE_CHK_SEQUENCE)
187 state->hdrlen = hdrlen;
188 state->debug = debug;
191 inflateReset(&state->strm);
197 z_decomp_reset(void *arg)
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(void *arg, u_char *mi, int inlen, u_char *mo, int *outlenp)
224 struct deflate_state *state = (struct deflate_state *) arg;
234 /* Check the sequence number. */
235 seq = (rptr[0] << 8) + rptr[1];
237 if (seq != state->seqno) {
241 printf("z_decompress%d: bad seq # %d, expected %d\n",
242 state->unit, seq, state->seqno);
248 * Set up to call inflate.
251 state->strm.next_in = rptr;
252 state->strm.avail_in = mi + inlen - rptr;
253 rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
254 state->strm.next_out = wptr;
255 state->strm.avail_out = state->mru + 2;
257 r = inflate(&state->strm, Z_PACKET_FLUSH);
262 printf("z_decompress%d: inflate returned %d (%s)\n",
263 state->unit, r, (state->strm.msg? state->strm.msg: ""));
264 return DECOMP_FATALERROR;
266 olen = state->mru + 2 - state->strm.avail_out;
269 if ((wptr[0] & 1) != 0)
270 ++olen; /* for suppressed protocol high byte */
271 olen += 2; /* for address, control */
274 if (olen > state->mru + PPP_HDRLEN)
275 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
276 state->unit, olen, state->mru + PPP_HDRLEN);
279 state->stats.unc_bytes += olen;
280 state->stats.unc_packets++;
281 state->stats.comp_bytes += rlen;
282 state->stats.comp_packets++;
288 * Incompressible data has arrived - add it to the history.
291 z_incomp(void *arg, u_char *mi, int mlen)
293 struct deflate_state *state = (struct deflate_state *) arg;
298 * Check that the protocol is one we handle.
302 if ((proto & 1) == 0)
303 proto = (proto << 8) + rptr[1];
304 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
311 rlen = mi + mlen - rptr;
312 state->strm.next_in = rptr;
313 state->strm.avail_in = rlen;
314 r = inflateIncomp(&state->strm);
320 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
321 state->unit, r, (state->strm.msg? state->strm.msg: ""));
331 state->stats.inc_bytes += rlen;
332 state->stats.inc_packets++;
333 state->stats.unc_bytes += rlen;
334 state->stats.unc_packets++;
337 #endif /* DO_DEFLATE */