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.3 1999/04/16 11:35:59 paulus Exp $
31 #include <sys/types.h>
40 #define DEFLATE_DEBUG 1
43 * State for a Deflate (de)compressor.
45 struct deflate_state
{
53 struct compstat stats
;
56 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
58 static void *z_alloc
__P((void *, u_int items
, u_int size
));
59 static void z_free
__P((void *, void *ptr
, u_int nb
));
60 static void *z_decomp_alloc
__P((u_char
*options
, int opt_len
));
61 static void z_decomp_free
__P((void *state
));
62 static int z_decomp_init
__P((void *state
, u_char
*options
, int opt_len
,
63 int unit
, int hdrlen
, int mru
, int debug
));
64 static void z_incomp
__P((void *state
, u_char
*dmsg
, int len
));
65 static int z_decompress
__P((void *state
, u_char
*cmp
, int inlen
,
66 u_char
*dmp
, int *outlenp
));
67 static void z_decomp_reset
__P((void *state
));
68 static void z_comp_stats
__P((void *state
, struct compstat
*stats
));
71 * Procedures exported to if_ppp.c.
73 struct compressor ppp_deflate
= {
74 CI_DEFLATE
, /* compress_proto */
75 z_decomp_alloc
, /* decomp_alloc */
76 z_decomp_free
, /* decomp_free */
77 z_decomp_init
, /* decomp_init */
78 z_decomp_reset
, /* decomp_reset */
79 z_decompress
, /* decompress */
80 z_incomp
, /* incomp */
81 z_comp_stats
, /* decomp_stat */
85 * Space allocation and freeing routines for use by zlib routines.
88 z_alloc(notused
, items
, size
)
92 return malloc(items
* size
);
96 z_free(notused
, ptr
, nbytes
)
105 z_comp_stats(arg
, stats
)
107 struct compstat
*stats
;
109 struct deflate_state
*state
= (struct deflate_state
*) arg
;
112 *stats
= state
->stats
;
113 stats
->ratio
= stats
->unc_bytes
;
114 out
= stats
->comp_bytes
+ stats
->unc_bytes
;
115 if (stats
->ratio
<= 0x7ffffff)
124 * Allocate space for a decompressor.
127 z_decomp_alloc(options
, opt_len
)
131 struct deflate_state
*state
;
134 if (opt_len
!= CILEN_DEFLATE
|| options
[0] != CI_DEFLATE
135 || options
[1] != CILEN_DEFLATE
136 || DEFLATE_METHOD(options
[2]) != DEFLATE_METHOD_VAL
137 || options
[3] != DEFLATE_CHK_SEQUENCE
)
139 w_size
= DEFLATE_SIZE(options
[2]);
140 if (w_size
< DEFLATE_MIN_SIZE
|| w_size
> DEFLATE_MAX_SIZE
)
143 state
= (struct deflate_state
*) malloc(sizeof(*state
));
147 state
->strm
.next_out
= NULL
;
148 state
->strm
.zalloc
= (alloc_func
) z_alloc
;
149 state
->strm
.zfree
= (free_func
) z_free
;
150 if (inflateInit2(&state
->strm
, -w_size
) != Z_OK
) {
155 state
->w_size
= w_size
;
156 memset(&state
->stats
, 0, sizeof(state
->stats
));
157 return (void *) state
;
164 struct deflate_state
*state
= (struct deflate_state
*) arg
;
166 inflateEnd(&state
->strm
);
171 z_decomp_init(arg
, options
, opt_len
, unit
, hdrlen
, mru
, debug
)
174 int opt_len
, unit
, hdrlen
, mru
, 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
);
200 struct deflate_state
*state
= (struct deflate_state
*) arg
;
203 inflateReset(&state
->strm
);
207 * Decompress a Deflate-compressed packet.
209 * Because of patent problems, we return DECOMP_ERROR for errors
210 * found by inspecting the input data and for system problems, but
211 * DECOMP_FATALERROR for any errors which could possibly be said to
212 * be being detected "after" decompression. For DECOMP_ERROR,
213 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
214 * infringing a patent of Motorola's if we do, so we take CCP down
217 * Given that the frame has the correct sequence number and a good FCS,
218 * errors such as invalid codes in the input most likely indicate a
219 * bug, so we return DECOMP_FATALERROR for them in order to turn off
220 * compression, even though they are detected by inspecting the input.
223 z_decompress(arg
, mi
, inlen
, mo
, outlenp
)
228 struct deflate_state
*state
= (struct deflate_state
*) arg
;
230 int rlen
, olen
, ospace
;
231 int seq
, i
, flush
, r
, decode_proto
;
238 /* Check the sequence number. */
239 seq
= (rptr
[0] << 8) + rptr
[1];
241 if (seq
!= state
->seqno
) {
245 printf("z_decompress%d: bad seq # %d, expected %d\n",
246 state
->unit
, seq
, state
->seqno
);
252 * Set up to call inflate.
255 state
->strm
.next_in
= rptr
;
256 state
->strm
.avail_in
= mi
+ inlen
- rptr
;
257 rlen
= state
->strm
.avail_in
+ PPP_HDRLEN
+ DEFLATE_OVHD
;
258 state
->strm
.next_out
= wptr
;
259 state
->strm
.avail_out
= state
->mru
+ 2;
261 r
= inflate(&state
->strm
, Z_PACKET_FLUSH
);
266 printf("z_decompress%d: inflate returned %d (%s)\n",
267 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
268 return DECOMP_FATALERROR
;
270 olen
= state
->mru
+ 2 - state
->strm
.avail_out
;
273 if ((wptr
[0] & 1) != 0)
274 ++olen
; /* for suppressed protocol high byte */
275 olen
+= 2; /* for address, control */
278 if (olen
> state
->mru
+ PPP_HDRLEN
)
279 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
280 state
->unit
, olen
, state
->mru
+ PPP_HDRLEN
);
283 state
->stats
.unc_bytes
+= olen
;
284 state
->stats
.unc_packets
++;
285 state
->stats
.comp_bytes
+= rlen
;
286 state
->stats
.comp_packets
++;
292 * Incompressible data has arrived - add it to the history.
295 z_incomp(arg
, mi
, mlen
)
300 struct deflate_state
*state
= (struct deflate_state
*) arg
;
305 * Check that the protocol is one we handle.
309 if ((proto
& 1) == 0)
310 proto
= (proto
<< 8) + rptr
[1];
311 if (proto
> 0x3fff || proto
== 0xfd || proto
== 0xfb)
318 rlen
= mi
+ mlen
- rptr
;
319 state
->strm
.next_in
= rptr
;
320 state
->strm
.avail_in
= rlen
;
321 r
= inflateIncomp(&state
->strm
);
327 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
328 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
338 state
->stats
.inc_bytes
+= rlen
;
339 state
->stats
.inc_packets
++;
340 state
->stats
.unc_bytes
+= rlen
;
341 state
->stats
.unc_packets
++;
344 #endif /* DO_DEFLATE */