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-2018 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 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #ifdef USE_COMP
33 
34 #include "comp.h"
35 #include "error.h"
36 #include "otime.h"
37 
38 #include "memdbg.h"
39 
40 struct compress_context *
41 comp_init(const struct compress_options *opt)
42 {
43  struct compress_context *compctx = NULL;
44  switch (opt->alg)
45  {
46  case COMP_ALG_STUB:
47  ALLOC_OBJ_CLEAR(compctx, struct compress_context);
48  compctx->flags = opt->flags;
49  compctx->alg = comp_stub_alg;
50  break;
51 
52  case COMP_ALGV2_UNCOMPRESSED:
53  ALLOC_OBJ_CLEAR(compctx, struct compress_context);
54  compctx->flags = opt->flags;
55  compctx->alg = compv2_stub_alg;
56  break;
57 
58 #ifdef ENABLE_LZO
59  case COMP_ALG_LZO:
60  ALLOC_OBJ_CLEAR(compctx, struct compress_context);
61  compctx->flags = opt->flags;
62  compctx->alg = lzo_alg;
63  break;
64 
65 #endif
66 #ifdef ENABLE_LZ4
67  case COMP_ALG_LZ4:
68  ALLOC_OBJ_CLEAR(compctx, struct compress_context);
69  compctx->flags = opt->flags;
70  compctx->alg = lz4_alg;
71  break;
72 
73  case COMP_ALGV2_LZ4:
74  ALLOC_OBJ_CLEAR(compctx, struct compress_context);
75  compctx->flags = opt->flags;
76  compctx->alg = lz4v2_alg;
77  break;
78 #endif
79  }
80  if (compctx)
81  {
82  (*compctx->alg.compress_init)(compctx);
83  }
84 
85  return compctx;
86 }
87 
88 /* In the v2 compression schemes, an uncompressed packet has
89  * has no opcode in front, unless the first byte is 0x50. In this
90  * case the packet needs to be escaped */
91 void
92 compv2_escape_data_ifneeded(struct buffer *buf)
93 {
94  uint8_t *head = BPTR(buf);
95  if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
96  {
97  return;
98  }
99 
100  /* Header is 0x50 */
101  ASSERT(buf_prepend(buf, 2));
102 
103  head = BPTR(buf);
104  head[0] = COMP_ALGV2_INDICATOR_BYTE;
105  head[1] = COMP_ALGV2_UNCOMPRESSED;
106 }
107 
108 
109 void
110 comp_uninit(struct compress_context *compctx)
111 {
112  if (compctx)
113  {
114  (*compctx->alg.compress_uninit)(compctx);
115  free(compctx);
116  }
117 }
118 
119 void
120 comp_add_to_extra_frame(struct frame *frame)
121 {
122  /* Leave room for our one-byte compressed/didn't-compress prefix byte. */
123  frame_add_to_extra_frame(frame, COMP_PREFIX_LEN);
124 }
125 
126 void
127 comp_add_to_extra_buffer(struct frame *frame)
128 {
129  /* Leave room for compression buffer to expand in worst case scenario
130  * where data is totally uncompressible */
131  frame_add_to_extra_buffer(frame, COMP_EXTRA_BUFFER(EXPANDED_SIZE(frame)));
132 }
133 
134 void
135 comp_print_stats(const struct compress_context *compctx, struct status_output *so)
136 {
137  if (compctx)
138  {
139  status_printf(so, "pre-compress bytes," counter_format, compctx->pre_compress);
140  status_printf(so, "post-compress bytes," counter_format, compctx->post_compress);
141  status_printf(so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
142  status_printf(so, "post-decompress bytes," counter_format, compctx->post_decompress);
143  }
144 }
145 
146 /*
147  * Tell our peer which compression algorithms we support.
148  */
149 void
150 comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out)
151 {
152  if (opt)
153  {
154  bool lzo_avail = false;
155  if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY))
156  {
157 #if defined(ENABLE_LZ4)
158  buf_printf(out, "IV_LZ4=1\n");
159  buf_printf(out, "IV_LZ4v2=1\n");
160 #endif
161 #if defined(ENABLE_LZO)
162  buf_printf(out, "IV_LZO=1\n");
163  lzo_avail = true;
164 #endif
165  }
166  if (!lzo_avail)
167  {
168  buf_printf(out, "IV_LZO_STUB=1\n");
169  }
170  buf_printf(out, "IV_COMP_STUB=1\n");
171  buf_printf(out, "IV_COMP_STUBv2=1\n");
172  buf_printf(out, "IV_TCPNL=1\n");
173  }
174 }
175 
176 #endif /* USE_COMP */
static void frame_add_to_extra_buffer(struct frame *frame, const int increment)
Definition: mtu.h:298
Packet geometry parameters.
Definition: mtu.h:93
static void frame_add_to_extra_frame(struct frame *frame, const unsigned int increment)
Definition: mtu.h:274
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:245
#define ASSERT(x)
Definition: error.h:221
void status_printf(struct status_output *so, const char *format,...)
Definition: status.c:239
#define BPTR(buf)
Definition: buffer.h:124
static uint8_t * buf_prepend(struct buffer *buf, int size)
Definition: buffer.h:627
#define counter_format
Definition: common.h:39
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1050
#define EXPANDED_SIZE(f)
Definition: mtu.h:172
unsigned __int8 uint8_t
Definition: config-msvc.h:123
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
#define free
Definition: cmocka.c:1850