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>
34 #ifdef PPP_DEFS_IN_NET
35 #include <net/ppp_defs.h>
44 #define DEFLATE_DEBUG 1
47 * State for a Deflate (de)compressor.
49 struct deflate_state
{
57 struct compstat stats
;
60 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
62 static void *z_alloc
__P((void *, u_int items
, u_int size
));
63 static void z_free
__P((void *, void *ptr
, u_int nb
));
64 static void *z_decomp_alloc
__P((u_char
*options
, int opt_len
));
65 static void z_decomp_free
__P((void *state
));
66 static int z_decomp_init
__P((void *state
, u_char
*options
, int opt_len
,
67 int unit
, int hdrlen
, int mru
, int debug
));
68 static void z_incomp
__P((void *state
, u_char
*dmsg
, int len
));
69 static int z_decompress
__P((void *state
, u_char
*cmp
, int inlen
,
70 u_char
*dmp
, int *outlenp
));
71 static void z_decomp_reset
__P((void *state
));
72 static void z_comp_stats
__P((void *state
, struct compstat
*stats
));
75 * Procedures exported to if_ppp.c.
77 struct compressor ppp_deflate
= {
78 CI_DEFLATE
, /* compress_proto */
79 z_decomp_alloc
, /* decomp_alloc */
80 z_decomp_free
, /* decomp_free */
81 z_decomp_init
, /* decomp_init */
82 z_decomp_reset
, /* decomp_reset */
83 z_decompress
, /* decompress */
84 z_incomp
, /* incomp */
85 z_comp_stats
, /* decomp_stat */
89 * Space allocation and freeing routines for use by zlib routines.
92 z_alloc(notused
, items
, size
)
96 return malloc(items
* size
);
100 z_free(notused
, ptr
, nbytes
)
109 z_comp_stats(arg
, stats
)
111 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 if (stats
->ratio
<= 0x7ffffff)
128 * Allocate space for a decompressor.
131 z_decomp_alloc(options
, opt_len
)
135 struct deflate_state
*state
;
138 if (opt_len
!= CILEN_DEFLATE
|| options
[0] != CI_DEFLATE
139 || options
[1] != CILEN_DEFLATE
140 || DEFLATE_METHOD(options
[2]) != DEFLATE_METHOD_VAL
141 || options
[3] != DEFLATE_CHK_SEQUENCE
)
143 w_size
= DEFLATE_SIZE(options
[2]);
144 if (w_size
< DEFLATE_MIN_SIZE
|| w_size
> DEFLATE_MAX_SIZE
)
147 state
= (struct deflate_state
*) malloc(sizeof(*state
));
151 state
->strm
.next_out
= NULL
;
152 state
->strm
.zalloc
= (alloc_func
) z_alloc
;
153 state
->strm
.zfree
= (free_func
) z_free
;
154 if (inflateInit2(&state
->strm
, -w_size
) != Z_OK
) {
159 state
->w_size
= w_size
;
160 memset(&state
->stats
, 0, sizeof(state
->stats
));
161 return (void *) state
;
168 struct deflate_state
*state
= (struct deflate_state
*) arg
;
170 inflateEnd(&state
->strm
);
175 z_decomp_init(arg
, options
, opt_len
, unit
, hdrlen
, mru
, debug
)
178 int opt_len
, unit
, hdrlen
, mru
, debug
;
180 struct deflate_state
*state
= (struct deflate_state
*) arg
;
182 if (opt_len
< CILEN_DEFLATE
|| options
[0] != CI_DEFLATE
183 || options
[1] != CILEN_DEFLATE
184 || DEFLATE_METHOD(options
[2]) != DEFLATE_METHOD_VAL
185 || DEFLATE_SIZE(options
[2]) != state
->w_size
186 || options
[3] != DEFLATE_CHK_SEQUENCE
)
191 state
->hdrlen
= hdrlen
;
192 state
->debug
= debug
;
195 inflateReset(&state
->strm
);
204 struct deflate_state
*state
= (struct deflate_state
*) arg
;
207 inflateReset(&state
->strm
);
211 * Decompress a Deflate-compressed packet.
213 * Because of patent problems, we return DECOMP_ERROR for errors
214 * found by inspecting the input data and for system problems, but
215 * DECOMP_FATALERROR for any errors which could possibly be said to
216 * be being detected "after" decompression. For DECOMP_ERROR,
217 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
218 * infringing a patent of Motorola's if we do, so we take CCP down
221 * Given that the frame has the correct sequence number and a good FCS,
222 * errors such as invalid codes in the input most likely indicate a
223 * bug, so we return DECOMP_FATALERROR for them in order to turn off
224 * compression, even though they are detected by inspecting the input.
227 z_decompress(arg
, mi
, inlen
, mo
, outlenp
)
232 struct deflate_state
*state
= (struct deflate_state
*) arg
;
234 int rlen
, olen
, ospace
;
235 int seq
, i
, flush
, r
, decode_proto
;
242 /* Check the sequence number. */
243 seq
= (rptr
[0] << 8) + rptr
[1];
245 if (seq
!= state
->seqno
) {
249 printf("z_decompress%d: bad seq # %d, expected %d\n",
250 state
->unit
, seq
, state
->seqno
);
256 * Set up to call inflate.
259 state
->strm
.next_in
= rptr
;
260 state
->strm
.avail_in
= mi
+ inlen
- rptr
;
261 rlen
= state
->strm
.avail_in
+ PPP_HDRLEN
+ DEFLATE_OVHD
;
262 state
->strm
.next_out
= wptr
;
263 state
->strm
.avail_out
= state
->mru
+ 2;
265 r
= inflate(&state
->strm
, Z_PACKET_FLUSH
);
270 printf("z_decompress%d: inflate returned %d (%s)\n",
271 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
272 return DECOMP_FATALERROR
;
274 olen
= state
->mru
+ 2 - state
->strm
.avail_out
;
277 if ((wptr
[0] & 1) != 0)
278 ++olen
; /* for suppressed protocol high byte */
279 olen
+= 2; /* for address, control */
282 if (olen
> state
->mru
+ PPP_HDRLEN
)
283 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
284 state
->unit
, olen
, state
->mru
+ PPP_HDRLEN
);
287 state
->stats
.unc_bytes
+= olen
;
288 state
->stats
.unc_packets
++;
289 state
->stats
.comp_bytes
+= rlen
;
290 state
->stats
.comp_packets
++;
296 * Incompressible data has arrived - add it to the history.
299 z_incomp(arg
, mi
, mlen
)
304 struct deflate_state
*state
= (struct deflate_state
*) arg
;
309 * Check that the protocol is one we handle.
313 if ((proto
& 1) == 0)
314 proto
= (proto
<< 8) + rptr
[1];
315 if (proto
> 0x3fff || proto
== 0xfd || proto
== 0xfb)
322 rlen
= mi
+ mlen
- rptr
;
323 state
->strm
.next_in
= rptr
;
324 state
->strm
.avail_in
= rlen
;
325 r
= inflateIncomp(&state
->strm
);
331 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
332 state
->unit
, r
, (state
->strm
.msg
? state
->strm
.msg
: ""));
342 state
->stats
.inc_bytes
+= rlen
;
343 state
->stats
.inc_packets
++;
344 state
->stats
.unc_bytes
+= rlen
;
345 state
->stats
.unc_packets
++;
348 #endif /* DO_DEFLATE */