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>
50 #define DEFLATE_DEBUG 1
53 * State for a Deflate (de)compressor.
55 struct deflate_state
{
63 struct compstat stats
;
66 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
68 static void *z_alloc
__P((void *, u_int items
, u_int size
));
69 static void z_free
__P((void *, void *ptr
, u_int nb
));
70 static void *z_decomp_alloc
__P((u_char
*options
, int opt_len
));
71 static void z_decomp_free
__P((void *state
));
72 static int z_decomp_init
__P((void *state
, u_char
*options
, int opt_len
,
73 int unit
, int hdrlen
, int mru
, int debug
));
74 static void z_incomp
__P((void *state
, u_char
*dmsg
, int len
));
75 static int z_decompress
__P((void *state
, u_char
*cmp
, int inlen
,
76 u_char
*dmp
, int *outlenp
));
77 static void z_decomp_reset
__P((void *state
));
78 static void z_comp_stats
__P((void *state
, struct compstat
*stats
));
81 * Procedures exported to if_ppp.c.
83 struct compressor ppp_deflate
= {
84 CI_DEFLATE
, /* compress_proto */
85 z_decomp_alloc
, /* decomp_alloc */
86 z_decomp_free
, /* decomp_free */
87 z_decomp_init
, /* decomp_init */
88 z_decomp_reset
, /* decomp_reset */
89 z_decompress
, /* decompress */
90 z_incomp
, /* incomp */
91 z_comp_stats
, /* decomp_stat */
95 * Space allocation and freeing routines for use by zlib routines.
98 z_alloc(notused
, items
, size
)
102 return malloc(items
* size
);
106 z_free(notused
, ptr
, nbytes
)
115 z_comp_stats(arg
, stats
)
117 struct compstat
*stats
;
119 struct deflate_state
*state
= (struct deflate_state
*) arg
;
122 *stats
= state
->stats
;
123 stats
->ratio
= stats
->unc_bytes
;
124 out
= stats
->comp_bytes
+ stats
->unc_bytes
;
125 if (stats
->ratio
<= 0x7ffffff)
134 * Allocate space for a decompressor.
137 z_decomp_alloc(options
, opt_len
)
141 struct deflate_state
*state
;
144 if (opt_len
!= CILEN_DEFLATE
|| options
[0] != CI_DEFLATE
145 || options
[1] != CILEN_DEFLATE
146 || DEFLATE_METHOD(options
[2]) != DEFLATE_METHOD_VAL
147 || options
[3] != DEFLATE_CHK_SEQUENCE
)
149 w_size
= DEFLATE_SIZE(options
[2]);
150 if (w_size
< DEFLATE_MIN_SIZE
|| w_size
> DEFLATE_MAX_SIZE
)
153 state
= (struct deflate_state
*) malloc(sizeof(*state
));
157 state
->strm
.next_out
= NULL
;
158 state
->strm
.zalloc
= (alloc_func
) z_alloc
;
159 state
->strm
.zfree
= (free_func
) z_free
;
160 if (inflateInit2(&state
->strm
, -w_size
) != Z_OK
) {
165 state
->w_size
= w_size
;
166 memset(&state
->stats
, 0, sizeof(state
->stats
));
167 return (void *) state
;
174 struct deflate_state
*state
= (struct deflate_state
*) arg
;
176 inflateEnd(&state
->strm
);
181 z_decomp_init(arg
, options
, opt_len
, unit
, hdrlen
, mru
, debug
)
184 int opt_len
, unit
, hdrlen
, mru
, debug
;
186 struct deflate_state
*state
= (struct deflate_state
*) arg
;
188 if (opt_len
< CILEN_DEFLATE
|| options
[0] != CI_DEFLATE
189 || options
[1] != CILEN_DEFLATE
190 || DEFLATE_METHOD(options
[2]) != DEFLATE_METHOD_VAL
191 || DEFLATE_SIZE(options
[2]) != state
->w_size
192 || options
[3] != DEFLATE_CHK_SEQUENCE
)
197 state
->hdrlen
= hdrlen
;
198 state
->debug
= debug
;
201 inflateReset(&state
->strm
);
210 struct deflate_state
*state
= (struct deflate_state
*) arg
;
213 inflateReset(&state
->strm
);
217 * Decompress a Deflate-compressed packet.
219 * Because of patent problems, we return DECOMP_ERROR for errors
220 * found by inspecting the input data and for system problems, but
221 * DECOMP_FATALERROR for any errors which could possibly be said to
222 * be being detected "after" decompression. For DECOMP_ERROR,
223 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
224 * infringing a patent of Motorola's if we do, so we take CCP down
227 * Given that the frame has the correct sequence number and a good FCS,
228 * errors such as invalid codes in the input most likely indicate a
229 * bug, so we return DECOMP_FATALERROR for them in order to turn off
230 * compression, even though they are detected by inspecting the input.
233 z_decompress(arg
, mi
, inlen
, mo
, outlenp
)
238 struct deflate_state
*state
= (struct deflate_state
*) arg
;
248 /* Check the sequence number. */
249 seq
= (rptr
[0] << 8) + rptr
[1];
251 if (seq
!= state
->seqno
) {
255 printf("z_decompress%d: bad seq # %d, expected %d\n",
256 state
->unit
, seq
, state
->seqno
);
262 * Set up to call inflate.
265 state
->strm
.next_in
= rptr
;
266 state
->strm
.avail_in
= mi
+ inlen
- rptr
;
267 rlen
= state
->strm
.avail_in
+ PPP_HDRLEN
+ DEFLATE_OVHD
;
268 state
->strm
.next_out
= wptr
;
269 state
->strm
.avail_out
= state
->mru
+ 2;
271 r
= inflate(&state
->strm
, Z_PACKET_FLUSH
);
276 printf("z_decompress%d: inflate returned %d (%s)\n",
277 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
278 return DECOMP_FATALERROR
;
280 olen
= state
->mru
+ 2 - state
->strm
.avail_out
;
283 if ((wptr
[0] & 1) != 0)
284 ++olen
; /* for suppressed protocol high byte */
285 olen
+= 2; /* for address, control */
288 if (olen
> state
->mru
+ PPP_HDRLEN
)
289 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
290 state
->unit
, olen
, state
->mru
+ PPP_HDRLEN
);
293 state
->stats
.unc_bytes
+= olen
;
294 state
->stats
.unc_packets
++;
295 state
->stats
.comp_bytes
+= rlen
;
296 state
->stats
.comp_packets
++;
302 * Incompressible data has arrived - add it to the history.
305 z_incomp(arg
, mi
, mlen
)
310 struct deflate_state
*state
= (struct deflate_state
*) arg
;
315 * Check that the protocol is one we handle.
319 if ((proto
& 1) == 0)
320 proto
= (proto
<< 8) + rptr
[1];
321 if (proto
> 0x3fff || proto
== 0xfd || proto
== 0xfb)
328 rlen
= mi
+ mlen
- rptr
;
329 state
->strm
.next_in
= rptr
;
330 state
->strm
.avail_in
= rlen
;
331 r
= inflateIncomp(&state
->strm
);
337 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
338 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
348 state
->stats
.inc_bytes
+= rlen
;
349 state
->stats
.inc_packets
++;
350 state
->stats
.unc_bytes
+= rlen
;
351 state
->stats
.unc_packets
++;
354 #endif /* DO_DEFLATE */