]>
Commit | Line | Data |
---|---|---|
38d96bd7 JY |
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 | * | |
b25c6d7e | 8 | * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net> |
38d96bd7 JY |
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 | * | |
caa54ac3 DS |
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. | |
38d96bd7 JY |
22 | */ |
23 | ||
24 | #ifdef HAVE_CONFIG_H | |
25 | #include "config.h" | |
38d96bd7 JY |
26 | #endif |
27 | ||
28 | #include "syshead.h" | |
29 | ||
38d96bd7 JY |
30 | #include "comp.h" |
31 | #include "error.h" | |
a8170dd0 AS |
32 | |
33 | #ifdef USE_COMP | |
34 | ||
38d96bd7 JY |
35 | #include "otime.h" |
36 | ||
37 | #include "memdbg.h" | |
38 | ||
39 | struct compress_context * | |
40 | comp_init(const struct compress_options *opt) | |
41 | { | |
81d882d5 DS |
42 | struct compress_context *compctx = NULL; |
43 | switch (opt->alg) | |
38d96bd7 | 44 | { |
81d882d5 DS |
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 | ||
38d96bd7 | 57 | #ifdef ENABLE_LZO |
81d882d5 DS |
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 | ||
38d96bd7 | 64 | #endif |
40efb635 | 65 | #ifdef ENABLE_LZ4 |
81d882d5 DS |
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; | |
38d96bd7 JY |
77 | #endif |
78 | } | |
81d882d5 DS |
79 | if (compctx) |
80 | { | |
81 | (*compctx->alg.compress_init)(compctx); | |
82 | } | |
67b3de98 | 83 | |
81d882d5 | 84 | return compctx; |
38d96bd7 JY |
85 | } |
86 | ||
a75bb2e4 AS |
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 | |
81d882d5 | 91 | compv2_escape_data_ifneeded(struct buffer *buf) |
a75bb2e4 | 92 | { |
81d882d5 | 93 | uint8_t *head = BPTR(buf); |
a75bb2e4 | 94 | if (head[0] != COMP_ALGV2_INDICATOR_BYTE) |
81d882d5 DS |
95 | { |
96 | return; | |
97 | } | |
a75bb2e4 AS |
98 | |
99 | /* Header is 0x50 */ | |
100 | ASSERT(buf_prepend(buf, 2)); | |
101 | ||
81d882d5 | 102 | head = BPTR(buf); |
a75bb2e4 AS |
103 | head[0] = COMP_ALGV2_INDICATOR_BYTE; |
104 | head[1] = COMP_ALGV2_UNCOMPRESSED; | |
105 | } | |
106 | ||
107 | ||
38d96bd7 JY |
108 | void |
109 | comp_uninit(struct compress_context *compctx) | |
110 | { | |
81d882d5 | 111 | if (compctx) |
38d96bd7 | 112 | { |
81d882d5 DS |
113 | (*compctx->alg.compress_uninit)(compctx); |
114 | free(compctx); | |
38d96bd7 JY |
115 | } |
116 | } | |
117 | ||
38d96bd7 | 118 | void |
81d882d5 | 119 | comp_print_stats(const struct compress_context *compctx, struct status_output *so) |
38d96bd7 | 120 | { |
81d882d5 | 121 | if (compctx) |
38d96bd7 | 122 | { |
81d882d5 DS |
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); | |
38d96bd7 JY |
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 | { | |
4117d950 AS |
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)) | |
38d96bd7 | 143 | { |
40efb635 | 144 | #if defined(ENABLE_LZ4) |
4117d950 AS |
145 | buf_printf(out, "IV_LZ4=1\n"); |
146 | buf_printf(out, "IV_LZ4v2=1\n"); | |
40efb635 | 147 | #endif |
38d96bd7 | 148 | #if defined(ENABLE_LZO) |
4117d950 AS |
149 | buf_printf(out, "IV_LZO=1\n"); |
150 | lzo_avail = true; | |
38d96bd7 | 151 | #endif |
38d96bd7 | 152 | } |
4117d950 AS |
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"); | |
38d96bd7 | 159 | } |
a8170dd0 | 160 | #endif /* USE_COMP */ |
38d96bd7 | 161 | |
e86bc8b2 AS |
162 | bool |
163 | check_compression_settings_valid(struct compress_options *info, int msglevel) | |
164 | { | |
4117d950 AS |
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 | { | |
a8170dd0 | 173 | #ifdef USE_COMP |
4117d950 AS |
174 | msg(msglevel, "Compression or compression stub framing is not allowed " |
175 | "since data-channel offloading is enabled."); | |
a8170dd0 AS |
176 | #else |
177 | msg(msglevel, "Compression or compression stub framing is not allowed " | |
178 | "since OpenVPN was built without compression support."); | |
179 | #endif | |
4117d950 AS |
180 | return false; |
181 | } | |
182 | ||
e86bc8b2 AS |
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 " | |
4117d950 | 186 | "set to 'stub-only'"); |
e86bc8b2 AS |
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 | |
4076d24f | 198 | if (info->alg == COMP_ALG_LZO) |
e86bc8b2 AS |
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 | } |