xref: /openbmc/linux/drivers/net/ppp/ppp_deflate.c (revision 2025cf9e)
1 /*
2  * ppp_deflate.c - interface the zlib procedures for Deflate compression
3  * and decompression (as used by gzip) to the PPP code.
4  *
5  * Copyright 1994-1998 Paul Mackerras.
6  *
7  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  version 2 as published by the Free Software Foundation.
10  */
11 
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/vmalloc.h>
15 #include <linux/init.h>
16 #include <linux/string.h>
17 
18 #include <linux/ppp_defs.h>
19 #include <linux/ppp-comp.h>
20 
21 #include <linux/zlib.h>
22 #include <asm/unaligned.h>
23 
24 /*
25  * State for a Deflate (de)compressor.
26  */
27 struct ppp_deflate_state {
28     int		seqno;
29     int		w_size;
30     int		unit;
31     int		mru;
32     int		debug;
33     z_stream	strm;
34     struct compstat stats;
35 };
36 
37 #define DEFLATE_OVHD	2		/* Deflate overhead/packet */
38 
39 static void	*z_comp_alloc(unsigned char *options, int opt_len);
40 static void	*z_decomp_alloc(unsigned char *options, int opt_len);
41 static void	z_comp_free(void *state);
42 static void	z_decomp_free(void *state);
43 static int	z_comp_init(void *state, unsigned char *options,
44 				 int opt_len,
45 				 int unit, int hdrlen, int debug);
46 static int	z_decomp_init(void *state, unsigned char *options,
47 				   int opt_len,
48 				   int unit, int hdrlen, int mru, int debug);
49 static int	z_compress(void *state, unsigned char *rptr,
50 				unsigned char *obuf,
51 				int isize, int osize);
52 static void	z_incomp(void *state, unsigned char *ibuf, int icnt);
53 static int	z_decompress(void *state, unsigned char *ibuf,
54 				int isize, unsigned char *obuf, int osize);
55 static void	z_comp_reset(void *state);
56 static void	z_decomp_reset(void *state);
57 static void	z_comp_stats(void *state, struct compstat *stats);
58 
59 /**
60  *	z_comp_free - free the memory used by a compressor
61  *	@arg:	pointer to the private state for the compressor.
62  */
63 static void z_comp_free(void *arg)
64 {
65 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
66 
67 	if (state) {
68 		zlib_deflateEnd(&state->strm);
69 		vfree(state->strm.workspace);
70 		kfree(state);
71 	}
72 }
73 
74 /**
75  *	z_comp_alloc - allocate space for a compressor.
76  *	@options: pointer to CCP option data
77  *	@opt_len: length of the CCP option at @options.
78  *
79  *	The @options pointer points to the a buffer containing the
80  *	CCP option data for the compression being negotiated.  It is
81  *	formatted according to RFC1979, and describes the window
82  *	size that the peer is requesting that we use in compressing
83  *	data to be sent to it.
84  *
85  *	Returns the pointer to the private state for the compressor,
86  *	or NULL if we could not allocate enough memory.
87  */
88 static void *z_comp_alloc(unsigned char *options, int opt_len)
89 {
90 	struct ppp_deflate_state *state;
91 	int w_size;
92 
93 	if (opt_len != CILEN_DEFLATE ||
94 	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
95 	    options[1] != CILEN_DEFLATE ||
96 	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
97 	    options[3] != DEFLATE_CHK_SEQUENCE)
98 		return NULL;
99 	w_size = DEFLATE_SIZE(options[2]);
100 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
101 		return NULL;
102 
103 	state = kzalloc(sizeof(*state),
104 						     GFP_KERNEL);
105 	if (state == NULL)
106 		return NULL;
107 
108 	state->strm.next_in   = NULL;
109 	state->w_size         = w_size;
110 	state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
111 	if (state->strm.workspace == NULL)
112 		goto out_free;
113 
114 	if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
115 			 DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
116 	    != Z_OK)
117 		goto out_free;
118 	return (void *) state;
119 
120 out_free:
121 	z_comp_free(state);
122 	return NULL;
123 }
124 
125 /**
126  *	z_comp_init - initialize a previously-allocated compressor.
127  *	@arg:	pointer to the private state for the compressor
128  *	@options: pointer to the CCP option data describing the
129  *		compression that was negotiated with the peer
130  *	@opt_len: length of the CCP option data at @options
131  *	@unit:	PPP unit number for diagnostic messages
132  *	@hdrlen: ignored (present for backwards compatibility)
133  *	@debug:	debug flag; if non-zero, debug messages are printed.
134  *
135  *	The CCP options described by @options must match the options
136  *	specified when the compressor was allocated.  The compressor
137  *	history is reset.  Returns 0 for failure (CCP options don't
138  *	match) or 1 for success.
139  */
140 static int z_comp_init(void *arg, unsigned char *options, int opt_len,
141 		       int unit, int hdrlen, int debug)
142 {
143 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
144 
145 	if (opt_len < CILEN_DEFLATE ||
146 	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
147 	    options[1] != CILEN_DEFLATE ||
148 	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
149 	    DEFLATE_SIZE(options[2]) != state->w_size ||
150 	    options[3] != DEFLATE_CHK_SEQUENCE)
151 		return 0;
152 
153 	state->seqno = 0;
154 	state->unit  = unit;
155 	state->debug = debug;
156 
157 	zlib_deflateReset(&state->strm);
158 
159 	return 1;
160 }
161 
162 /**
163  *	z_comp_reset - reset a previously-allocated compressor.
164  *	@arg:	pointer to private state for the compressor.
165  *
166  *	This clears the history for the compressor and makes it
167  *	ready to start emitting a new compressed stream.
168  */
169 static void z_comp_reset(void *arg)
170 {
171 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
172 
173 	state->seqno = 0;
174 	zlib_deflateReset(&state->strm);
175 }
176 
177 /**
178  *	z_compress - compress a PPP packet with Deflate compression.
179  *	@arg:	pointer to private state for the compressor
180  *	@rptr:	uncompressed packet (input)
181  *	@obuf:	compressed packet (output)
182  *	@isize:	size of uncompressed packet
183  *	@osize:	space available at @obuf
184  *
185  *	Returns the length of the compressed packet, or 0 if the
186  *	packet is incompressible.
187  */
188 static int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf,
189 	       int isize, int osize)
190 {
191 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
192 	int r, proto, off, olen, oavail;
193 	unsigned char *wptr;
194 
195 	/*
196 	 * Check that the protocol is in the range we handle.
197 	 */
198 	proto = PPP_PROTOCOL(rptr);
199 	if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
200 		return 0;
201 
202 	/* Don't generate compressed packets which are larger than
203 	   the uncompressed packet. */
204 	if (osize > isize)
205 		osize = isize;
206 
207 	wptr = obuf;
208 
209 	/*
210 	 * Copy over the PPP header and store the 2-byte sequence number.
211 	 */
212 	wptr[0] = PPP_ADDRESS(rptr);
213 	wptr[1] = PPP_CONTROL(rptr);
214 	put_unaligned_be16(PPP_COMP, wptr + 2);
215 	wptr += PPP_HDRLEN;
216 	put_unaligned_be16(state->seqno, wptr);
217 	wptr += DEFLATE_OVHD;
218 	olen = PPP_HDRLEN + DEFLATE_OVHD;
219 	state->strm.next_out = wptr;
220 	state->strm.avail_out = oavail = osize - olen;
221 	++state->seqno;
222 
223 	off = (proto > 0xff) ? 2 : 3;	/* skip 1st proto byte if 0 */
224 	rptr += off;
225 	state->strm.next_in = rptr;
226 	state->strm.avail_in = (isize - off);
227 
228 	for (;;) {
229 		r = zlib_deflate(&state->strm, Z_PACKET_FLUSH);
230 		if (r != Z_OK) {
231 			if (state->debug)
232 				printk(KERN_ERR
233 				       "z_compress: deflate returned %d\n", r);
234 			break;
235 		}
236 		if (state->strm.avail_out == 0) {
237 			olen += oavail;
238 			state->strm.next_out = NULL;
239 			state->strm.avail_out = oavail = 1000000;
240 		} else {
241 			break;		/* all done */
242 		}
243 	}
244 	olen += oavail - state->strm.avail_out;
245 
246 	/*
247 	 * See if we managed to reduce the size of the packet.
248 	 */
249 	if (olen < isize && olen <= osize) {
250 		state->stats.comp_bytes += olen;
251 		state->stats.comp_packets++;
252 	} else {
253 		state->stats.inc_bytes += isize;
254 		state->stats.inc_packets++;
255 		olen = 0;
256 	}
257 	state->stats.unc_bytes += isize;
258 	state->stats.unc_packets++;
259 
260 	return olen;
261 }
262 
263 /**
264  *	z_comp_stats - return compression statistics for a compressor
265  *		or decompressor.
266  *	@arg:	pointer to private space for the (de)compressor
267  *	@stats:	pointer to a struct compstat to receive the result.
268  */
269 static void z_comp_stats(void *arg, struct compstat *stats)
270 {
271 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
272 
273 	*stats = state->stats;
274 }
275 
276 /**
277  *	z_decomp_free - Free the memory used by a decompressor.
278  *	@arg:	pointer to private space for the decompressor.
279  */
280 static void z_decomp_free(void *arg)
281 {
282 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
283 
284 	if (state) {
285 		zlib_inflateEnd(&state->strm);
286 		vfree(state->strm.workspace);
287 		kfree(state);
288 	}
289 }
290 
291 /**
292  *	z_decomp_alloc - allocate space for a decompressor.
293  *	@options: pointer to CCP option data
294  *	@opt_len: length of the CCP option at @options.
295  *
296  *	The @options pointer points to the a buffer containing the
297  *	CCP option data for the compression being negotiated.  It is
298  *	formatted according to RFC1979, and describes the window
299  *	size that we are requesting the peer to use in compressing
300  *	data to be sent to us.
301  *
302  *	Returns the pointer to the private state for the decompressor,
303  *	or NULL if we could not allocate enough memory.
304  */
305 static void *z_decomp_alloc(unsigned char *options, int opt_len)
306 {
307 	struct ppp_deflate_state *state;
308 	int w_size;
309 
310 	if (opt_len != CILEN_DEFLATE ||
311 	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
312 	    options[1] != CILEN_DEFLATE ||
313 	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
314 	    options[3] != DEFLATE_CHK_SEQUENCE)
315 		return NULL;
316 	w_size = DEFLATE_SIZE(options[2]);
317 	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
318 		return NULL;
319 
320 	state = kzalloc(sizeof(*state), GFP_KERNEL);
321 	if (state == NULL)
322 		return NULL;
323 
324 	state->w_size         = w_size;
325 	state->strm.next_out  = NULL;
326 	state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
327 	if (state->strm.workspace == NULL)
328 		goto out_free;
329 
330 	if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)
331 		goto out_free;
332 	return (void *) state;
333 
334 out_free:
335 	z_decomp_free(state);
336 	return NULL;
337 }
338 
339 /**
340  *	z_decomp_init - initialize a previously-allocated decompressor.
341  *	@arg:	pointer to the private state for the decompressor
342  *	@options: pointer to the CCP option data describing the
343  *		compression that was negotiated with the peer
344  *	@opt_len: length of the CCP option data at @options
345  *	@unit:	PPP unit number for diagnostic messages
346  *	@hdrlen: ignored (present for backwards compatibility)
347  *	@mru:	maximum length of decompressed packets
348  *	@debug:	debug flag; if non-zero, debug messages are printed.
349  *
350  *	The CCP options described by @options must match the options
351  *	specified when the decompressor was allocated.  The decompressor
352  *	history is reset.  Returns 0 for failure (CCP options don't
353  *	match) or 1 for success.
354  */
355 static int z_decomp_init(void *arg, unsigned char *options, int opt_len,
356 			 int unit, int hdrlen, int mru, int debug)
357 {
358 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
359 
360 	if (opt_len < CILEN_DEFLATE ||
361 	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
362 	    options[1] != CILEN_DEFLATE ||
363 	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
364 	    DEFLATE_SIZE(options[2]) != state->w_size ||
365 	    options[3] != DEFLATE_CHK_SEQUENCE)
366 		return 0;
367 
368 	state->seqno = 0;
369 	state->unit  = unit;
370 	state->debug = debug;
371 	state->mru   = mru;
372 
373 	zlib_inflateReset(&state->strm);
374 
375 	return 1;
376 }
377 
378 /**
379  *	z_decomp_reset - reset a previously-allocated decompressor.
380  *	@arg:	pointer to private state for the decompressor.
381  *
382  *	This clears the history for the decompressor and makes it
383  *	ready to receive a new compressed stream.
384  */
385 static void z_decomp_reset(void *arg)
386 {
387 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
388 
389 	state->seqno = 0;
390 	zlib_inflateReset(&state->strm);
391 }
392 
393 /**
394  *	z_decompress - decompress a Deflate-compressed packet.
395  *	@arg:	pointer to private state for the decompressor
396  *	@ibuf:	pointer to input (compressed) packet data
397  *	@isize:	length of input packet
398  *	@obuf:	pointer to space for output (decompressed) packet
399  *	@osize:	amount of space available at @obuf
400  *
401  * Because of patent problems, we return DECOMP_ERROR for errors
402  * found by inspecting the input data and for system problems, but
403  * DECOMP_FATALERROR for any errors which could possibly be said to
404  * be being detected "after" decompression.  For DECOMP_ERROR,
405  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
406  * infringing a patent of Motorola's if we do, so we take CCP down
407  * instead.
408  *
409  * Given that the frame has the correct sequence number and a good FCS,
410  * errors such as invalid codes in the input most likely indicate a
411  * bug, so we return DECOMP_FATALERROR for them in order to turn off
412  * compression, even though they are detected by inspecting the input.
413  */
414 static int z_decompress(void *arg, unsigned char *ibuf, int isize,
415 		 unsigned char *obuf, int osize)
416 {
417 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
418 	int olen, seq, r;
419 	int decode_proto, overflow;
420 	unsigned char overflow_buf[1];
421 
422 	if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {
423 		if (state->debug)
424 			printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
425 			       state->unit, isize);
426 		return DECOMP_ERROR;
427 	}
428 
429 	/* Check the sequence number. */
430 	seq = get_unaligned_be16(ibuf + PPP_HDRLEN);
431 	if (seq != (state->seqno & 0xffff)) {
432 		if (state->debug)
433 			printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
434 			       state->unit, seq, state->seqno & 0xffff);
435 		return DECOMP_ERROR;
436 	}
437 	++state->seqno;
438 
439 	/*
440 	 * Fill in the first part of the PPP header.  The protocol field
441 	 * comes from the decompressed data.
442 	 */
443 	obuf[0] = PPP_ADDRESS(ibuf);
444 	obuf[1] = PPP_CONTROL(ibuf);
445 	obuf[2] = 0;
446 
447 	/*
448 	 * Set up to call inflate.  We set avail_out to 1 initially so we can
449 	 * look at the first byte of the output and decide whether we have
450 	 * a 1-byte or 2-byte protocol field.
451 	 */
452 	state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;
453 	state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);
454 	state->strm.next_out = obuf + 3;
455 	state->strm.avail_out = 1;
456 	decode_proto = 1;
457 	overflow = 0;
458 
459 	/*
460 	 * Call inflate, supplying more input or output as needed.
461 	 */
462 	for (;;) {
463 		r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);
464 		if (r != Z_OK) {
465 			if (state->debug)
466 				printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
467 				       state->unit, r, (state->strm.msg? state->strm.msg: ""));
468 			return DECOMP_FATALERROR;
469 		}
470 		if (state->strm.avail_out != 0)
471 			break;		/* all done */
472 		if (decode_proto) {
473 			state->strm.avail_out = osize - PPP_HDRLEN;
474 			if ((obuf[3] & 1) == 0) {
475 				/* 2-byte protocol field */
476 				obuf[2] = obuf[3];
477 				--state->strm.next_out;
478 				++state->strm.avail_out;
479 			}
480 			decode_proto = 0;
481 		} else if (!overflow) {
482 			/*
483 			 * We've filled up the output buffer; the only way to
484 			 * find out whether inflate has any more characters
485 			 * left is to give it another byte of output space.
486 			 */
487 			state->strm.next_out = overflow_buf;
488 			state->strm.avail_out = 1;
489 			overflow = 1;
490 		} else {
491 			if (state->debug)
492 				printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
493 				       state->unit);
494 			return DECOMP_FATALERROR;
495 		}
496 	}
497 
498 	if (decode_proto) {
499 		if (state->debug)
500 			printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
501 			       state->unit);
502 		return DECOMP_ERROR;
503 	}
504 
505 	olen = osize + overflow - state->strm.avail_out;
506 	state->stats.unc_bytes += olen;
507 	state->stats.unc_packets++;
508 	state->stats.comp_bytes += isize;
509 	state->stats.comp_packets++;
510 
511 	return olen;
512 }
513 
514 /**
515  *	z_incomp - add incompressible input data to the history.
516  *	@arg:	pointer to private state for the decompressor
517  *	@ibuf:	pointer to input packet data
518  *	@icnt:	length of input data.
519  */
520 static void z_incomp(void *arg, unsigned char *ibuf, int icnt)
521 {
522 	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
523 	int proto, r;
524 
525 	/*
526 	 * Check that the protocol is one we handle.
527 	 */
528 	proto = PPP_PROTOCOL(ibuf);
529 	if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
530 		return;
531 
532 	++state->seqno;
533 
534 	/*
535 	 * We start at the either the 1st or 2nd byte of the protocol field,
536 	 * depending on whether the protocol value is compressible.
537 	 */
538 	state->strm.next_in = ibuf + 3;
539 	state->strm.avail_in = icnt - 3;
540 	if (proto > 0xff) {
541 		--state->strm.next_in;
542 		++state->strm.avail_in;
543 	}
544 
545 	r = zlib_inflateIncomp(&state->strm);
546 	if (r != Z_OK) {
547 		/* gak! */
548 		if (state->debug) {
549 			printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
550 			       state->unit, r, (state->strm.msg? state->strm.msg: ""));
551 		}
552 		return;
553 	}
554 
555 	/*
556 	 * Update stats.
557 	 */
558 	state->stats.inc_bytes += icnt;
559 	state->stats.inc_packets++;
560 	state->stats.unc_bytes += icnt;
561 	state->stats.unc_packets++;
562 }
563 
564 /*************************************************************
565  * Module interface table
566  *************************************************************/
567 
568 /* These are in ppp_generic.c */
569 extern int  ppp_register_compressor   (struct compressor *cp);
570 extern void ppp_unregister_compressor (struct compressor *cp);
571 
572 /*
573  * Procedures exported to if_ppp.c.
574  */
575 static struct compressor ppp_deflate = {
576 	.compress_proto =	CI_DEFLATE,
577 	.comp_alloc =		z_comp_alloc,
578 	.comp_free =		z_comp_free,
579 	.comp_init =		z_comp_init,
580 	.comp_reset =		z_comp_reset,
581 	.compress =		z_compress,
582 	.comp_stat =		z_comp_stats,
583 	.decomp_alloc =		z_decomp_alloc,
584 	.decomp_free =		z_decomp_free,
585 	.decomp_init =		z_decomp_init,
586 	.decomp_reset =		z_decomp_reset,
587 	.decompress =		z_decompress,
588 	.incomp =		z_incomp,
589 	.decomp_stat =		z_comp_stats,
590 	.owner =		THIS_MODULE
591 };
592 
593 static struct compressor ppp_deflate_draft = {
594 	.compress_proto =	CI_DEFLATE_DRAFT,
595 	.comp_alloc =		z_comp_alloc,
596 	.comp_free =		z_comp_free,
597 	.comp_init =		z_comp_init,
598 	.comp_reset =		z_comp_reset,
599 	.compress =		z_compress,
600 	.comp_stat =		z_comp_stats,
601 	.decomp_alloc =		z_decomp_alloc,
602 	.decomp_free =		z_decomp_free,
603 	.decomp_init =		z_decomp_init,
604 	.decomp_reset =		z_decomp_reset,
605 	.decompress =		z_decompress,
606 	.incomp =		z_incomp,
607 	.decomp_stat =		z_comp_stats,
608 	.owner =		THIS_MODULE
609 };
610 
611 static int __init deflate_init(void)
612 {
613 	int rc;
614 
615 	rc = ppp_register_compressor(&ppp_deflate);
616 	if (rc)
617 		return rc;
618 
619 	rc = ppp_register_compressor(&ppp_deflate_draft);
620 	if (rc) {
621 		ppp_unregister_compressor(&ppp_deflate);
622 		return rc;
623 	}
624 
625 	pr_info("PPP Deflate Compression module registered\n");
626 	return 0;
627 }
628 
629 static void __exit deflate_cleanup(void)
630 {
631 	ppp_unregister_compressor(&ppp_deflate);
632 	ppp_unregister_compressor(&ppp_deflate_draft);
633 }
634 
635 module_init(deflate_init);
636 module_exit(deflate_cleanup);
637 MODULE_LICENSE("Dual BSD/GPL");
638 MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
639 MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
640