]> git.ipfire.org Git - thirdparty/openvpn.git/blob - src/openvpn/comp.c
311f3e9191ed3c010926930bd4a8ad6985d45403
[thirdparty/openvpn.git] / src / openvpn / comp.c
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-2023 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, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "syshead.h"
29
30 #include "comp.h"
31 #include "error.h"
32
33 #ifdef USE_COMP
34
35 #include "otime.h"
36
37 #include "memdbg.h"
38
39 struct compress_context *
40 comp_init(const struct compress_options *opt)
41 {
42 struct compress_context *compctx = NULL;
43 switch (opt->alg)
44 {
45 case COMP_ALG_STUB:
46 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
47 compctx->flags = opt->flags;
48 compctx->alg = comp_stub_alg;
49 break;
50
51 case COMP_ALGV2_UNCOMPRESSED:
52 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
53 compctx->flags = opt->flags;
54 compctx->alg = compv2_stub_alg;
55 break;
56
57 #ifdef ENABLE_LZO
58 case COMP_ALG_LZO:
59 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
60 compctx->flags = opt->flags;
61 compctx->alg = lzo_alg;
62 break;
63
64 #endif
65 #ifdef ENABLE_LZ4
66 case COMP_ALG_LZ4:
67 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
68 compctx->flags = opt->flags;
69 compctx->alg = lz4_alg;
70 break;
71
72 case COMP_ALGV2_LZ4:
73 ALLOC_OBJ_CLEAR(compctx, struct compress_context);
74 compctx->flags = opt->flags;
75 compctx->alg = lz4v2_alg;
76 break;
77 #endif
78 }
79 if (compctx)
80 {
81 (*compctx->alg.compress_init)(compctx);
82 }
83
84 return compctx;
85 }
86
87 /* In the v2 compression schemes, an uncompressed packet has
88 * has no opcode in front, unless the first byte is 0x50. In this
89 * case the packet needs to be escaped */
90 void
91 compv2_escape_data_ifneeded(struct buffer *buf)
92 {
93 uint8_t *head = BPTR(buf);
94 if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
95 {
96 return;
97 }
98
99 /* Header is 0x50 */
100 ASSERT(buf_prepend(buf, 2));
101
102 head = BPTR(buf);
103 head[0] = COMP_ALGV2_INDICATOR_BYTE;
104 head[1] = COMP_ALGV2_UNCOMPRESSED;
105 }
106
107
108 void
109 comp_uninit(struct compress_context *compctx)
110 {
111 if (compctx)
112 {
113 (*compctx->alg.compress_uninit)(compctx);
114 free(compctx);
115 }
116 }
117
118 void
119 comp_print_stats(const struct compress_context *compctx, struct status_output *so)
120 {
121 if (compctx)
122 {
123 status_printf(so, "pre-compress bytes," counter_format, compctx->pre_compress);
124 status_printf(so, "post-compress bytes," counter_format, compctx->post_compress);
125 status_printf(so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
126 status_printf(so, "post-decompress bytes," counter_format, compctx->post_decompress);
127 }
128 }
129
130 /*
131 * Tell our peer which compression algorithms we support.
132 */
133 void
134 comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out)
135 {
136 if (!opt || opt->flags & COMP_F_ALLOW_NOCOMP_ONLY)
137 {
138 return;
139 }
140
141 bool lzo_avail = false;
142 if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY))
143 {
144 #if defined(ENABLE_LZ4)
145 buf_printf(out, "IV_LZ4=1\n");
146 buf_printf(out, "IV_LZ4v2=1\n");
147 #endif
148 #if defined(ENABLE_LZO)
149 buf_printf(out, "IV_LZO=1\n");
150 lzo_avail = true;
151 #endif
152 }
153 if (!lzo_avail)
154 {
155 buf_printf(out, "IV_LZO_STUB=1\n");
156 }
157 buf_printf(out, "IV_COMP_STUB=1\n");
158 buf_printf(out, "IV_COMP_STUBv2=1\n");
159 }
160 #endif /* USE_COMP */
161
162 bool
163 check_compression_settings_valid(struct compress_options *info, int msglevel)
164 {
165 /*
166 * We also allow comp-stub-v2 here as it technically allows escaping of
167 * weird mac address and IPv5 protocol but practically always is used
168 * as an way to disable all framing.
169 */
170 if (info->alg != COMP_ALGV2_UNCOMPRESSED && info->alg != COMP_ALG_UNDEF
171 && (info->flags & COMP_F_ALLOW_NOCOMP_ONLY))
172 {
173 #ifdef USE_COMP
174 msg(msglevel, "Compression or compression stub framing is not allowed "
175 "since data-channel offloading is enabled.");
176 #else
177 msg(msglevel, "Compression or compression stub framing is not allowed "
178 "since OpenVPN was built without compression support.");
179 #endif
180 return false;
181 }
182
183 if ((info->flags & COMP_F_ALLOW_STUB_ONLY) && comp_non_stub_enabled(info))
184 {
185 msg(msglevel, "Compression is not allowed since allow-compression is "
186 "set to 'stub-only'");
187 return false;
188 }
189 #ifndef ENABLE_LZ4
190 if (info->alg == COMP_ALGV2_LZ4 || info->alg == COMP_ALG_LZ4)
191 {
192 msg(msglevel, "OpenVPN is compiled without LZ4 support. Requested "
193 "compression cannot be enabled.");
194 return false;
195 }
196 #endif
197 #ifndef ENABLE_LZO
198 if (info->alg == COMP_ALG_LZO)
199 {
200 msg(msglevel, "OpenVPN is compiled without LZO support. Requested "
201 "compression cannot be enabled.");
202 return false;
203 }
204 #endif
205 return true;
206 }