summaryrefslogtreecommitdiff
path: root/src/openvpn/comp.h
blob: 0dadd1e6c4cd29c65c9e9f2a7f11949ece851750 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 *  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 */