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