Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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