111499Sjkh// SPDX-License-Identifier: GPL-2.0-only
211499Sjkh/*
311499Sjkh * ppp_deflate.c - interface the zlib procedures for Deflate compression
411499Sjkh * and decompression (as used by gzip) to the PPP code.
511499Sjkh *
611499Sjkh * Copyright 1994-1998 Paul Mackerras.
750479Speter */
811499Sjkh
911499Sjkh#include <linux/module.h>
1011499Sjkh#include <linux/slab.h>
1111499Sjkh#include <linux/vmalloc.h>
1211499Sjkh#include <linux/init.h>
1311499Sjkh#include <linux/string.h>
1411499Sjkh
1511499Sjkh#include <linux/ppp_defs.h>
1611499Sjkh#include <linux/ppp-comp.h>
1711499Sjkh
1811499Sjkh#include <linux/zlib.h>
1911499Sjkh#include <asm/unaligned.h>
2011499Sjkh
2111499Sjkh/*
2211499Sjkh * State for a Deflate (de)compressor.
2311499Sjkh */
2411499Sjkhstruct ppp_deflate_state {
2511499Sjkh    int		seqno;
2611499Sjkh    int		w_size;
2711499Sjkh    int		unit;
2811499Sjkh    int		mru;
2911499Sjkh    int		debug;
3011499Sjkh    z_stream	strm;
3111499Sjkh    struct compstat stats;
3211499Sjkh};
3311499Sjkh
3411499Sjkh#define DEFLATE_OVHD	2		/* Deflate overhead/packet */
3511499Sjkh
3611499Sjkhstatic void	*z_comp_alloc(unsigned char *options, int opt_len);
3711532Sjkhstatic void	*z_decomp_alloc(unsigned char *options, int opt_len);
3811303Sjkhstatic void	z_comp_free(void *state);
3911303Sjkhstatic void	z_decomp_free(void *state);
4011303Sjkhstatic int	z_comp_init(void *state, unsigned char *options,
4111303Sjkh				 int opt_len,
4211303Sjkh				 int unit, int hdrlen, int debug);
4311303Sjkhstatic int	z_decomp_init(void *state, unsigned char *options,
4411303Sjkh				   int opt_len,
4511303Sjkh				   int unit, int hdrlen, int mru, int debug);
4616366Sjkhstatic int	z_compress(void *state, unsigned char *rptr,
4717377Sjkh				unsigned char *obuf,
4811303Sjkh				int isize, int osize);
4943534Sjkhstatic void	z_incomp(void *state, unsigned char *ibuf, int icnt);
5043534Sjkhstatic int	z_decompress(void *state, unsigned char *ibuf,
5143534Sjkh				int isize, unsigned char *obuf, int osize);
5243534Sjkhstatic void	z_comp_reset(void *state);
5343534Sjkhstatic void	z_decomp_reset(void *state);
5443534Sjkhstatic void	z_comp_stats(void *state, struct compstat *stats);
5543534Sjkh
5643534Sjkh/**
5743534Sjkh *	z_comp_free - free the memory used by a compressor
5843534Sjkh *	@arg:	pointer to the private state for the compressor.
5914670Sjkh */
6047055Sjkhstatic void z_comp_free(void *arg)
6147055Sjkh{
6247055Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
6311303Sjkh
6411303Sjkh	if (state) {
6511303Sjkh		zlib_deflateEnd(&state->strm);
6611303Sjkh		vfree(state->strm.workspace);
6711593Sjkh		kfree(state);
6811303Sjkh	}
6911303Sjkh}
7011303Sjkh
7124235Sjkh/**
7224235Sjkh *	z_comp_alloc - allocate space for a compressor.
7347221Sjkh *	@options: pointer to CCP option data
7424235Sjkh *	@opt_len: length of the CCP option at @options.
7524235Sjkh *
7647179Sjkh *	The @options pointer points to the a buffer containing the
7711479Sjkh *	CCP option data for the compression being negotiated.  It is
7812245Sjkh *	formatted according to RFC1979, and describes the window
7912245Sjkh *	size that the peer is requesting that we use in compressing
8011303Sjkh *	data to be sent to it.
8142520Sasami *
8211303Sjkh *	Returns the pointer to the private state for the compressor,
8321132Sobrien *	or NULL if we could not allocate enough memory.
8411303Sjkh */
8511303Sjkhstatic void *z_comp_alloc(unsigned char *options, int opt_len)
8641752Ssteve{
8711303Sjkh	struct ppp_deflate_state *state;
8811303Sjkh	int w_size;
8921132Sobrien
9011303Sjkh	if (opt_len != CILEN_DEFLATE ||
9141752Ssteve	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
9211303Sjkh	    options[1] != CILEN_DEFLATE ||
9311303Sjkh	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
9440281Sjkh	    options[3] != DEFLATE_CHK_SEQUENCE)
9511303Sjkh		return NULL;
9611303Sjkh	w_size = DEFLATE_SIZE(options[2]);
9742005Sjkh	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
9842520Sasami		return NULL;
9911303Sjkh
10053020Sjkh	state = kzalloc(sizeof(*state),
10111303Sjkh						     GFP_KERNEL);
10234792Sjkh	if (state == NULL)
10311303Sjkh		return NULL;
10444047Sjkh
10550780Sjkh	state->strm.next_in   = NULL;
10611303Sjkh	state->w_size         = w_size;
10750780Sjkh	state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
10834867Sjkh	if (state->strm.workspace == NULL)
10924235Sjkh		goto out_free;
11011303Sjkh
11111303Sjkh	if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
11211303Sjkh			 DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
11311303Sjkh	    != Z_OK)
11411303Sjkh		goto out_free;
11541752Ssteve	return (void *) state;
11614670Sjkh
11711303Sjkhout_free:
11811303Sjkh	z_comp_free(state);
11911303Sjkh	return NULL;
12039595Sjkh}
12111303Sjkh
12243536Sjkh/**
12343536Sjkh *	z_comp_init - initialize a previously-allocated compressor.
12441752Ssteve *	@arg:	pointer to the private state for the compressor
12541752Ssteve *	@options: pointer to the CCP option data describing the
12611303Sjkh *		compression that was negotiated with the peer
12711303Sjkh *	@opt_len: length of the CCP option data at @options
12811303Sjkh *	@unit:	PPP unit number for diagnostic messages
12941752Ssteve *	@hdrlen: ignored (present for backwards compatibility)
13011303Sjkh *	@debug:	debug flag; if non-zero, debug messages are printed.
13111303Sjkh *
13211303Sjkh *	The CCP options described by @options must match the options
13311303Sjkh *	specified when the compressor was allocated.  The compressor
13425481Sjkh *	history is reset.  Returns 0 for failure (CCP options don't
13541752Ssteve *	match) or 1 for success.
13641752Ssteve */
13741752Sstevestatic int z_comp_init(void *arg, unsigned char *options, int opt_len,
13853020Sjkh		       int unit, int hdrlen, int debug)
13953020Sjkh{
14041752Ssteve	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
14141752Ssteve
14241752Ssteve	if (opt_len < CILEN_DEFLATE ||
14341752Ssteve	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
14453020Sjkh	    options[1] != CILEN_DEFLATE ||
14553020Sjkh	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
14641752Ssteve	    DEFLATE_SIZE(options[2]) != state->w_size ||
14721132Sobrien	    options[3] != DEFLATE_CHK_SEQUENCE)
14842520Sasami		return 0;
14925481Sjkh
15011303Sjkh	state->seqno = 0;
15140281Sjkh	state->unit  = unit;
15240281Sjkh	state->debug = debug;
15342520Sasami
15450780Sjkh	zlib_deflateReset(&state->strm);
15540281Sjkh
15641752Ssteve	return 1;
15711303Sjkh}
15811303Sjkh
15911303Sjkh/**
16011303Sjkh *	z_comp_reset - reset a previously-allocated compressor.
16111303Sjkh *	@arg:	pointer to private state for the compressor.
16211303Sjkh *
16311303Sjkh *	This clears the history for the compressor and makes it
16411303Sjkh *	ready to start emitting a new compressed stream.
16511303Sjkh */
16611303Sjkhstatic void z_comp_reset(void *arg)
16711303Sjkh{
16811303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
16911303Sjkh
17011303Sjkh	state->seqno = 0;
17111303Sjkh	zlib_deflateReset(&state->strm);
17211303Sjkh}
17311303Sjkh
17411303Sjkh/**
17511579Sjkh *	z_compress - compress a PPP packet with Deflate compression.
17611303Sjkh *	@arg:	pointer to private state for the compressor
17711303Sjkh *	@rptr:	uncompressed packet (input)
17811303Sjkh *	@obuf:	compressed packet (output)
17911303Sjkh *	@isize:	size of uncompressed packet
18011303Sjkh *	@osize:	space available at @obuf
18111303Sjkh *
18216688Sjkh *	Returns the length of the compressed packet, or 0 if the
18316688Sjkh *	packet is incompressible.
18416688Sjkh */
18516688Sjkhstatic int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf,
18616688Sjkh	       int isize, int osize)
18716688Sjkh{
18816688Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
18916688Sjkh	int r, proto, off, olen, oavail;
19016688Sjkh	unsigned char *wptr;
19116688Sjkh
19216688Sjkh	/*
19311303Sjkh	 * Check that the protocol is in the range we handle.
19414670Sjkh	 */
19511303Sjkh	proto = PPP_PROTOCOL(rptr);
19611579Sjkh	if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
19711303Sjkh		return 0;
19811303Sjkh
19911303Sjkh	/* Don't generate compressed packets which are larger than
20011303Sjkh	   the uncompressed packet. */
20111303Sjkh	if (osize > isize)
20216688Sjkh		osize = isize;
20311303Sjkh
20414670Sjkh	wptr = obuf;
20543534Sjkh
20643534Sjkh	/*
20711303Sjkh	 * Copy over the PPP header and store the 2-byte sequence number.
20811303Sjkh	 */
20911303Sjkh	wptr[0] = PPP_ADDRESS(rptr);
21011303Sjkh	wptr[1] = PPP_CONTROL(rptr);
21111303Sjkh	put_unaligned_be16(PPP_COMP, wptr + 2);
21211303Sjkh	wptr += PPP_HDRLEN;
21311303Sjkh	put_unaligned_be16(state->seqno, wptr);
21411303Sjkh	wptr += DEFLATE_OVHD;
21511593Sjkh	olen = PPP_HDRLEN + DEFLATE_OVHD;
21611303Sjkh	state->strm.next_out = wptr;
21711303Sjkh	state->strm.avail_out = oavail = osize - olen;
21811303Sjkh	++state->seqno;
21911303Sjkh
22011303Sjkh	off = (proto > 0xff) ? 2 : 3;	/* skip 1st proto byte if 0 */
22111303Sjkh	rptr += off;
22211303Sjkh	state->strm.next_in = rptr;
22311303Sjkh	state->strm.avail_in = (isize - off);
22411303Sjkh
22511303Sjkh	for (;;) {
22611303Sjkh		r = zlib_deflate(&state->strm, Z_PACKET_FLUSH);
22711303Sjkh		if (r != Z_OK) {
22811303Sjkh			if (state->debug)
22911528Sjkh				printk(KERN_ERR
23011303Sjkh				       "z_compress: deflate returned %d\n", r);
23111303Sjkh			break;
23211303Sjkh		}
23311303Sjkh		if (state->strm.avail_out == 0) {
23411303Sjkh			olen += oavail;
23511303Sjkh			state->strm.next_out = NULL;
23611303Sjkh			state->strm.avail_out = oavail = 1000000;
23711303Sjkh		} else {
23811303Sjkh			break;		/* all done */
23911303Sjkh		}
24011303Sjkh	}
24111303Sjkh	olen += oavail - state->strm.avail_out;
24211303Sjkh
24311303Sjkh	/*
24411303Sjkh	 * See if we managed to reduce the size of the packet.
24511303Sjkh	 */
24611303Sjkh	if (olen < isize && olen <= osize) {
24711303Sjkh		state->stats.comp_bytes += olen;
24811303Sjkh		state->stats.comp_packets++;
24911303Sjkh	} else {
25011532Sjkh		state->stats.inc_bytes += isize;
25120315Sjkh		state->stats.inc_packets++;
25211532Sjkh		olen = 0;
25311532Sjkh	}
25411532Sjkh	state->stats.unc_bytes += isize;
25511532Sjkh	state->stats.unc_packets++;
25620315Sjkh
25711532Sjkh	return olen;
25811532Sjkh}
25911532Sjkh
26011532Sjkh/**
26111532Sjkh *	z_comp_stats - return compression statistics for a compressor
26211532Sjkh *		or decompressor.
26311303Sjkh *	@arg:	pointer to private space for the (de)compressor
26424364Sjkh *	@stats:	pointer to a struct compstat to receive the result.
26511303Sjkh */
26611303Sjkhstatic void z_comp_stats(void *arg, struct compstat *stats)
26724364Sjkh{
26811303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
26911532Sjkh
27011303Sjkh	*stats = state->stats;
27120315Sjkh}
27211532Sjkh
27311532Sjkh/**
27411303Sjkh *	z_decomp_free - Free the memory used by a decompressor.
27511303Sjkh *	@arg:	pointer to private space for the decompressor.
27611303Sjkh */
27711303Sjkhstatic void z_decomp_free(void *arg)
27811303Sjkh{
27911303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
28011303Sjkh
28111303Sjkh	if (state) {
28224364Sjkh		vfree(state->strm.workspace);
28324645Sjkh		kfree(state);
28424645Sjkh	}
28524645Sjkh}
28624645Sjkh
28711303Sjkh/**
28811303Sjkh *	z_decomp_alloc - allocate space for a decompressor.
28911303Sjkh *	@options: pointer to CCP option data
29011303Sjkh *	@opt_len: length of the CCP option at @options.
29120315Sjkh *
29211303Sjkh *	The @options pointer points to the a buffer containing the
29314670Sjkh *	CCP option data for the compression being negotiated.  It is
29443534Sjkh *	formatted according to RFC1979, and describes the window
29511303Sjkh *	size that we are requesting the peer to use in compressing
29620315Sjkh *	data to be sent to us.
29711303Sjkh *
29811303Sjkh *	Returns the pointer to the private state for the decompressor,
29911303Sjkh *	or NULL if we could not allocate enough memory.
30014670Sjkh */
30111303Sjkhstatic void *z_decomp_alloc(unsigned char *options, int opt_len)
30211593Sjkh{
30311303Sjkh	struct ppp_deflate_state *state;
30411303Sjkh	int w_size;
30511303Sjkh
30611303Sjkh	if (opt_len != CILEN_DEFLATE ||
30711303Sjkh	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
30811303Sjkh	    options[1] != CILEN_DEFLATE ||
30911303Sjkh	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
31011303Sjkh	    options[3] != DEFLATE_CHK_SEQUENCE)
31143534Sjkh		return NULL;
31243534Sjkh	w_size = DEFLATE_SIZE(options[2]);
31343534Sjkh	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
31443534Sjkh		return NULL;
31543534Sjkh
31643534Sjkh	state = kzalloc(sizeof(*state), GFP_KERNEL);
31743534Sjkh	if (state == NULL)
31843534Sjkh		return NULL;
31943534Sjkh
32011303Sjkh	state->w_size         = w_size;
32111303Sjkh	state->strm.next_out  = NULL;
32211303Sjkh	state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
32311303Sjkh	if (state->strm.workspace == NULL)
32411303Sjkh		goto out_free;
32511303Sjkh
32614738Sjkh	if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)
32714738Sjkh		goto out_free;
32814738Sjkh	return (void *) state;
32914738Sjkh
33014738Sjkhout_free:
33114738Sjkh	z_decomp_free(state);
33211303Sjkh	return NULL;
33314738Sjkh}
33414738Sjkh
33514738Sjkh/**
33614738Sjkh *	z_decomp_init - initialize a previously-allocated decompressor.
33714738Sjkh *	@arg:	pointer to the private state for the decompressor
33814738Sjkh *	@options: pointer to the CCP option data describing the
33911303Sjkh *		compression that was negotiated with the peer
34011303Sjkh *	@opt_len: length of the CCP option data at @options
34114738Sjkh *	@unit:	PPP unit number for diagnostic messages
34211303Sjkh *	@hdrlen: ignored (present for backwards compatibility)
34311303Sjkh *	@mru:	maximum length of decompressed packets
34411303Sjkh *	@debug:	debug flag; if non-zero, debug messages are printed.
34511303Sjkh *
34611303Sjkh *	The CCP options described by @options must match the options
34711303Sjkh *	specified when the decompressor was allocated.  The decompressor
34811303Sjkh *	history is reset.  Returns 0 for failure (CCP options don't
34911303Sjkh *	match) or 1 for success.
35011303Sjkh */
35111303Sjkhstatic int z_decomp_init(void *arg, unsigned char *options, int opt_len,
35211303Sjkh			 int unit, int hdrlen, int mru, int debug)
35311303Sjkh{
35411303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
35511303Sjkh
35611303Sjkh	if (opt_len < CILEN_DEFLATE ||
35711303Sjkh	    (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
35811303Sjkh	    options[1] != CILEN_DEFLATE ||
35911303Sjkh	    DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
36011303Sjkh	    DEFLATE_SIZE(options[2]) != state->w_size ||
36111303Sjkh	    options[3] != DEFLATE_CHK_SEQUENCE)
36211303Sjkh		return 0;
36311303Sjkh
36411303Sjkh	state->seqno = 0;
36511303Sjkh	state->unit  = unit;
36611303Sjkh	state->debug = debug;
36711303Sjkh	state->mru   = mru;
36811303Sjkh
36911303Sjkh	zlib_inflateReset(&state->strm);
37011303Sjkh
37111303Sjkh	return 1;
37211303Sjkh}
37311303Sjkh
37411303Sjkh/**
37511303Sjkh *	z_decomp_reset - reset a previously-allocated decompressor.
37611303Sjkh *	@arg:	pointer to private state for the decompressor.
37711303Sjkh *
37811593Sjkh *	This clears the history for the decompressor and makes it
37911593Sjkh *	ready to receive a new compressed stream.
38011303Sjkh */
38111303Sjkhstatic void z_decomp_reset(void *arg)
38211303Sjkh{
38311303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
38411303Sjkh
38547221Sjkh	state->seqno = 0;
38611593Sjkh	zlib_inflateReset(&state->strm);
38711303Sjkh}
38811303Sjkh
38911303Sjkh/**
39011303Sjkh *	z_decompress - decompress a Deflate-compressed packet.
39111303Sjkh *	@arg:	pointer to private state for the decompressor
39215788Sjkh *	@ibuf:	pointer to input (compressed) packet data
39311303Sjkh *	@isize:	length of input packet
39411303Sjkh *	@obuf:	pointer to space for output (decompressed) packet
39511303Sjkh *	@osize:	amount of space available at @obuf
39615788Sjkh *
39715788Sjkh * Because of patent problems, we return DECOMP_ERROR for errors
39815788Sjkh * found by inspecting the input data and for system problems, but
39911303Sjkh * DECOMP_FATALERROR for any errors which could possibly be said to
40015788Sjkh * be being detected "after" decompression.  For DECOMP_ERROR,
40115788Sjkh * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
40211303Sjkh * infringing a patent of Motorola's if we do, so we take CCP down
40311303Sjkh * instead.
40411303Sjkh *
40511303Sjkh * Given that the frame has the correct sequence number and a good FCS,
40615242Sjkh * errors such as invalid codes in the input most likely indicate a
40715242Sjkh * bug, so we return DECOMP_FATALERROR for them in order to turn off
40815242Sjkh * compression, even though they are detected by inspecting the input.
40915242Sjkh */
41011303Sjkhstatic int z_decompress(void *arg, unsigned char *ibuf, int isize,
41111303Sjkh		 unsigned char *obuf, int osize)
41211303Sjkh{
41311303Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
41411303Sjkh	int olen, seq, r;
41511303Sjkh	int decode_proto, overflow;
41647221Sjkh	unsigned char overflow_buf[1];
41747221Sjkh
41847221Sjkh	if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {
41947221Sjkh		if (state->debug)
42011303Sjkh			printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
42147221Sjkh			       state->unit, isize);
42247221Sjkh		return DECOMP_ERROR;
42347221Sjkh	}
42447221Sjkh
42547221Sjkh	/* Check the sequence number. */
42611303Sjkh	seq = get_unaligned_be16(ibuf + PPP_HDRLEN);
42747221Sjkh	if (seq != (state->seqno & 0xffff)) {
42847221Sjkh		if (state->debug)
42911303Sjkh			printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
43011303Sjkh			       state->unit, seq, state->seqno & 0xffff);
43147221Sjkh		return DECOMP_ERROR;
43211303Sjkh	}
43311303Sjkh	++state->seqno;
43411303Sjkh
43511303Sjkh	/*
43611303Sjkh	 * Fill in the first part of the PPP header.  The protocol field
43711303Sjkh	 * comes from the decompressed data.
43815242Sjkh	 */
43915242Sjkh	obuf[0] = PPP_ADDRESS(ibuf);
44011479Sjkh	obuf[1] = PPP_CONTROL(ibuf);
44143534Sjkh	obuf[2] = 0;
44243534Sjkh
44316204Sjkh	/*
44411520Sjkh	 * Set up to call inflate.  We set avail_out to 1 initially so we can
44516204Sjkh	 * look at the first byte of the output and decide whether we have
44643534Sjkh	 * a 1-byte or 2-byte protocol field.
44743534Sjkh	 */
44843534Sjkh	state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;
44943534Sjkh	state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);
45043534Sjkh	state->strm.next_out = obuf + 3;
45143534Sjkh	state->strm.avail_out = 1;
45243534Sjkh	decode_proto = 1;
45343534Sjkh	overflow = 0;
45443534Sjkh
45515242Sjkh	/*
45615242Sjkh	 * Call inflate, supplying more input or output as needed.
45711479Sjkh	 */
45815242Sjkh	for (;;) {
45915242Sjkh		r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);
46015242Sjkh		if (r != Z_OK) {
46115477Sjkh			if (state->debug)
46243534Sjkh				printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
46343534Sjkh				       state->unit, r, (state->strm.msg? state->strm.msg: ""));
46415242Sjkh			return DECOMP_FATALERROR;
46515242Sjkh		}
46615477Sjkh		if (state->strm.avail_out != 0)
46715477Sjkh			break;		/* all done */
46843534Sjkh		if (decode_proto) {
46943534Sjkh			state->strm.avail_out = osize - PPP_HDRLEN;
47015242Sjkh			if ((obuf[3] & 1) == 0) {
47115242Sjkh				/* 2-byte protocol field */
47215242Sjkh				obuf[2] = obuf[3];
47343534Sjkh				--state->strm.next_out;
47416204Sjkh				++state->strm.avail_out;
47515242Sjkh			}
47616204Sjkh			decode_proto = 0;
47716204Sjkh		} else if (!overflow) {
47816204Sjkh			/*
47943534Sjkh			 * We've filled up the output buffer; the only way to
48016204Sjkh			 * find out whether inflate has any more characters
48116204Sjkh			 * left is to give it another byte of output space.
48243534Sjkh			 */
48322105Sjkh			state->strm.next_out = overflow_buf;
48422105Sjkh			state->strm.avail_out = 1;
48545371Sjkh			overflow = 1;
48645371Sjkh		} else {
48722105Sjkh			if (state->debug)
48845371Sjkh				printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
48943534Sjkh				       state->unit);
49043534Sjkh			return DECOMP_FATALERROR;
49143534Sjkh		}
49243534Sjkh	}
49345371Sjkh
49422105Sjkh	if (decode_proto) {
49522105Sjkh		if (state->debug)
49643534Sjkh			printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
49743534Sjkh			       state->unit);
49843534Sjkh		return DECOMP_ERROR;
49911520Sjkh	}
50022102Sjkh
50143534Sjkh	olen = osize + overflow - state->strm.avail_out;
50215468Sjkh	state->stats.unc_bytes += olen;
50315242Sjkh	state->stats.unc_packets++;
50411520Sjkh	state->stats.comp_bytes += isize;
50515477Sjkh	state->stats.comp_packets++;
50643534Sjkh
50743534Sjkh	return olen;
50843534Sjkh}
50911479Sjkh
51015242Sjkh/**
51115242Sjkh *	z_incomp - add incompressible input data to the history.
51215242Sjkh *	@arg:	pointer to private state for the decompressor
51315242Sjkh *	@ibuf:	pointer to input packet data
51443534Sjkh *	@icnt:	length of input data.
51515477Sjkh */
51615242Sjkhstatic void z_incomp(void *arg, unsigned char *ibuf, int icnt)
51715477Sjkh{
51811479Sjkh	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
51911479Sjkh	int proto, r;
52015242Sjkh
52115242Sjkh	/*
52215242Sjkh	 * Check that the protocol is one we handle.
52316688Sjkh	 */
52416688Sjkh	proto = PPP_PROTOCOL(ibuf);
52516688Sjkh	if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
52616688Sjkh		return;
52716688Sjkh
52815242Sjkh	++state->seqno;
52915242Sjkh
53011303Sjkh	/*
53143534Sjkh	 * We start at the either the 1st or 2nd byte of the protocol field,
53211303Sjkh	 * depending on whether the protocol value is compressible.
53343534Sjkh	 */
53411593Sjkh	state->strm.next_in = ibuf + 3;
53511303Sjkh	state->strm.avail_in = icnt - 3;
53615242Sjkh	if (proto > 0xff) {
53715242Sjkh		--state->strm.next_in;
53811479Sjkh		++state->strm.avail_in;
53915355Sjkh	}
54011303Sjkh
54143534Sjkh	r = zlib_inflateIncomp(&state->strm);
54243534Sjkh	if (r != Z_OK) {
54343534Sjkh		/* gak! */
54443534Sjkh		if (state->debug) {
54511479Sjkh			printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
54611479Sjkh			       state->unit, r, (state->strm.msg? state->strm.msg: ""));
54711479Sjkh		}
54815355Sjkh		return;
54911593Sjkh	}
55011479Sjkh
55111593Sjkh	/*
55211593Sjkh	 * Update stats.
55316688Sjkh	 */
55411303Sjkh	state->stats.inc_bytes += icnt;
55511593Sjkh	state->stats.inc_packets++;
55611479Sjkh	state->stats.unc_bytes += icnt;
55711593Sjkh	state->stats.unc_packets++;
55811593Sjkh}
55911479Sjkh
56011303Sjkh/*************************************************************
56111593Sjkh * Module interface table
56211303Sjkh *************************************************************/
56315355Sjkh
56415242Sjkh/* These are in ppp_generic.c */
56511303Sjkhextern int  ppp_register_compressor   (struct compressor *cp);
56611479Sjkhextern void ppp_unregister_compressor (struct compressor *cp);
56711303Sjkh
56811479Sjkh/*
56912129Sjkh * Procedures exported to if_ppp.c.
57024235Sjkh */
57124235Sjkhstatic struct compressor ppp_deflate = {
57211479Sjkh	.compress_proto =	CI_DEFLATE,
57324235Sjkh	.comp_alloc =		z_comp_alloc,
57424311Sjkh	.comp_free =		z_comp_free,
57524311Sjkh	.comp_init =		z_comp_init,
57624235Sjkh	.comp_reset =		z_comp_reset,
57711479Sjkh	.compress =		z_compress,
57815242Sjkh	.comp_stat =		z_comp_stats,
57924235Sjkh	.decomp_alloc =		z_decomp_alloc,
58015242Sjkh	.decomp_free =		z_decomp_free,
58111593Sjkh	.decomp_init =		z_decomp_init,
58224235Sjkh	.decomp_reset =		z_decomp_reset,
58324235Sjkh	.decompress =		z_decompress,
58424235Sjkh	.incomp =		z_incomp,
58524235Sjkh	.decomp_stat =		z_comp_stats,
58615242Sjkh	.owner =		THIS_MODULE
58715242Sjkh};
58843534Sjkh
58911479Sjkhstatic struct compressor ppp_deflate_draft = {
59011479Sjkh	.compress_proto =	CI_DEFLATE_DRAFT,
59111479Sjkh	.comp_alloc =		z_comp_alloc,
59215242Sjkh	.comp_free =		z_comp_free,
59315242Sjkh	.comp_init =		z_comp_init,
59411479Sjkh	.comp_reset =		z_comp_reset,
59516366Sjkh	.compress =		z_compress,
59617404Sjkh	.comp_stat =		z_comp_stats,
59711479Sjkh	.decomp_alloc =		z_decomp_alloc,
59815242Sjkh	.decomp_free =		z_decomp_free,
59924235Sjkh	.decomp_init =		z_decomp_init,
60024235Sjkh	.decomp_reset =		z_decomp_reset,
60115242Sjkh	.decompress =		z_decompress,
60211303Sjkh	.incomp =		z_incomp,
60311303Sjkh	.decomp_stat =		z_comp_stats,
60411303Sjkh	.owner =		THIS_MODULE
60511303Sjkh};
60611303Sjkh
60711303Sjkhstatic int __init deflate_init(void)
60811303Sjkh{
60911303Sjkh	int rc;
61011303Sjkh
61111303Sjkh	rc = ppp_register_compressor(&ppp_deflate);
61211303Sjkh	if (rc)
61311303Sjkh		return rc;
61443534Sjkh
61511303Sjkh	rc = ppp_register_compressor(&ppp_deflate_draft);
61615355Sjkh	if (rc) {
61711303Sjkh		ppp_unregister_compressor(&ppp_deflate);
61811303Sjkh		return rc;
61916366Sjkh	}
62011303Sjkh
62115512Sjkh	pr_info("PPP Deflate Compression module registered\n");
62215512Sjkh	return 0;
62315512Sjkh}
62411303Sjkh
62511303Sjkhstatic void __exit deflate_cleanup(void)
62611303Sjkh{
62711487Sjkh	ppp_unregister_compressor(&ppp_deflate);
62847221Sjkh	ppp_unregister_compressor(&ppp_deflate_draft);
62911303Sjkh}
63015242Sjkh
63114670Sjkhmodule_init(deflate_init);
63214738Sjkhmodule_exit(deflate_cleanup);
63314670SjkhMODULE_DESCRIPTION("PPP Deflate compression module");
63414738SjkhMODULE_LICENSE("Dual BSD/GPL");
63514670SjkhMODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
63614670SjkhMODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
63720247Sjkh