/*
* deflate.c - interface the zlib procedures for Deflate compression
* and decompression (as used by gzip) to the PPP code.
*
* This version is for use with STREAMS in Solaris 2
*
* Copyright (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* Copyright (c) 1994 The Australian National University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies. This software is provided without any
* warranty, express or implied. The Australian National University
* makes no representations about the suitability of this software for
* any purpose.
*
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
* THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*
* $Id: deflate.c,v 1.9 1999/01/19 23:58:35 paulus Exp $
*/
#define NO_DUMMY_DECL
#include <net/ppp_defs.h>
/* Defined for platform-neutral include file */
#include <net/ppp-comp.h>
#include "s_common.h"
#include "zlib.h"
#if DO_DEFLATE
/*
* State for a Deflate (de)compressor.
*/
struct deflate_state {
int seqno;
int w_size;
int unit;
int hdrlen;
int mru;
int flags;
};
static void z_comp_free(void *state);
static void z_decomp_free(void *state);
static void z_comp_reset(void *state);
static void z_decomp_reset(void *state);
/*
* Procedures exported to ppp_comp.c.
*/
CI_DEFLATE, /* compress_proto */
z_comp_alloc, /* comp_alloc */
z_comp_free, /* comp_free */
z_comp_init, /* comp_init */
z_comp_reset, /* comp_reset */
z_compress, /* compress */
z_comp_stats, /* comp_stat */
z_decomp_alloc, /* decomp_alloc */
z_decomp_free, /* decomp_free */
z_decomp_init, /* decomp_init */
z_decomp_reset, /* decomp_reset */
z_decompress, /* decompress */
z_incomp, /* incomp */
z_comp_stats, /* decomp_stat */
z_set_effort, /* set_effort */
};
CI_DEFLATE_DRAFT, /* compress_proto */
z_comp_alloc, /* comp_alloc */
z_comp_free, /* comp_free */
z_comp_init, /* comp_init */
z_comp_reset, /* comp_reset */
z_compress, /* compress */
z_comp_stats, /* comp_stat */
z_decomp_alloc, /* decomp_alloc */
z_decomp_free, /* decomp_free */
z_decomp_init, /* decomp_init */
z_decomp_reset, /* decomp_reset */
z_decompress, /* decompress */
z_incomp, /* incomp */
z_comp_stats, /* decomp_stat */
z_set_effort, /* set_effort */
};
/*
* Space allocation and freeing routines for use by zlib routines.
*/
struct zchunk {
};
/*
* z_alloc()
*/
/* ARGSUSED */
static void *
{
struct zchunk *z;
if (z == NULL)
return (NULL);
z->guard = GUARD_MAGIC;
return ((void *)(z + 1));
}
/*
* z_free()
*/
/* ARGSUSED */
static void
{
return;
if (z->guard != GUARD_MAGIC) {
"deflate: z_free of corrupted chunk at 0x%p (%x, %x)\n",
return;
}
}
/*
* Allocate space for a compressor.
*/
static void *
{
int w_size;
if (opt_len != CILEN_DEFLATE ||
return (NULL);
}
/*
* Check <= minimum size to avoid unfixable zlib bug -- window size
* 256 (w_size 8) is not supported.
*/
return (NULL);
}
return (NULL);
}
return ((void *)state);
}
/*
* z_comp_free()
*/
static void
{
}
/*
* z_comp_init()
*/
static int
int debug)
{
if (opt_len < CILEN_DEFLATE ||
return (0);
}
if (debug)
else
return (1);
}
/*
* z_comp_reset()
*/
static void
{
}
/*
* z_compress()
*/
static int
{
int olen;
int wspace;
int r;
int flush;
mblk_t *m;
#else
#endif
#define ADJRPTR() { \
break; \
} \
} \
} \
}
#define GETBYTE(v) { \
(v) = *rptr++; \
} \
}
/*
* Check that the protocol is one we handle. Pullup is *NOT*
* possible here.
*/
ADJRPTR();
ADJRPTR();
ADJRPTR();
/*
* Per RFC 1979, the protocol field must be compressed using a
* PFC-like procedure. Also, all protocols between 0000-3FFF
* except the two compression protocols must be LZ compressed.
*/
return (orig_len);
r = *rptr;
if (r == 0) {
rptr++;
ADJRPTR();
return (orig_len);
} else {
if (r > 0x3F)
return (orig_len);
}
/*
* Allocate one mblk initially
*/
}
wspace = 0;
m = NULL;
} else {
if (wspace > 4096) {
wspace = 4096;
}
}
if (m != NULL) {
*mret = m;
}
/*
* Copy over the PPP header and store the 2-byte
* sequence number
*/
wptr += PPP_HDRLEN;
wptr += 2;
#ifdef DEBUG
/*
* If testing output, just garbling the sequence here
* does the trick.
*/
#endif
} else {
}
olen = 0;
for (;;) {
if (r != Z_OK) {
"z_compress%d: deflate returned %d (%s)\n",
break;
}
break; /* all done */
} else {
}
}
if (m != NULL) {
if (wspace <= 0) {
wspace = 0;
} else {
if (wspace < 32) {
wspace = 32;
} else if (wspace > 4096) {
wspace = 4096;
}
}
m = m->b_cont;
if (m != NULL) {
m->b_wptr;
}
}
if (m == NULL) {
}
}
}
if (m != NULL) {
}
/*
* See if we managed to reduce the size of the packet.
*/
} else {
}
}
return (olen);
}
/*
* z_incomp()
*
* Incompressible data has arrived - add it to the history.
*/
static int
{
int rlen;
int r;
/*
* Check that the protocol is one we handle. Pullup is *NOT*
* possible here.
*/
ADJRPTR();
rptr++; /* skip address */
ADJRPTR();
rptr++; /* skip control */
ADJRPTR();
/*
* Per RFC 1979, the protocol field must be compressed using a
* PFC-like procedure. Also, all protocols between 0000-3FFF
* except the two compression protocols must be LZ compressed.
*/
return (0);
r = *rptr;
if (r == 0) {
rptr++;
ADJRPTR();
return (0);
} else {
if (r > 0x3F)
return (0);
}
/*
* Iterate through the message blocks, adding the characters
* in them to the decompressor's history.
*/
for (;;) {
if (r != Z_OK) { /* gak! */
"z_incomp%d: inflateIncomp returned "
}
return (-1);
}
break;
}
}
/*
* Update stats
*/
return (0);
}
/*
* z_comp_stats()
*/
static void
{
} else {
out >>= 8;
}
if (out != 0) {
}
}
/*
* z_decomp_alloc()
*
* Allocate space for a decompressor.
*/
static void *
{
int w_size;
if (opt_len != CILEN_DEFLATE ||
return (NULL);
}
/*
* Check <= minimum size to avoid unfixable zlib bug -- window size
* 256 (w_size 8) is not supported.
*/
return (NULL);
}
return (NULL);
}
return ((void *)state);
}
/*
* z_decomp_free()
*/
static void
{
}
/*
* z_decomp_init()
*/
static int
{
if (opt_len < CILEN_DEFLATE ||
return (0);
}
if (debug)
else
return (1);
}
/*
* z_decomp_reset()
*/
static void
{
}
/*
* z_decompress()
*
* Decompress a Deflate-compressed packet.
*
* Because of patent problems, we return DECOMP_ERROR for errors
* found by inspecting the input data and for system problems, but
* DECOMP_FATALERROR for any errors which could possibly be said to
* be being detected "after" decompression. For DECOMP_ERROR,
* we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
* infringing a patent of Motorola's if we do, so we take CCP down
* instead.
*
* Given that the frame has the correct sequence number and a good FCS,
* errors such as invalid codes in the input most likely indicate a
* bug, so we return DECOMP_FATALERROR for them in order to turn off
* compression, even though they are detected by inspecting the input.
*/
static int
{
int rlen;
int olen;
int ospace;
int seq;
int flush;
int r;
int decode_proto;
#else
#endif
/* Note: spppcomp already did a pullup to fix the first buffer. */
}
return (DECOMP_ERROR);
}
/*
* Note that we free as we go. If we fail to decompress,
* there's nothing good that the caller can do.
*/
#define ADJRPTR() { \
break; \
} \
} \
} \
}
/*
* Check the sequence number
*/
ADJRPTR();
ADJRPTR();
}
return (DECOMP_ERROR);
}
#ifdef DEBUG
/*
* If testing input, just pretending the sequence is bad here
* does the trick.
*/
seq ^= 0x55;
#endif
"z_decompress%d: bad seq # %d, expected %d\n",
}
return (DECOMP_ERROR);
}
/*
* Allocate an output message block
*/
return (DECOMP_ERROR);
}
olen = 0;
/*
* Fill in the first part of the PPP header. The protocol field
* comes from the decompressed data.
*/
*wptr++ = 0;
/*
* Set up to call inflate. We set avail_out to 1 initially so we can
* look at the first byte of the output and decide whether we have
* a 1-byte or 2-byte protocol field.
*/
decode_proto = 1;
/*
* Call inflate, supplying more input or output as needed.
*/
for (;;) {
if (r != Z_OK) {
"z_decompress%d: inflate returned %d "
}
return (DECOMP_FATALERROR);
}
}
break; /* all done */
} else {
}
}
if (decode_proto) {
if ((wptr[0] & 1) == 0) {
/*
* 2-byte protocol field
*/
}
decode_proto = 0;
} else {
return (DECOMP_ERROR);
}
}
}
}
if (decode_proto) {
return (DECOMP_ERROR);
}
}
return (DECOMP_OK);
}
/* ARGSUSED */
static int
{
#ifdef DEBUG
#endif
int retv;
#ifdef DEBUG
/* corrupt received data. */
}
if (effortlevel != 2112)
return (0);
}
/* corrupt transmitted data. */
}
return (0);
}
#endif
return (EINVAL);
return (0);
}
#endif /* DO_DEFLATE */