/* VTun - Virtual Tunnel over TCP/IP network. Copyright (C) 1998-2000 Maxim Krasnyansky VTun has been derived from VPPP package by Maxim Krasnyansky. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /* * $Id: lfd_zlib.c,v 1.5.2.1 2007/06/29 05:26:13 mtbishop Exp $ */ /* ZLIB compression module */ #include "config.h" #include #include #include #include #include "vtun.h" #include "linkfd.h" #include "lib.h" #ifdef HAVE_ZLIB #include static z_stream zi, zd; static unsigned char *zbuf; static int zbuf_size = VTUN_FRAME_SIZE + 200; /* * Initialize compressor/decompressor. * Allocate the buffer. */ int zlib_alloc(struct vtun_host *host) { int zlevel = host->zlevel ? host->zlevel : 1; zd.zalloc = (alloc_func)0; zd.zfree = (free_func)0; zd.opaque = (voidpf)0; zi.zalloc = (alloc_func)0; zi.zfree = (free_func)0; zi.opaque = (voidpf)0; if( deflateInit(&zd, zlevel ) != Z_OK ){ vtun_syslog(LOG_ERR,"Can't initialize compressor"); return 1; } if( inflateInit(&zi) != Z_OK ){ vtun_syslog(LOG_ERR,"Can't initialize decompressor"); return 1; } if( !(zbuf = (void *) lfd_alloc(zbuf_size)) ){ vtun_syslog(LOG_ERR,"Can't allocate buffer for the compressor"); return 1; } vtun_syslog(LOG_INFO,"ZLIB compression[level %d] initialized.", zlevel); return 0; } /* * Deinitialize compressor/decompressor. * Free the buffer. */ int zlib_free() { deflateEnd(&zd); inflateEnd(&zi); lfd_free(zbuf); zbuf = NULL; return 0; } static int expand_zbuf(z_stream *zs, int len) { if( !(zbuf = lfd_realloc(zbuf,zbuf_size+len)) ) return -1; zs->next_out = zbuf + zbuf_size; zs->avail_out = len; zbuf_size += len; return 0; } /* * This functions _MUST_ consume all incoming bytes in one pass, * That's why we expand buffer dynamically. * Practice shows that buffer will not grow larger that 16K. */ int zlib_comp(int len, char *in, char **out) { int oavail, olen = 0; int err; zd.next_in = (void *) in; zd.avail_in = len; zd.next_out = (void *) zbuf; zd.avail_out = zbuf_size; while(1) { oavail = zd.avail_out; if( (err=deflate(&zd, Z_SYNC_FLUSH)) != Z_OK ){ vtun_syslog(LOG_ERR,"Deflate error %d",err); return -1; } olen += oavail - zd.avail_out; if(!zd.avail_in) break; if( expand_zbuf(&zd,100) ) { vtun_syslog( LOG_ERR, "Can't expand compression buffer"); return -1; } } *out = (void *) zbuf; return olen; } int zlib_decomp(int len, char *in, char **out) { int oavail = 0, olen = 0; int err; zi.next_in = (void *) in; zi.avail_in = len; zi.next_out = (void *) zbuf; zi.avail_out = zbuf_size; while(1) { oavail = zi.avail_out; if( (err=inflate(&zi, Z_SYNC_FLUSH)) != Z_OK ) { vtun_syslog(LOG_ERR,"Inflate error %d len %d", err, len); return -1; } olen += oavail - zi.avail_out; if(!zi.avail_in) break; if( expand_zbuf(&zi,100) ) { vtun_syslog( LOG_ERR, "Can't expand compression buffer"); return -1; } } *out = (void *) zbuf; return olen; } struct lfd_mod lfd_zlib = { "ZLIB", zlib_alloc, zlib_comp, NULL, zlib_decomp, NULL, zlib_free, NULL, NULL }; #else /* HAVE_ZLIB */ int no_zlib(struct vtun_host *host) { vtun_syslog(LOG_INFO, "ZLIB compression is not supported"); return -1; } struct lfd_mod lfd_zlib = { "ZLIB", no_zlib, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif /* HAVE_ZLIB */