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-2024 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 
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
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 }
comp_non_stub_enabled
static bool comp_non_stub_enabled(const struct compress_options *info)
Definition: comp.h:71
compress_options
Definition: comp.h:64
compress_options::alg
int alg
Definition: comp.h:66
error.h
ASSERT
#define ASSERT(x)
Definition: error.h:195
COMP_ALG_LZ4
#define COMP_ALG_LZ4
Definition: comp.h:49
COMP_F_ADVERTISE_STUBS_ONLY
#define COMP_F_ADVERTISE_STUBS_ONLY
Definition: comp.h:38
COMP_ALG_UNDEF
#define COMP_ALG_UNDEF
Definition: comp.h:45
COMP_ALGV2_UNCOMPRESSED
#define COMP_ALGV2_UNCOMPRESSED
Definition: comp.h:53
status_printf
void status_printf(struct status_output *so, const char *format,...)
Definition: status.c:222
status_output
Definition: status.h:48
compress_options::flags
unsigned int flags
Definition: comp.h:67
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
syshead.h
BPTR
#define BPTR(buf)
Definition: buffer.h:124
COMP_F_ALLOW_NOCOMP_ONLY
#define COMP_F_ALLOW_NOCOMP_ONLY
Definition: comp.h:42
check_compression_settings_valid
bool check_compression_settings_valid(struct compress_options *info, int msglevel)
Checks if the compression settings are valid.
Definition: comp.c:163
buf_prepend
static uint8_t * buf_prepend(struct buffer *buf, int size)
Definition: buffer.h:611
counter_format
#define counter_format
Definition: common.h:31
comp.h
COMP_ALG_STUB
#define COMP_ALG_STUB
Definition: comp.h:46
otime.h
ALLOC_OBJ_CLEAR
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1065
config.h
COMP_ALG_LZO
#define COMP_ALG_LZO
Definition: comp.h:47
memdbg.h
COMP_ALGV2_LZ4
#define COMP_ALGV2_LZ4
Definition: comp.h:54
msg
#define msg(flags,...)
Definition: error.h:144
buf_printf
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:240
COMP_F_ALLOW_STUB_ONLY
#define COMP_F_ALLOW_STUB_ONLY
Definition: comp.h:39