diff options
Diffstat (limited to 'src/openvpn/comp.c')
-rw-r--r-- | src/openvpn/comp.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/openvpn/comp.c b/src/openvpn/comp.c new file mode 100644 index 0000000..499fef9 --- /dev/null +++ b/src/openvpn/comp.c @@ -0,0 +1,167 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2012 OpenVPN Technologies, Inc. <sales@openvpn.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#ifdef USE_COMP + +#include "comp.h" +#include "error.h" +#include "otime.h" + +#include "memdbg.h" + +struct compress_context * +comp_init(const struct compress_options *opt) +{ + struct compress_context *compctx = NULL; + switch (opt->alg) + { + case COMP_ALG_STUB: + ALLOC_OBJ_CLEAR (compctx, struct compress_context); + compctx->flags = opt->flags; + compctx->alg = comp_stub_alg; + break; + case COMP_ALGV2_UNCOMPRESSED: + ALLOC_OBJ_CLEAR (compctx, struct compress_context); + compctx->flags = opt->flags; + compctx->alg = compv2_stub_alg; + break; +#ifdef ENABLE_LZO + case COMP_ALG_LZO: + ALLOC_OBJ_CLEAR (compctx, struct compress_context); + compctx->flags = opt->flags; + compctx->alg = lzo_alg; + break; +#endif +#ifdef ENABLE_LZ4 + case COMP_ALG_LZ4: + ALLOC_OBJ_CLEAR (compctx, struct compress_context); + compctx->flags = opt->flags; + compctx->alg = lz4_alg; + break; + case COMP_ALGV2_LZ4: + ALLOC_OBJ_CLEAR (compctx, struct compress_context); + compctx->flags = opt->flags; + compctx->alg = lz4v2_alg; + break; +#endif + } + if (compctx) + (*compctx->alg.compress_init)(compctx); + + return compctx; +} + +/* In the v2 compression schemes, an uncompressed packet has + * has no opcode in front, unless the first byte is 0x50. In this + * case the packet needs to be escaped */ +void +compv2_escape_data_ifneeded (struct buffer *buf) +{ + uint8_t *head = BPTR (buf); + if (head[0] != COMP_ALGV2_INDICATOR_BYTE) + return; + + /* Header is 0x50 */ + ASSERT(buf_prepend(buf, 2)); + + head = BPTR (buf); + head[0] = COMP_ALGV2_INDICATOR_BYTE; + head[1] = COMP_ALGV2_UNCOMPRESSED; +} + + +void +comp_uninit(struct compress_context *compctx) +{ + if (compctx) + { + (*compctx->alg.compress_uninit)(compctx); + free(compctx); + } +} + +void +comp_add_to_extra_frame(struct frame *frame) +{ + /* Leave room for our one-byte compressed/didn't-compress prefix byte. */ + frame_add_to_extra_frame (frame, COMP_PREFIX_LEN); +} + +void +comp_add_to_extra_buffer(struct frame *frame) +{ + /* Leave room for compression buffer to expand in worst case scenario + where data is totally uncompressible */ + frame_add_to_extra_buffer (frame, COMP_EXTRA_BUFFER (EXPANDED_SIZE(frame))); +} + +void +comp_print_stats (const struct compress_context *compctx, struct status_output *so) +{ + if (compctx) + { + status_printf (so, "pre-compress bytes," counter_format, compctx->pre_compress); + status_printf (so, "post-compress bytes," counter_format, compctx->post_compress); + status_printf (so, "pre-decompress bytes," counter_format, compctx->pre_decompress); + status_printf (so, "post-decompress bytes," counter_format, compctx->post_decompress); + } +} + +/* + * Tell our peer which compression algorithms we support. + */ +void +comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out) +{ + if (opt) + { + bool lzo_avail = false; + if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY)) + { +#if defined(ENABLE_LZ4) + buf_printf (out, "IV_LZ4=1\n"); + buf_printf (out, "IV_LZ4v2=1\n"); +#endif +#if defined(ENABLE_LZO) + buf_printf (out, "IV_LZO=1\n"); + lzo_avail = true; +#endif + } + if (!lzo_avail) + buf_printf (out, "IV_LZO_STUB=1\n"); + buf_printf (out, "IV_COMP_STUB=1\n"); + buf_printf (out, "IV_COMP_STUBv2=1\n"); + buf_printf (out, "IV_TCPNL=1\n"); + } +} + +#endif /* USE_COMP */ |