blob: 0dadd1e6c4cd29c65c9e9f2a7f11949ece851750 [file] [log] [blame]
/*
* 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-2018 OpenVPN 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; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* Generic compression support. Currently we support
* LZO 2 and LZ4.
*/
#ifndef OPENVPN_COMP_H
#define OPENVPN_COMP_H
#ifdef USE_COMP
#include "buffer.h"
#include "mtu.h"
#include "common.h"
#include "status.h"
/* algorithms */
#define COMP_ALG_UNDEF 0
#define COMP_ALG_STUB 1 /* support compression command byte and framing without actual compression */
#define COMP_ALG_LZO 2 /* LZO algorithm */
#define COMP_ALG_SNAPPY 3 /* Snappy algorithm (no longer supported) */
#define COMP_ALG_LZ4 4 /* LZ4 algorithm */
/* algorithm v2 */
#define COMP_ALGV2_UNCOMPRESSED 10
#define COMP_ALGV2_LZ4 11
/*
#define COMP_ALGV2_LZO 12
#define COMP_ALGV2_SNAPPY 13
*/
/* Compression flags */
#define COMP_F_ADAPTIVE (1<<0) /* COMP_ALG_LZO only */
#define COMP_F_ASYM (1<<1) /* only downlink is compressed, not uplink */
#define COMP_F_SWAP (1<<2) /* initial command byte is swapped with last byte in buffer to preserve payload alignment */
#define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only support compression stubs */
/*
* Length of prepended prefix on compressed packets
*/
#define COMP_PREFIX_LEN 1
/*
* Prefix bytes
*/
/* V1 on wire codes */
/* Initial command byte to tell our peer if we compressed */
#define LZO_COMPRESS_BYTE 0x66
#define LZ4_COMPRESS_BYTE 0x69
#define NO_COMPRESS_BYTE 0xFA
#define NO_COMPRESS_BYTE_SWAP 0xFB /* to maintain payload alignment, replace this byte with last byte of packet */
/* V2 on wire code */
#define COMP_ALGV2_INDICATOR_BYTE 0x50
#define COMP_ALGV2_UNCOMPRESSED_BYTE 0
#define COMP_ALGV2_LZ4_BYTE 1
#define COMP_ALGV2_LZO_BYTE 2
#define COMP_ALGV2_SNAPPY_BYTE 3
/*
* Compress worst case size expansion (for any algorithm)
*
* LZO: len + len/8 + 128 + 3
* Snappy: len + len/6 + 32
* LZ4: len + len/255 + 16 (LZ4_COMPRESSBOUND(len))
*/
#define COMP_EXTRA_BUFFER(len) ((len)/6 + 128 + 3 + COMP_PREFIX_LEN)
/*
* Don't try to compress any packet smaller than this.
*/
#define COMPRESS_THRESHOLD 100
/* Forward declaration of compression context */
struct compress_context;
/*
* Virtual methods and other static info for each compression algorithm
*/
struct compress_alg
{
const char *name;
void (*compress_init)(struct compress_context *compctx);
void (*compress_uninit)(struct compress_context *compctx);
void (*compress)(struct buffer *buf, struct buffer work,
struct compress_context *compctx,
const struct frame *frame);
void (*decompress)(struct buffer *buf, struct buffer work,
struct compress_context *compctx,
const struct frame *frame);
};
/*
* Headers for each compression implementation
*/
#ifdef ENABLE_LZO
#include "lzo.h"
#endif
#ifdef ENABLE_LZ4
#include "comp-lz4.h"
#endif
/*
* Information that basically identifies a compression
* algorithm and related flags.
*/
struct compress_options
{
int alg;
unsigned int flags;
};
/*
* Workspace union of all supported compression algorithms
*/
union compress_workspace_union
{
#ifdef ENABLE_LZO
struct lzo_compress_workspace lzo;
#endif
#ifdef ENABLE_LZ4
struct lz4_workspace lz4;
#endif
};
/*
* Context for active compression session
*/
struct compress_context
{
unsigned int flags;
struct compress_alg alg;
union compress_workspace_union wu;
/* statistics */
counter_type pre_decompress;
counter_type post_decompress;
counter_type pre_compress;
counter_type post_compress;
};
extern const struct compress_alg comp_stub_alg;
extern const struct compress_alg compv2_stub_alg;
struct compress_context *comp_init(const struct compress_options *opt);
void comp_uninit(struct compress_context *compctx);
void comp_add_to_extra_frame(struct frame *frame);
void comp_add_to_extra_buffer(struct frame *frame);
void comp_print_stats(const struct compress_context *compctx, struct status_output *so);
void comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out);
void compv2_escape_data_ifneeded(struct buffer *buf);
static inline bool
comp_enabled(const struct compress_options *info)
{
return info->alg != COMP_ALG_UNDEF;
}
static inline bool
comp_unswapped_prefix(const struct compress_options *info)
{
return !(info->flags & COMP_F_SWAP);
}
#endif /* USE_COMP */
#endif /* ifndef OPENVPN_COMP_H */