2 * ==FILEVERSION 980319==
4 * ppp_deflate.c - interface the zlib procedures for Deflate compression
5 * and decompression (as used by gzip) to the PPP code.
6 * This version is for use with Linux kernel 1.3.X.
8 * Copyright (c) 1994 The Australian National University.
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation is hereby granted, provided that the above copyright
13 * notice appears in all copies. This software is provided without any
14 * warranty, express or implied. The Australian National University
15 * makes no representations about the suitability of this software for
18 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
19 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
20 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
21 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
24 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
26 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
27 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
28 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
31 * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp
34 #include <linux/module.h>
35 #include <linux/slab.h>
36 #include <linux/vmalloc.h>
37 #include <linux/init.h>
39 #include <linux/ppp_defs.h>
40 #include <linux/ppp-comp.h>
42 #include <linux/zlib.h>
45 * State for a Deflate (de)compressor.
47 struct ppp_deflate_state {
54 struct compstat stats;
57 #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
59 static void *z_comp_alloc __P((unsigned char *options, int opt_len));
60 static void *z_decomp_alloc __P((unsigned char *options, int opt_len));
61 static void z_comp_free __P((void *state));
62 static void z_decomp_free __P((void *state));
63 static int z_comp_init __P((void *state, unsigned char *options,
65 int unit, int hdrlen, int debug));
66 static int z_decomp_init __P((void *state, unsigned char *options,
68 int unit, int hdrlen, int mru, int debug));
69 static int z_compress __P((void *state, unsigned char *rptr,
71 int isize, int osize));
72 static void z_incomp __P((void *state, unsigned char *ibuf, int icnt));
73 static int z_decompress __P((void *state, unsigned char *ibuf,
74 int isize, unsigned char *obuf, int osize));
75 static void z_comp_reset __P((void *state));
76 static void z_decomp_reset __P((void *state));
77 static void z_comp_stats __P((void *state, struct compstat *stats));
83 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
86 zlib_deflateEnd(&state->strm);
87 if (state->strm.workspace)
88 vfree(state->strm.workspace);
95 * Allocate space for a compressor.
98 z_comp_alloc(options, opt_len)
99 unsigned char *options;
102 struct ppp_deflate_state *state;
105 if (opt_len != CILEN_DEFLATE
106 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
107 || options[1] != CILEN_DEFLATE
108 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
109 || options[3] != DEFLATE_CHK_SEQUENCE)
111 w_size = DEFLATE_SIZE(options[2]);
112 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
115 state = (struct ppp_deflate_state *) kmalloc(sizeof(*state),
121 memset (state, 0, sizeof (struct ppp_deflate_state));
122 state->strm.next_in = NULL;
123 state->w_size = w_size;
124 state->strm.workspace = vmalloc(zlib_deflate_workspacesize());
125 if (state->strm.workspace == NULL)
128 if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
129 DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
132 return (void *) state;
140 z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
142 unsigned char *options;
143 int opt_len, unit, hdrlen, debug;
145 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
147 if (opt_len < CILEN_DEFLATE
148 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
149 || options[1] != CILEN_DEFLATE
150 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
151 || DEFLATE_SIZE(options[2]) != state->w_size
152 || options[3] != DEFLATE_CHK_SEQUENCE)
157 state->debug = debug;
159 zlib_deflateReset(&state->strm);
168 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
171 zlib_deflateReset(&state->strm);
175 z_compress(arg, rptr, obuf, isize, osize)
177 unsigned char *rptr; /* uncompressed packet (in) */
178 unsigned char *obuf; /* compressed packet (out) */
181 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
182 int r, proto, off, olen, oavail;
186 * Check that the protocol is in the range we handle.
188 proto = PPP_PROTOCOL(rptr);
189 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
192 /* Don't generate compressed packets which are larger than
193 the uncompressed packet. */
200 * Copy over the PPP header and store the 2-byte sequence number.
202 wptr[0] = PPP_ADDRESS(rptr);
203 wptr[1] = PPP_CONTROL(rptr);
204 wptr[2] = PPP_COMP >> 8;
207 wptr[0] = state->seqno >> 8;
208 wptr[1] = state->seqno;
209 wptr += DEFLATE_OVHD;
210 olen = PPP_HDRLEN + DEFLATE_OVHD;
211 state->strm.next_out = wptr;
212 state->strm.avail_out = oavail = osize - olen;
215 off = (proto > 0xff) ? 2 : 3; /* skip 1st proto byte if 0 */
217 state->strm.next_in = rptr;
218 state->strm.avail_in = (isize - off);
221 r = zlib_deflate(&state->strm, Z_PACKET_FLUSH);
225 "z_compress: deflate returned %d\n", r);
228 if (state->strm.avail_out == 0) {
230 state->strm.next_out = NULL;
231 state->strm.avail_out = oavail = 1000000;
233 break; /* all done */
236 olen += oavail - state->strm.avail_out;
239 * See if we managed to reduce the size of the packet.
242 state->stats.comp_bytes += olen;
243 state->stats.comp_packets++;
245 state->stats.inc_bytes += isize;
246 state->stats.inc_packets++;
249 state->stats.unc_bytes += isize;
250 state->stats.unc_packets++;
256 z_comp_stats(arg, stats)
258 struct compstat *stats;
260 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
262 *stats = state->stats;
269 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
272 zlib_inflateEnd(&state->strm);
273 if (state->strm.workspace)
274 kfree(state->strm.workspace);
281 * Allocate space for a decompressor.
284 z_decomp_alloc(options, opt_len)
285 unsigned char *options;
288 struct ppp_deflate_state *state;
291 if (opt_len != CILEN_DEFLATE
292 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
293 || options[1] != CILEN_DEFLATE
294 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
295 || options[3] != DEFLATE_CHK_SEQUENCE)
297 w_size = DEFLATE_SIZE(options[2]);
298 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
301 state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
306 memset (state, 0, sizeof (struct ppp_deflate_state));
307 state->w_size = w_size;
308 state->strm.next_out = NULL;
309 state->strm.workspace = kmalloc(zlib_inflate_workspacesize(),
311 if (state->strm.workspace == NULL)
314 if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)
316 return (void *) state;
319 z_decomp_free(state);
324 z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
326 unsigned char *options;
327 int opt_len, unit, hdrlen, mru, debug;
329 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
331 if (opt_len < CILEN_DEFLATE
332 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
333 || options[1] != CILEN_DEFLATE
334 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
335 || DEFLATE_SIZE(options[2]) != state->w_size
336 || options[3] != DEFLATE_CHK_SEQUENCE)
341 state->debug = debug;
344 zlib_inflateReset(&state->strm);
353 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
356 zlib_inflateReset(&state->strm);
360 * Decompress a Deflate-compressed packet.
362 * Because of patent problems, we return DECOMP_ERROR for errors
363 * found by inspecting the input data and for system problems, but
364 * DECOMP_FATALERROR for any errors which could possibly be said to
365 * be being detected "after" decompression. For DECOMP_ERROR,
366 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
367 * infringing a patent of Motorola's if we do, so we take CCP down
370 * Given that the frame has the correct sequence number and a good FCS,
371 * errors such as invalid codes in the input most likely indicate a
372 * bug, so we return DECOMP_FATALERROR for them in order to turn off
373 * compression, even though they are detected by inspecting the input.
376 z_decompress(arg, ibuf, isize, obuf, osize)
383 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
385 int decode_proto, overflow;
386 unsigned char overflow_buf[1];
388 if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {
390 printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
395 /* Check the sequence number. */
396 seq = (ibuf[PPP_HDRLEN] << 8) + ibuf[PPP_HDRLEN+1];
397 if (seq != state->seqno) {
399 printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
400 state->unit, seq, state->seqno);
406 * Fill in the first part of the PPP header. The protocol field
407 * comes from the decompressed data.
409 obuf[0] = PPP_ADDRESS(ibuf);
410 obuf[1] = PPP_CONTROL(ibuf);
414 * Set up to call inflate. We set avail_out to 1 initially so we can
415 * look at the first byte of the output and decide whether we have
416 * a 1-byte or 2-byte protocol field.
418 state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;
419 state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);
420 state->strm.next_out = obuf + 3;
421 state->strm.avail_out = 1;
426 * Call inflate, supplying more input or output as needed.
429 r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);
432 printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
433 state->unit, r, (state->strm.msg? state->strm.msg: ""));
434 return DECOMP_FATALERROR;
436 if (state->strm.avail_out != 0)
437 break; /* all done */
439 state->strm.avail_out = osize - PPP_HDRLEN;
440 if ((obuf[3] & 1) == 0) {
441 /* 2-byte protocol field */
443 --state->strm.next_out;
444 ++state->strm.avail_out;
447 } else if (!overflow) {
449 * We've filled up the output buffer; the only way to
450 * find out whether inflate has any more characters
451 * left is to give it another byte of output space.
453 state->strm.next_out = overflow_buf;
454 state->strm.avail_out = 1;
458 printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
460 return DECOMP_FATALERROR;
466 printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
471 olen = osize + overflow - state->strm.avail_out;
472 state->stats.unc_bytes += olen;
473 state->stats.unc_packets++;
474 state->stats.comp_bytes += isize;
475 state->stats.comp_packets++;
481 * Incompressible data has arrived - add it to the history.
484 z_incomp(arg, ibuf, icnt)
489 struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
493 * Check that the protocol is one we handle.
495 proto = PPP_PROTOCOL(ibuf);
496 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
502 * We start at the either the 1st or 2nd byte of the protocol field,
503 * depending on whether the protocol value is compressible.
505 state->strm.next_in = ibuf + 3;
506 state->strm.avail_in = icnt - 3;
508 --state->strm.next_in;
509 ++state->strm.avail_in;
512 r = zlib_inflateIncomp(&state->strm);
516 printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
517 state->unit, r, (state->strm.msg? state->strm.msg: ""));
525 state->stats.inc_bytes += icnt;
526 state->stats.inc_packets++;
527 state->stats.unc_bytes += icnt;
528 state->stats.unc_packets++;
531 /*************************************************************
532 * Module interface table
533 *************************************************************/
535 /* These are in ppp_generic.c */
536 extern int ppp_register_compressor (struct compressor *cp);
537 extern void ppp_unregister_compressor (struct compressor *cp);
540 * Procedures exported to if_ppp.c.
542 struct compressor ppp_deflate = {
543 CI_DEFLATE, /* compress_proto */
544 z_comp_alloc, /* comp_alloc */
545 z_comp_free, /* comp_free */
546 z_comp_init, /* comp_init */
547 z_comp_reset, /* comp_reset */
548 z_compress, /* compress */
549 z_comp_stats, /* comp_stat */
550 z_decomp_alloc, /* decomp_alloc */
551 z_decomp_free, /* decomp_free */
552 z_decomp_init, /* decomp_init */
553 z_decomp_reset, /* decomp_reset */
554 z_decompress, /* decompress */
555 z_incomp, /* incomp */
556 z_comp_stats, /* decomp_stat */
559 struct compressor ppp_deflate_draft = {
560 CI_DEFLATE_DRAFT, /* compress_proto */
561 z_comp_alloc, /* comp_alloc */
562 z_comp_free, /* comp_free */
563 z_comp_init, /* comp_init */
564 z_comp_reset, /* comp_reset */
565 z_compress, /* compress */
566 z_comp_stats, /* comp_stat */
567 z_decomp_alloc, /* decomp_alloc */
568 z_decomp_free, /* decomp_free */
569 z_decomp_init, /* decomp_init */
570 z_decomp_reset, /* decomp_reset */
571 z_decompress, /* decompress */
572 z_incomp, /* incomp */
573 z_comp_stats, /* decomp_stat */
576 int __init deflate_init(void)
578 int answer = ppp_register_compressor(&ppp_deflate);
581 "PPP Deflate Compression module registered\n");
582 ppp_register_compressor(&ppp_deflate_draft);
586 void __exit deflate_cleanup(void)
588 ppp_unregister_compressor(&ppp_deflate);
589 ppp_unregister_compressor(&ppp_deflate_draft);
592 module_init(deflate_init);
593 module_exit(deflate_cleanup);
594 MODULE_LICENSE("Dual BSD/GPL");