~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to src/openvpn/lzo.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2010 OpenVPN Technologies, 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
 
20
 *  along with this program (see the file COPYING included with this
 
21
 *  distribution); if not, write to the Free Software Foundation, Inc.,
 
22
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
 
 
25
/**
 
26
 * @file Data Channel Compression module function definitions.
 
27
 */
 
28
 
 
29
#ifdef HAVE_CONFIG_H
 
30
#include "config.h"
 
31
#elif defined(_MSC_VER)
 
32
#include "config-msvc.h"
 
33
#endif
 
34
 
 
35
#include "syshead.h"
 
36
 
 
37
#ifdef ENABLE_LZO
 
38
 
 
39
#include "lzo.h"
 
40
#include "error.h"
 
41
#include "otime.h"
 
42
 
 
43
#include "memdbg.h"
 
44
 
 
45
#ifndef ENABLE_LZO_STUB
 
46
/**
 
47
 * Perform adaptive compression housekeeping.
 
48
 *
 
49
 * @param ac the adaptive compression state structure.
 
50
 *
 
51
 * @return
 
52
 */
 
53
static bool
 
54
lzo_adaptive_compress_test (struct lzo_adaptive_compress *ac)
 
55
{
 
56
  const bool save = ac->compress_state;
 
57
  const time_t local_now = now;
 
58
 
 
59
  if (!ac->compress_state)
 
60
    {
 
61
      if (local_now >= ac->next)
 
62
        {
 
63
          if (ac->n_total > AC_MIN_BYTES
 
64
              && (ac->n_total - ac->n_comp) < (ac->n_total / (100 / AC_SAVE_PCT)))
 
65
            {
 
66
              ac->compress_state = true;
 
67
              ac->next = local_now + AC_OFF_SEC;
 
68
            }
 
69
          else
 
70
            {
 
71
              ac->next = local_now + AC_SAMP_SEC;
 
72
            }
 
73
          dmsg (D_COMP, "lzo_adaptive_compress_test: comp=%d total=%d", ac->n_comp, ac->n_total);
 
74
          ac->n_total = ac->n_comp = 0;
 
75
        }
 
76
    }
 
77
  else 
 
78
    {
 
79
      if (local_now >= ac->next)
 
80
        {
 
81
          ac->next = local_now + AC_SAMP_SEC;
 
82
          ac->n_total = ac->n_comp = 0;
 
83
          ac->compress_state = false;
 
84
        }
 
85
    }
 
86
 
 
87
  if (ac->compress_state != save)
 
88
    dmsg (D_COMP_LOW, "Adaptive compression state %s", (ac->compress_state ? "OFF" : "ON"));
 
89
 
 
90
  return !ac->compress_state;
 
91
}
 
92
 
 
93
static inline void
 
94
lzo_adaptive_compress_data (struct lzo_adaptive_compress *ac, int n_total, int n_comp)
 
95
{
 
96
  ac->n_total += n_total;
 
97
  ac->n_comp += n_comp;
 
98
}
 
99
 
 
100
#endif /* ENABLE_LZO_STUB */
 
101
 
 
102
void lzo_adjust_frame_parameters (struct frame *frame)
 
103
{
 
104
  /* Leave room for our one-byte compressed/didn't-compress prefix byte. */
 
105
  frame_add_to_extra_frame (frame, LZO_PREFIX_LEN);
 
106
 
 
107
  /* Leave room for compression buffer to expand in worst case scenario
 
108
     where data is totally uncompressible */
 
109
  frame_add_to_extra_buffer (frame, LZO_EXTRA_BUFFER (EXPANDED_SIZE(frame)));
 
110
}
 
111
 
 
112
void
 
113
lzo_compress_init (struct lzo_compress_workspace *lzowork, unsigned int flags)
 
114
{
 
115
  CLEAR (*lzowork);
 
116
 
 
117
  lzowork->flags = flags;
 
118
#ifndef ENABLE_LZO_STUB
 
119
  lzowork->wmem_size = LZO_WORKSPACE;
 
120
 
 
121
  if (lzo_init () != LZO_E_OK)
 
122
    msg (M_FATAL, "Cannot initialize LZO compression library");
 
123
  lzowork->wmem = (lzo_voidp) lzo_malloc (lzowork->wmem_size);
 
124
  check_malloc_return (lzowork->wmem);
 
125
  msg (D_INIT_MEDIUM, "LZO compression initialized");
 
126
#else
 
127
  msg (D_INIT_MEDIUM, "LZO stub compression initialized");
 
128
#endif
 
129
  lzowork->defined = true;
 
130
}
 
131
 
 
132
void
 
133
lzo_compress_uninit (struct lzo_compress_workspace *lzowork)
 
134
{
 
135
  if (lzowork)
 
136
    {
 
137
      ASSERT (lzowork->defined);
 
138
#ifndef ENABLE_LZO_STUB
 
139
      lzo_free (lzowork->wmem);
 
140
      lzowork->wmem = NULL;
 
141
#endif
 
142
      lzowork->defined = false;
 
143
    }
 
144
}
 
145
 
 
146
static inline bool
 
147
lzo_compression_enabled (struct lzo_compress_workspace *lzowork)
 
148
{
 
149
#ifndef ENABLE_LZO_STUB
 
150
  if ((lzowork->flags & (LZO_SELECTED|LZO_ON)) == (LZO_SELECTED|LZO_ON))
 
151
    {
 
152
      if (lzowork->flags & LZO_ADAPTIVE)
 
153
        return lzo_adaptive_compress_test (&lzowork->ac);
 
154
      else
 
155
        return true;
 
156
    }
 
157
#endif
 
158
  return false;
 
159
}
 
160
 
 
161
void
 
162
lzo_compress (struct buffer *buf, struct buffer work,
 
163
              struct lzo_compress_workspace *lzowork,
 
164
              const struct frame* frame)
 
165
{
 
166
#ifndef ENABLE_LZO_STUB
 
167
  lzo_uint zlen = 0;
 
168
  int err;
 
169
  bool compressed = false;
 
170
#endif
 
171
 
 
172
  ASSERT (lzowork->defined);
 
173
 
 
174
  if (buf->len <= 0)
 
175
    return;
 
176
 
 
177
#ifndef ENABLE_LZO_STUB
 
178
  /*
 
179
   * In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
 
180
   * and our adaptive level must give the OK.
 
181
   */
 
182
  if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (lzowork))
 
183
    {
 
184
      ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
 
185
      ASSERT (buf_safe (&work, LZO_EXTRA_BUFFER (PAYLOAD_SIZE (frame))));
 
186
 
 
187
      if (!(buf->len <= PAYLOAD_SIZE (frame)))
 
188
        {
 
189
          dmsg (D_COMP_ERRORS, "LZO compression buffer overflow");
 
190
          buf->len = 0;
 
191
          return;
 
192
        }
 
193
 
 
194
      err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, lzowork->wmem);
 
195
      if (err != LZO_E_OK)
 
196
        {
 
197
          dmsg (D_COMP_ERRORS, "LZO compression error: %d", err);
 
198
          buf->len = 0;
 
199
          return;
 
200
        }
 
201
 
 
202
      ASSERT (buf_safe (&work, zlen));
 
203
      work.len = zlen;
 
204
      compressed = true;
 
205
 
 
206
      dmsg (D_COMP, "compress %d -> %d", buf->len, work.len);
 
207
      lzowork->pre_compress += buf->len;
 
208
      lzowork->post_compress += work.len;
 
209
 
 
210
      /* tell adaptive level about our success or lack thereof in getting any size reduction */
 
211
      if (lzowork->flags & LZO_ADAPTIVE)
 
212
        lzo_adaptive_compress_data (&lzowork->ac, buf->len, work.len);
 
213
    }
 
214
 
 
215
  /* did compression save us anything ? */
 
216
  if (compressed && work.len < buf->len)
 
217
    {
 
218
      uint8_t *header = buf_prepend (&work, 1);
 
219
      *header = YES_COMPRESS;
 
220
      *buf = work;
 
221
    }
 
222
  else
 
223
#endif
 
224
    {
 
225
      uint8_t *header = buf_prepend (buf, 1);
 
226
      *header = NO_COMPRESS;
 
227
    }
 
228
}
 
229
 
 
230
void
 
231
lzo_decompress (struct buffer *buf, struct buffer work,
 
232
                struct lzo_compress_workspace *lzowork,
 
233
                const struct frame* frame)
 
234
{
 
235
#ifndef ENABLE_LZO_STUB
 
236
  lzo_uint zlen = EXPANDED_SIZE (frame);
 
237
  int err;
 
238
#endif
 
239
  uint8_t c;            /* flag indicating whether or not our peer compressed */
 
240
 
 
241
  ASSERT (lzowork->defined);
 
242
 
 
243
  if (buf->len <= 0)
 
244
    return;
 
245
 
 
246
  ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
 
247
 
 
248
  c = *BPTR (buf);
 
249
  ASSERT (buf_advance (buf, 1));
 
250
 
 
251
  if (c == YES_COMPRESS)        /* packet was compressed */
 
252
    {
 
253
#ifndef ENABLE_LZO_STUB
 
254
      ASSERT (buf_safe (&work, zlen));
 
255
      err = LZO_DECOMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen,
 
256
                            lzowork->wmem);
 
257
      if (err != LZO_E_OK)
 
258
        {
 
259
          dmsg (D_COMP_ERRORS, "LZO decompression error: %d", err);
 
260
          buf->len = 0;
 
261
          return;
 
262
        }
 
263
 
 
264
      ASSERT (buf_safe (&work, zlen));
 
265
      work.len = zlen;
 
266
 
 
267
      dmsg (D_COMP, "decompress %d -> %d", buf->len, work.len);
 
268
      lzowork->pre_decompress += buf->len;
 
269
      lzowork->post_decompress += work.len;
 
270
 
 
271
      *buf = work;
 
272
#else
 
273
      dmsg (D_COMP_ERRORS, "LZO decompression error: LZO capability not compiled");
 
274
      buf->len = 0;
 
275
      return;
 
276
#endif
 
277
    }
 
278
  else if (c == NO_COMPRESS)    /* packet was not compressed */
 
279
    {
 
280
      ;
 
281
    }
 
282
  else
 
283
    {
 
284
      dmsg (D_COMP_ERRORS, "Bad LZO decompression header byte: %d", c);
 
285
      buf->len = 0;
 
286
    }
 
287
}
 
288
 
 
289
void
 
290
lzo_modify_flags (struct lzo_compress_workspace *lzowork, unsigned int flags)
 
291
{
 
292
  ASSERT (lzowork->defined);
 
293
  lzowork->flags = flags;
 
294
}
 
295
 
 
296
void lzo_print_stats (const struct lzo_compress_workspace *lzo_compwork, struct status_output *so)
 
297
{
 
298
  ASSERT (lzo_compwork->defined);
 
299
 
 
300
#ifndef ENABLE_LZO_STUB
 
301
  status_printf (so, "pre-compress bytes," counter_format, lzo_compwork->pre_compress);
 
302
  status_printf (so, "post-compress bytes," counter_format, lzo_compwork->post_compress);
 
303
  status_printf (so, "pre-decompress bytes," counter_format, lzo_compwork->pre_decompress);
 
304
  status_printf (so, "post-decompress bytes," counter_format, lzo_compwork->post_decompress);
 
305
#endif
 
306
}
 
307
 
 
308
#else
 
309
static void dummy(void) {}
 
310
#endif /* ENABLE_LZO */