OpenVPN
comp.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "comp.h"
30#include "error.h"
31
32#ifdef USE_COMP
33
34#include "otime.h"
35
36#include "memdbg.h"
37
38struct compress_context *
39comp_init(const struct compress_options *opt)
40{
41 struct compress_context *compctx = NULL;
42 switch (opt->alg)
43 {
44 case COMP_ALG_STUB:
45 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
46 compctx->flags = opt->flags;
47 compctx->alg = comp_stub_alg;
48 break;
49
51 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
52 compctx->flags = opt->flags;
53 compctx->alg = compv2_stub_alg;
54 break;
55
56#ifdef ENABLE_LZO
57 case COMP_ALG_LZO:
58 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
59 compctx->flags = opt->flags;
60 compctx->alg = lzo_alg;
61 break;
62
63#endif
64#ifdef ENABLE_LZ4
65 case COMP_ALG_LZ4:
66 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
67 compctx->flags = opt->flags;
68 compctx->alg = lz4_alg;
69 break;
70
71 case COMP_ALGV2_LZ4:
72 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
73 compctx->flags = opt->flags;
74 compctx->alg = lz4v2_alg;
75 break;
76#endif
77 }
78 if (compctx)
79 {
80 (*compctx->alg.compress_init)(compctx);
81 }
82
83 return compctx;
84}
85
86/* In the v2 compression schemes, an uncompressed packet has
87 * has no opcode in front, unless the first byte is 0x50. In this
88 * case the packet needs to be escaped */
89void
90compv2_escape_data_ifneeded(struct buffer *buf)
91{
92 uint8_t *head = BPTR(buf);
93 if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
94 {
95 return;
96 }
97
98 /* Header is 0x50 */
99 ASSERT(buf_prepend(buf, 2));
100
101 head = BPTR(buf);
102 head[0] = COMP_ALGV2_INDICATOR_BYTE;
103 head[1] = COMP_ALGV2_UNCOMPRESSED;
104}
105
106
107void
108comp_uninit(struct compress_context *compctx)
109{
110 if (compctx)
111 {
112 (*compctx->alg.compress_uninit)(compctx);
113 free(compctx);
114 }
115}
116
117void
118comp_print_stats(const struct compress_context *compctx, struct status_output *so)
119{
120 if (compctx)
121 {
122 status_printf(so, "pre-compress bytes," counter_format, compctx->pre_compress);
123 status_printf(so, "post-compress bytes," counter_format, compctx->post_compress);
124 status_printf(so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
125 status_printf(so, "post-decompress bytes," counter_format, compctx->post_decompress);
126 }
127}
128
129/*
130 * Tell our peer which compression algorithms we support.
131 */
132void
133comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out)
134{
135 if (!opt || opt->flags & COMP_F_ALLOW_NOCOMP_ONLY)
136 {
137 return;
138 }
139
140 bool lzo_avail = false;
142 {
143#if defined(ENABLE_LZ4)
144 buf_printf(out, "IV_LZ4=1\n");
145 buf_printf(out, "IV_LZ4v2=1\n");
146#endif
147#if defined(ENABLE_LZO)
148 buf_printf(out, "IV_LZO=1\n");
149 lzo_avail = true;
150#endif
151 }
152 if (!lzo_avail)
153 {
154 buf_printf(out, "IV_LZO_STUB=1\n");
155 }
156 buf_printf(out, "IV_COMP_STUB=1\n");
157 buf_printf(out, "IV_COMP_STUBv2=1\n");
158}
159#endif /* USE_COMP */
160
161bool
163{
164 /*
165 * We also allow comp-stub-v2 here as it technically allows escaping of
166 * weird mac address and IPv5 protocol but practically always is used
167 * as an way to disable all framing.
168 */
169 if (info->alg != COMP_ALGV2_UNCOMPRESSED && info->alg != COMP_ALG_UNDEF
170 && (info->flags & COMP_F_ALLOW_NOCOMP_ONLY))
171 {
172#ifdef USE_COMP
173 msg(msglevel, "Compression or compression stub framing is not allowed "
174 "since data-channel offloading is enabled.");
175#else
176 msg(msglevel, "Compression or compression stub framing is not allowed "
177 "since OpenVPN was built without compression support.");
178#endif
179 return false;
180 }
181
183 {
184 msg(msglevel, "Compression is not allowed since allow-compression is "
185 "set to 'stub-only'");
186 return false;
187 }
188#ifndef ENABLE_LZ4
189 if (info->alg == COMP_ALGV2_LZ4 || info->alg == COMP_ALG_LZ4)
190 {
191 msg(msglevel, "OpenVPN is compiled without LZ4 support. Requested "
192 "compression cannot be enabled.");
193 return false;
194 }
195#endif
196#ifndef ENABLE_LZO
197 if (info->alg == COMP_ALG_LZO)
198 {
199 msg(msglevel, "OpenVPN is compiled without LZO support. Requested "
200 "compression cannot be enabled.");
201 return false;
202 }
203#endif
204 return true;
205}
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
#define BPTR(buf)
Definition buffer.h:123
static uint8_t * buf_prepend(struct buffer *buf, int size)
Definition buffer.h:604
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1042
#define counter_format
Definition common.h:30
bool check_compression_settings_valid(struct compress_options *info, int msglevel)
Checks if the compression settings are valid.
Definition comp.c:162
#define COMP_F_ALLOW_STUB_ONLY
Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY we still accept other compression...
Definition comp.h:45
#define COMP_ALG_LZ4
LZ4 algorithm.
Definition comp.h:59
#define COMP_ALGV2_LZ4
Definition comp.h:64
#define COMP_F_ALLOW_NOCOMP_ONLY
Do not allow compression framing (breaks DCO)
Definition comp.h:51
#define COMP_ALGV2_UNCOMPRESSED
Definition comp.h:63
#define COMP_ALG_STUB
support compression command byte and framing without actual compression
Definition comp.h:56
#define COMP_ALG_LZO
LZO algorithm.
Definition comp.h:57
#define COMP_F_ADVERTISE_STUBS_ONLY
tell server that we only support compression stubs
Definition comp.h:42
static bool comp_non_stub_enabled(const struct compress_options *info)
Definition comp.h:81
#define COMP_ALG_UNDEF
Definition comp.h:54
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
void status_printf(struct status_output *so, const char *format,...)
Definition status.c:213
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
unsigned int flags
Definition comp.h:77