Ticket #271: 0002-Added-support-for-the-Snappy-compression-algorithm.patch

File 0002-Added-support-for-the-Snappy-compression-algorithm.patch, 61.4 KB (added by Gert Döring, 11 years ago)

patch to current git master branch, tested both as a client and as "openvpn-in-AS".

  • configure.ac

    From 45f43a41caf14692e908cc83dbeb9767b7375af3 Mon Sep 17 00:00:00 2001
    From: James Yonan <james@openvpn.net>
    Date: Tue, 18 Sep 2012 08:33:34 +0200
    Subject: [PATCH 2/2] Added support for the Snappy compression algorithm
    
    Added support for the Snappy compression algorithm which has shown to
    have considerably better compression speed than LZO at a comparable
    compression ratio.
    
    To enable Snappy add:
    
      compress snappy
    
    to both client and server config files.
    
    Alternatively, enable compression framing on the client:
    
      compress
    
    and have the server selectively push "compress snappy" to the client.
    
    This change also extends the client capability handshake to include
    IV_SNAPPY so the server can be aware that a connecting client supports
    Snappy.
    
    Note that the Snappy implementation also includes an improved framing
    approach where the first byte of the compressed payload is replaced by
    the compression control byte (the first payload byte is moved to the end
    of the packet).  This solves off-by-one alignment issues, which improves
    performance on ARM.
    
    By default, the configure script will try to build with Snappy support.
    To disable, use the --disable-snappy option.
    
    The --enable-lzo-stub configure directive is now --enable-comp-stub
    (because it's not actually "lzo" but "compression-enabled packet framing")
    
    Add compression overhead to extra buffer unconditionally, as long
    as USE_COMP is defined.
    
    OpenVPN SVN r8206 (2.1.21a) and r8212 (2.1.21b)
    
    Signed-off-by: Gert Doering <gert@greenie.muc.de>
    ---
     configure.ac             |  65 ++++++++++++--
     doc/openvpn.8            |  22 ++++-
     src/openvpn/Makefile.am  |   4 +
     src/openvpn/comp.c       | 135 ++++++++++++++++++++++++++++
     src/openvpn/comp.h       | 171 ++++++++++++++++++++++++++++++++++++
     src/openvpn/compstub.c   | 118 +++++++++++++++++++++++++
     src/openvpn/forward.c    |  12 +--
     src/openvpn/init.c       | 100 +++++++++++++++------
     src/openvpn/lzo.c        | 154 +++++++++++---------------------
     src/openvpn/lzo.h        | 222 +----------------------------------------------
     src/openvpn/openvpn.h    |  16 ++--
     src/openvpn/options.c    | 100 +++++++++++++++++----
     src/openvpn/options.h    |   7 +-
     src/openvpn/sig.c        |   6 +-
     src/openvpn/snappy.c     | 189 ++++++++++++++++++++++++++++++++++++++++
     src/openvpn/snappy.h     |  39 +++++++++
     src/openvpn/ssl.c        |   6 +-
     src/openvpn/ssl_common.h |   5 ++
     src/openvpn/syshead.h    |   7 ++
     19 files changed, 975 insertions(+), 403 deletions(-)
     create mode 100644 src/openvpn/comp.c
     create mode 100644 src/openvpn/comp.h
     create mode 100644 src/openvpn/compstub.c
     create mode 100644 src/openvpn/snappy.c
     create mode 100644 src/openvpn/snappy.h
    
    diff --git a/configure.ac b/configure.ac
    index 7b35e50..5da5772 100644
    a b AC_ARG_ENABLE( 
    4646        [enable_lzo="yes"]
    4747)
    4848
    49 AC_ARG_ENABLE(
    50         [lzo-stub],
    51         [AS_HELP_STRING([--enable-lzo-stub], [don't compile LZO compression support but still allow limited interoperability with LZO-enabled peers @<:@default=no@:>@])],
    52         ,
    53         [enable_lzo_stub="no"]
     49AC_ARG_ENABLE(snappy,
     50        [  --disable-snappy        Disable Snappy compression support],
     51        [enable_snappy="$enableval"],
     52        [enable_snappy="yes"]
     53)
     54
     55AC_ARG_ENABLE(comp-stub,
     56        [  --enable-comp-stub      Don't compile compression support but still allow limited interoperability with compression-enabled peers],
     57        [enable_comp_stub="$enableval"],
     58        [enable_comp_stub="no"]
    5459)
    5560
    5661AC_ARG_ENABLE(
    if test "${have_lzo}" = "yes"; then 
    895900        CFLAGS="${saved_CFLAGS}"
    896901fi
    897902
     903dnl
     904dnl check for Snappy library
     905dnl
     906
     907AC_ARG_VAR([SNAPPY_CFLAGS], [C compiler flags for snappy])
     908AC_ARG_VAR([SNAPPY_LIBS], [linker flags for snappy])
     909if test "$enable_snappy" = "yes" && test "$enable_comp_stub" = "no"; then
     910    AC_CHECKING([for Snappy Library and Header files])
     911    havesnappylib=1
     912
     913    # if SNAPPY_LIBS is set, we assume it will work, otherwise test
     914    if test -z "${SNAPPY_LIBS}"; then
     915        AC_CHECK_LIB(snappy, snappy_compress,
     916            [ SNAPPY_LIBS="-lsnappy" ],
     917            [
     918                AC_MSG_RESULT([Snappy library not found.])
     919                havesnappylib=0
     920            ])
     921    fi
     922
     923    saved_CFLAGS="${CFLAGS}"
     924    CFLAGS="${CFLAGS} ${SNAPPY_CFLAGS}"
     925    AC_CHECK_HEADER(snappy-c.h,
     926       ,
     927       [
     928           AC_MSG_RESULT([Snappy headers not found.])
     929           havesnappylib=0
     930       ])
     931
     932    if test $havesnappylib = 0 ; then
     933        AC_MSG_RESULT([Snappy library available from http://code.google.com/p/snappy/])
     934        AC_MSG_ERROR([Or try ./configure --disable-snappy OR ./configure --enable-comp-stub])
     935    fi
     936    OPTIONAL_SNAPPY_CFLAGS="${SNAPPY_CFLAGS}"
     937    OPTIONAL_SNAPPY_LIBS="${SNAPPY_LIBS}"
     938    AC_DEFINE(ENABLE_SNAPPY, 1, [Enable Snappy compression library])
     939    CFLAGS="${saved_CFLAGS}"
     940fi
     941
     942
    898943AC_MSG_CHECKING([git checkout])
    899944GIT_CHECKOUT="no"
    900945if test -n "${GIT}" -a -d "${srcdir}/.git"; then
    if test "${enable_lzo}" = "yes"; then 
    10031048        OPTIONAL_LZO_LIBS="${LZO_LIBS}"
    10041049        AC_DEFINE([ENABLE_LZO], [1], [Enable LZO compression library])
    10051050fi
    1006 if test "${enable_lzo_stub}" = "yes"; then
    1007         test "${enable_lzo}" = "yes" && AC_MSG_ERROR([Cannot have both lzo stub and lzo enabled])
    1008         AC_DEFINE([ENABLE_LZO_STUB], [1], [Enable LZO stub capability])
    1009         AC_DEFINE([ENABLE_LZO], [1], [Enable LZO compression library])
     1051if test "${enable_comp_stub}" = "yes"; then
     1052        test "${enable_lzo}" = "yes" && AC_MSG_ERROR([Cannot have both comp stub and lzo enabled (use --disable-lzo)])
     1053        test "${enable_snappy}" = "yes" && AC_MSG_ERROR([Cannot have both comp stub and snappy enabled (use --disable-snappy)])
     1054        AC_DEFINE([ENABLE_COMP_STUB], [1], [Enable compression stub capability])
    10101055fi
    10111056
    10121057if test "${enable_pkcs11}" = "yes"; then
    AC_SUBST([OPTIONAL_CRYPTO_CFLAGS]) 
    10601105AC_SUBST([OPTIONAL_CRYPTO_LIBS])
    10611106AC_SUBST([OPTIONAL_LZO_CFLAGS])
    10621107AC_SUBST([OPTIONAL_LZO_LIBS])
     1108AC_SUBST([OPTIONAL_SNAPPY_CFLAGS])
     1109AC_SUBST([OPTIONAL_SNAPPY_LIBS])
    10631110AC_SUBST([OPTIONAL_PKCS11_HELPER_CFLAGS])
    10641111AC_SUBST([OPTIONAL_PKCS11_HELPER_LIBS])
    10651112
  • doc/openvpn.8

    diff --git a/doc/openvpn.8 b/doc/openvpn.8
    index d590714..cab1ed7 100644
    a b consecutive messages in the same category. This is useful to 
    23522352limit repetitive logging of similar message types.
    23532353.\"*********************************************************
    23542354.TP
     2355.B \-\-compress [algorithm]
     2356Enable a compression algorithm.
     2357
     2358The
     2359.B algorithm
     2360parameter may be "snappy", "lzo", or empty.  Snappy and LZO
     2361are different compression algorithms, with Snappy generally
     2362offering the best performance.
     2363
     2364If the
     2365.B algorithm
     2366parameter is empty, compression will be turned off, but the packet
     2367framing for compression will still be enabled, allowing a different
     2368setting to be pushed later.
     2369.\"*********************************************************
     2370.TP
    23552371.B \-\-comp-lzo [mode]
    2356 Use fast LZO compression \-\- may add up to 1 byte per
     2372Use LZO compression \-\- may add up to 1 byte per
    23572373packet for incompressible data.
    23582374.B mode
    23592375may be "yes", "no", or "adaptive" (default).
    23602376
     2377This option is deprecated in favor of the newer
     2378.B --compress
     2379option.
     2380
    23612381In a server mode setup, it is possible to selectively turn
    23622382compression on or off for individual clients.
    23632383
  • src/openvpn/Makefile.am

    diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am
    index 5d38628..70e19c2 100644
    a b AM_CFLAGS = \ 
    2626        $(TAP_CFLAGS) \
    2727        $(OPTIONAL_CRYPTO_CFLAGS) \
    2828        $(OPTIONAL_LZO_CFLAGS) \
     29        $(OPTIONAL_SNAPPY_CFLAGS) \
    2930        $(OPTIONAL_PKCS11_HELPER_CFLAGS)
    3031if WIN32
    3132# we want unicode entry point but not the macro
    openvpn_SOURCES = \ 
    4142        circ_list.h \
    4243        clinat.c clinat.h \
    4344        common.h \
     45        comp.c comp.h compstub.c \
    4446        crypto.c crypto.h crypto_backend.h \
    4547        crypto_openssl.c crypto_openssl.h \
    4648        crypto_polarssl.c crypto_polarssl.h \
    openvpn_SOURCES = \ 
    98100        session_id.c session_id.h \
    99101        shaper.c shaper.h \
    100102        sig.c sig.h \
     103        snappy.c snappy.h \
    101104        socket.c socket.h \
    102105        socks.c socks.h \
    103106        ssl.c ssl.h  ssl_backend.h \
    openvpn_LDADD = \ 
    116119        $(top_builddir)/src/compat/libcompat.la \
    117120        $(SOCKETS_LIBS) \
    118121        $(OPTIONAL_LZO_LIBS) \
     122        $(OPTIONAL_SNAPPY_LIBS) \
    119123        $(OPTIONAL_PKCS11_HELPER_LIBS) \
    120124        $(OPTIONAL_CRYPTO_LIBS) \
    121125        $(OPTIONAL_SELINUX_LIBS) \
  • new file src/openvpn/comp.c

    diff --git a/src/openvpn/comp.c b/src/openvpn/comp.c
    new file mode 100644
    index 0000000..9692257
    - +  
     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-2012 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#ifdef HAVE_CONFIG_H
     26#include "config.h"
     27#elif defined(_MSC_VER)
     28#include "config-msvc.h"
     29#endif
     30
     31#include "syshead.h"
     32
     33#ifdef USE_COMP
     34
     35#include "comp.h"
     36#include "error.h"
     37#include "otime.h"
     38
     39#include "memdbg.h"
     40
     41struct compress_context *
     42comp_init(const struct compress_options *opt)
     43{
     44  struct compress_context *compctx = NULL;
     45  switch (opt->alg)
     46    {
     47    case COMP_ALG_STUB:
     48      ALLOC_OBJ_CLEAR (compctx, struct compress_context);
     49      compctx->flags = opt->flags;
     50      compctx->alg = comp_stub_alg;
     51      (*compctx->alg.compress_init)(compctx);
     52      break;
     53#ifdef ENABLE_LZO
     54    case COMP_ALG_LZO:
     55      ALLOC_OBJ_CLEAR (compctx, struct compress_context);
     56      compctx->flags = opt->flags;
     57      compctx->alg = lzo_alg;
     58      (*compctx->alg.compress_init)(compctx);
     59      break;
     60#endif
     61#ifdef ENABLE_SNAPPY
     62    case COMP_ALG_SNAPPY:
     63      ALLOC_OBJ_CLEAR (compctx, struct compress_context);
     64      compctx->flags = opt->flags;
     65      compctx->alg = snappy_alg;
     66      (*compctx->alg.compress_init)(compctx);
     67      break;
     68#endif
     69    }
     70  return compctx;
     71}
     72
     73void
     74comp_uninit(struct compress_context *compctx)
     75{
     76  if (compctx)
     77    {
     78      (*compctx->alg.compress_uninit)(compctx);
     79      free(compctx);
     80    }
     81}
     82
     83void
     84comp_add_to_extra_frame(struct frame *frame)
     85{
     86  /* Leave room for our one-byte compressed/didn't-compress prefix byte. */
     87  frame_add_to_extra_frame (frame, COMP_PREFIX_LEN);
     88}
     89
     90void
     91comp_add_to_extra_buffer(struct frame *frame)
     92{
     93  /* Leave room for compression buffer to expand in worst case scenario
     94     where data is totally uncompressible */
     95  frame_add_to_extra_buffer (frame, COMP_EXTRA_BUFFER (EXPANDED_SIZE(frame)));
     96}
     97
     98void
     99comp_print_stats (const struct compress_context *compctx, struct status_output *so)
     100{
     101  if (compctx)
     102    {
     103      status_printf (so, "pre-compress bytes," counter_format, compctx->pre_compress);
     104      status_printf (so, "post-compress bytes," counter_format, compctx->post_compress);
     105      status_printf (so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
     106      status_printf (so, "post-decompress bytes," counter_format, compctx->post_decompress);
     107    }
     108}
     109
     110/*
     111 * Tell our peer which compression algorithms we support.
     112 */
     113void
     114comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out)
     115{
     116  if (opt)
     117    {
     118      bool lzo_avail = false;
     119      if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY))
     120        {
     121#if defined(ENABLE_SNAPPY)
     122          buf_printf (out, "IV_SNAPPY=1\n");
     123#endif
     124#if defined(ENABLE_LZO)
     125          buf_printf (out, "IV_LZO=1\n");
     126          lzo_avail = true;
     127#endif
     128        }
     129      if (!lzo_avail)
     130        buf_printf (out, "IV_LZO_STUB=1\n");
     131      buf_printf (out, "IV_COMP_STUB=1\n");
     132    }
     133}
     134
     135#endif /* USE_COMP */
  • new file src/openvpn/comp.h

    diff --git a/src/openvpn/comp.h b/src/openvpn/comp.h
    new file mode 100644
    index 0000000..0d2f1bc
    - +  
     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-2012 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 * Generic compression support.  Currently we support
     27 * Snappy and LZO 2.
     28 */
     29#ifndef OPENVPN_COMP_H
     30#define OPENVPN_COMP_H
     31
     32#ifdef USE_COMP
     33
     34#include "buffer.h"
     35#include "mtu.h"
     36#include "common.h"
     37#include "status.h"
     38
     39/* algorithms */
     40#define COMP_ALG_UNDEF  0
     41#define COMP_ALG_STUB   1 /* support compression command byte and framing without actual compression */
     42#define COMP_ALG_LZO    2 /* LZO algorithm */
     43#define COMP_ALG_SNAPPY 3 /* Snappy algorithm */
     44
     45/* Compression flags */
     46#define COMP_F_ADAPTIVE   (1<<0) /* COMP_ALG_LZO only */
     47#define COMP_F_ASYM       (1<<1) /* only downlink is compressed, not uplink */
     48#define COMP_F_SWAP       (1<<2) /* initial command byte is swapped with last byte in buffer to preserve payload alignment */
     49#define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only support compression stubs */
     50
     51/*
     52 * Length of prepended prefix on compressed packets
     53 */
     54#define COMP_PREFIX_LEN 1
     55
     56/*
     57 * Prefix bytes
     58 */
     59#define NO_COMPRESS_BYTE      0xFA
     60#define NO_COMPRESS_BYTE_SWAP 0xFB /* to maintain payload alignment, replace this byte with last byte of packet */
     61
     62/*
     63 * Compress worst case size expansion (for any algorithm)
     64 *
     65 * LZO:    len + len/8 + 128 + 3
     66 * Snappy: len + len/6 + 32
     67 */
     68#define COMP_EXTRA_BUFFER(len) ((len)/6 + 128 + 3 + COMP_PREFIX_LEN)
     69
     70/*
     71 * Don't try to compress any packet smaller than this.
     72 */
     73#define COMPRESS_THRESHOLD 100
     74
     75/* Forward declaration of compression context */
     76struct compress_context;
     77
     78/*
     79 * Virtual methods and other static info for each compression algorithm
     80 */
     81struct compress_alg
     82{
     83  const char *name;
     84  void (*compress_init)(struct compress_context *compctx);
     85  void (*compress_uninit)(struct compress_context *compctx);
     86  void (*compress)(struct buffer *buf, struct buffer work,
     87                   struct compress_context *compctx,
     88                   const struct frame* frame);
     89
     90  void (*decompress)(struct buffer *buf, struct buffer work,
     91                     struct compress_context *compctx,
     92                     const struct frame* frame);
     93};
     94
     95/*
     96 * Headers for each compression implementation
     97 */
     98#ifdef ENABLE_LZO
     99#include "lzo.h"
     100#endif
     101
     102#ifdef ENABLE_SNAPPY
     103#include "snappy.h"
     104#endif
     105
     106/*
     107 * Information that basically identifies a compression
     108 * algorithm and related flags.
     109 */
     110struct compress_options
     111{
     112  int alg;
     113  unsigned int flags;
     114};
     115
     116/*
     117 * Workspace union of all supported compression algorithms
     118 */
     119union compress_workspace_union
     120{
     121#ifdef ENABLE_LZO
     122  struct lzo_compress_workspace lzo;
     123#endif
     124#ifdef ENABLE_SNAPPY
     125  struct snappy_workspace snappy;
     126#endif
     127};
     128
     129/*
     130 * Context for active compression session
     131 */
     132struct compress_context
     133{
     134  unsigned int flags;
     135  struct compress_alg alg;
     136  union compress_workspace_union wu;
     137
     138  /* statistics */
     139  counter_type pre_decompress;
     140  counter_type post_decompress;
     141  counter_type pre_compress;
     142  counter_type post_compress;
     143};
     144
     145extern const struct compress_alg comp_stub_alg;
     146
     147struct compress_context *comp_init(const struct compress_options *opt);
     148
     149void comp_uninit(struct compress_context *compctx);
     150
     151void comp_add_to_extra_frame(struct frame *frame);
     152void comp_add_to_extra_buffer(struct frame *frame);
     153
     154void comp_print_stats (const struct compress_context *compctx, struct status_output *so);
     155
     156void comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out);
     157
     158static inline bool
     159comp_enabled(const struct compress_options *info)
     160{
     161  return info->alg != COMP_ALG_UNDEF;
     162}
     163
     164static inline bool
     165comp_unswapped_prefix(const struct compress_options *info)
     166{
     167  return !(info->flags & COMP_F_SWAP);
     168}
     169
     170#endif /* USE_COMP */
     171#endif
  • new file src/openvpn/compstub.c

    diff --git a/src/openvpn/compstub.c b/src/openvpn/compstub.c
    new file mode 100644
    index 0000000..2ab7163
    - +  
     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-2012 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#ifdef HAVE_CONFIG_H
     26#include "config.h"
     27#elif defined(_MSC_VER)
     28#include "config-msvc.h"
     29#endif
     30
     31#include "syshead.h"
     32
     33#if defined(USE_COMP)
     34
     35#include "comp.h"
     36#include "error.h"
     37#include "otime.h"
     38
     39#include "memdbg.h"
     40
     41static void
     42stub_compress_init (struct compress_context *compctx)
     43{
     44}
     45
     46static void
     47stub_compress_uninit (struct compress_context *compctx)
     48{
     49}
     50
     51static void
     52stub_compress (struct buffer *buf, struct buffer work,
     53               struct compress_context *compctx,
     54               const struct frame* frame)
     55{
     56  if (buf->len <= 0)
     57    return;
     58  if (compctx->flags & COMP_F_SWAP)
     59    {
     60      uint8_t *head = BPTR (buf);
     61      uint8_t *tail  = BEND (buf);
     62      ASSERT (buf_safe (buf, 1));
     63      ++buf->len;
     64
     65      /* move head byte of payload to tail */
     66      *tail = *head;
     67      *head = NO_COMPRESS_BYTE_SWAP;
     68    }
     69  else
     70    {
     71      uint8_t *header = buf_prepend (buf, 1);
     72      *header = NO_COMPRESS_BYTE;
     73    }
     74}
     75
     76static void
     77stub_decompress (struct buffer *buf, struct buffer work,
     78                 struct compress_context *compctx,
     79                 const struct frame* frame)
     80{
     81  uint8_t c;
     82  if (buf->len <= 0)
     83    return;
     84  if (compctx->flags & COMP_F_SWAP)
     85    {
     86      uint8_t *head = BPTR (buf);
     87      c = *head;
     88      --buf->len;
     89      *head = *BEND (buf);
     90      if (c != NO_COMPRESS_BYTE_SWAP)
     91        {
     92          dmsg (D_COMP_ERRORS, "Bad compression stub (swap) decompression header byte: %d", c);
     93          buf->len = 0;
     94        }
     95    }
     96  else
     97    {
     98      c = *BPTR (buf);
     99      ASSERT (buf_advance (buf, 1));
     100      if (c != NO_COMPRESS_BYTE)
     101        {
     102          dmsg (D_COMP_ERRORS, "Bad compression stub decompression header byte: %d", c);
     103          buf->len = 0;
     104        }
     105    }
     106}
     107
     108const struct compress_alg comp_stub_alg = {
     109  "stub",
     110  stub_compress_init,
     111  stub_compress_uninit,
     112  stub_compress,
     113  stub_decompress
     114};
     115
     116#else
     117static void dummy(void) {}
     118#endif /* USE_STUB */
  • src/openvpn/forward.c

    diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
    index 024cd58..447b86d 100644
    a b encrypt_sign (struct context *c, bool comp_frag) 
    444444
    445445  if (comp_frag)
    446446    {
    447 #ifdef ENABLE_LZO
     447#ifdef USE_COMP
    448448      /* Compress the packet. */
    449       if (lzo_defined (&c->c2.lzo_compwork))
    450         lzo_compress (&c->c2.buf, b->lzo_compress_buf, &c->c2.lzo_compwork, &c->c2.frame);
     449      if (c->c2.comp_context)
     450        (*c->c2.comp_context->alg.compress)(&c->c2.buf, b->compress_buf, c->c2.comp_context, &c->c2.frame);
    451451#endif
    452452#ifdef ENABLE_FRAGMENT
    453453      if (c->c2.fragment)
    process_incoming_link (struct context *c) 
    846846        fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);
    847847#endif
    848848
    849 #ifdef ENABLE_LZO
     849#ifdef USE_COMP
    850850      /* decompress the incoming packet */
    851       if (lzo_defined (&c->c2.lzo_compwork))
    852         lzo_decompress (&c->c2.buf, c->c2.buffers->lzo_decompress_buf, &c->c2.lzo_compwork, &c->c2.frame);
     851      if (c->c2.comp_context)
     852        (*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf, c->c2.comp_context, &c->c2.frame);
    853853#endif
    854854
    855855#ifdef PACKET_TRUNCATION_CHECK
  • src/openvpn/init.c

    diff --git a/src/openvpn/init.c b/src/openvpn/init.c
    index 979ba23..16501fd 100644
    a b do_deferred_options (struct context *c, const unsigned int found) 
    17461746    }
    17471747#endif
    17481748
    1749 #ifdef ENABLE_LZO
     1749#ifdef USE_COMP
    17501750  if (found & OPT_P_COMP)
    17511751    {
    1752       if (lzo_defined (&c->c2.lzo_compwork))
    1753         {
    1754           msg (D_PUSH, "OPTIONS IMPORT: LZO parms modified");
    1755           lzo_modify_flags (&c->c2.lzo_compwork, c->options.lzo);
    1756         }
     1752      msg (D_PUSH, "OPTIONS IMPORT: compression parms modified");
     1753      comp_uninit (c->c2.comp_context);
     1754      c->c2.comp_context = comp_init (&c->options.comp);
    17571755    }
    17581756#endif
    17591757
    do_init_crypto_tls (struct context *c, const unsigned int flags) 
    22482246#endif
    22492247#endif
    22502248
     2249#ifdef USE_COMP
     2250  to.comp_options = options->comp;
     2251#endif
     2252
    22512253  /* TLS handshake authentication (--tls-auth) */
    22522254  if (options->tls_auth_file)
    22532255    {
    do_init_crypto (struct context *c, const unsigned int flags) 
    23302332static void
    23312333do_init_frame (struct context *c)
    23322334{
    2333 #ifdef ENABLE_LZO
     2335#ifdef USE_COMP
    23342336  /*
    2335    * Initialize LZO compression library.
     2337   * modify frame parameters if compression is enabled
    23362338   */
    2337   if (c->options.lzo & LZO_SELECTED)
     2339  if (comp_enabled(&c->options.comp))
    23382340    {
    2339       lzo_adjust_frame_parameters (&c->c2.frame);
     2341      comp_add_to_extra_frame (&c->c2.frame);
    23402342
     2343#if !defined(ENABLE_SNAPPY)
    23412344      /*
    2342        * LZO usage affects buffer alignment.
     2345       * Compression usage affects buffer alignment when non-swapped algs
     2346       * such as LZO is used.
     2347       * Newer algs like Snappy and comp-stub with COMP_F_SWAP don't need
     2348       * any special alignment because of the control-byte swap approach.
     2349       * LZO alignment (on the other hand) is problematic because
     2350       * the presence of the control byte means that either the output of
     2351       * decryption must be written to an unaligned buffer, or the input
     2352       * to compression (or packet dispatch if packet is uncompressed)
     2353       * must be read from an unaligned buffer.
     2354       * This code tries to align the input to compression (or packet
     2355       * dispatch if packet is uncompressed) at the cost of requiring
     2356       * decryption output to be written to an unaligned buffer, so
     2357       * it's more of a tradeoff than an optimal solution and we don't
     2358       * include it when we are doing a modern build with Snappy.
     2359       * Strictly speaking, on the server it would be better to execute
     2360       * this code for every connection after we decide the compression
     2361       * method, but currently the frame code doesn't appear to be
     2362       * flexible enough for this, since the frame is already established
     2363       * before it is known which compression options will be pushed.
    23432364       */
    2344       if (CIPHER_ENABLED (c))
     2365      if (comp_unswapped_prefix (&c->options.comp) && CIPHER_ENABLED (c))
    23452366        {
    2346           frame_add_to_align_adjust (&c->c2.frame, LZO_PREFIX_LEN);
     2367          frame_add_to_align_adjust (&c->c2.frame, COMP_PREFIX_LEN);
    23472368          frame_or_align_flags (&c->c2.frame,
    23482369                                FRAME_HEADROOM_MARKER_FRAGMENT
    23492370                                |FRAME_HEADROOM_MARKER_DECRYPT);
    23502371        }
     2372#endif
    23512373
    23522374#ifdef ENABLE_FRAGMENT
    2353       lzo_adjust_frame_parameters (&c->c2.frame_fragment_omit); /* omit LZO frame delta from final frame_fragment */
     2375      comp_add_to_extra_frame (&c->c2.frame_fragment_omit); /* omit compression frame delta from final frame_fragment */
    23542376#endif
    23552377    }
    2356 #endif /* ENABLE_LZO */
     2378#endif /* USE_COMP */
    23572379
    23582380#ifdef ENABLE_SOCKS
    23592381  /*
    do_init_frame (struct context *c) 
    23822404   */
    23832405  frame_finalize_options (c, NULL);
    23842406
     2407#ifdef USE_COMP
     2408  /*
     2409   * Modify frame parameters if compression is compiled in.
     2410   * Should be called after frame_finalize_options.
     2411   */
     2412  comp_add_to_extra_buffer (&c->c2.frame);
     2413#ifdef ENABLE_FRAGMENT
     2414  comp_add_to_extra_buffer (&c->c2.frame_fragment_omit); /* omit compression frame delta from final frame_fragment */
     2415#endif
     2416#endif /* USE_COMP */
     2417
    23852418#ifdef ENABLE_FRAGMENT
    23862419  /*
    23872420   * Set frame parameter for fragment code.  This is necessary because
    init_context_buffers (const struct frame *frame) 
    25132546  b->decrypt_buf = alloc_buf (BUF_SIZE (frame));
    25142547#endif
    25152548
    2516 #ifdef ENABLE_LZO
    2517   b->lzo_compress_buf = alloc_buf (BUF_SIZE (frame));
    2518   b->lzo_decompress_buf = alloc_buf (BUF_SIZE (frame));
     2549#ifdef USE_COMP
     2550  b->compress_buf = alloc_buf (BUF_SIZE (frame));
     2551  b->decompress_buf = alloc_buf (BUF_SIZE (frame));
    25192552#endif
    25202553
    25212554  return b;
    free_context_buffers (struct context_buffers *b) 
    25302563      free_buf (&b->read_tun_buf);
    25312564      free_buf (&b->aux_buf);
    25322565
    2533 #ifdef ENABLE_LZO
    2534       free_buf (&b->lzo_compress_buf);
    2535       free_buf (&b->lzo_decompress_buf);
     2566#ifdef USE_COMP
     2567      free_buf (&b->compress_buf);
     2568      free_buf (&b->decompress_buf);
    25362569#endif
    25372570
    25382571#ifdef ENABLE_CRYPTO
    init_instance (struct context *c, const struct env_set *env, const unsigned int 
    33643397      goto sig;
    33653398  }
    33663399
    3367 #ifdef ENABLE_LZO
    3368   /* initialize LZO compression library. */
    3369   if ((options->lzo & LZO_SELECTED) && (c->mode == CM_P2P || child))
    3370     lzo_compress_init (&c->c2.lzo_compwork, options->lzo);
     3400#ifdef USE_COMP
     3401  /* initialize compression library. */
     3402  if (comp_enabled(&options->comp) && (c->mode == CM_P2P || child))
     3403    c->c2.comp_context = comp_init (&options->comp);
    33713404#endif
    33723405
    33733406  /* initialize MTU variables */
    close_instance (struct context *c) 
    34813514        /* if xinetd/inetd mode, don't allow restart */
    34823515        do_close_check_if_restart_permitted (c);
    34833516
    3484 #ifdef ENABLE_LZO
    3485         if (lzo_defined (&c->c2.lzo_compwork))
    3486           lzo_compress_uninit (&c->c2.lzo_compwork);
     3517#ifdef USE_COMP
     3518        if (c->c2.comp_context)
     3519          {
     3520            comp_uninit (c->c2.comp_context);
     3521            c->c2.comp_context = NULL;
     3522          }
    34873523#endif
    34883524
    34893525        /* free buffers */
    inherit_context_child (struct context *dest, 
    36073643      dest->c2.link_socket_info->lsa = &dest->c1.link_socket_addr;
    36083644      dest->c2.link_socket_info->connection_established = false;
    36093645    }
     3646
     3647#ifdef USE_COMP
     3648  dest->c2.comp_context = NULL;
     3649#endif
    36103650}
    36113651
    36123652void
    inherit_context_top (struct context *dest, 
    36553695  dest->c2.event_set = NULL;
    36563696  if (proto_is_dgram(src->options.ce.proto))
    36573697    do_event_set_init (dest, false);
     3698
     3699#ifdef USE_COMP
     3700  dest->c2.comp_context = NULL;
     3701#endif
    36583702}
    36593703
    36603704void
  • src/openvpn/lzo.c

    diff --git a/src/openvpn/lzo.c b/src/openvpn/lzo.c
    index 195b819..daa02ed 100644
    a b  
    3434
    3535#include "syshead.h"
    3636
    37 #ifdef ENABLE_LZO
     37#if defined(ENABLE_LZO)
    3838
    39 #include "lzo.h"
     39#include "comp.h"
    4040#include "error.h"
    4141#include "otime.h"
    4242
    4343#include "memdbg.h"
    4444
    45 #ifndef ENABLE_LZO_STUB
     45/* Initial command byte to tell our peer if we compressed */
     46#define LZO_COMPRESS_BYTE 0x66
     47
    4648/**
    4749 * Perform adaptive compression housekeeping.
    4850 *
    lzo_adaptive_compress_data (struct lzo_adaptive_compress *ac, int n_total, int n 
    9799  ac->n_comp += n_comp;
    98100}
    99101
    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)
     102static void
     103lzo_compress_init (struct compress_context *compctx)
    114104{
    115   CLEAR (*lzowork);
    116 
    117   lzowork->flags = flags;
    118 #ifndef ENABLE_LZO_STUB
    119   lzowork->wmem_size = LZO_WORKSPACE;
    120 
     105  msg (D_INIT_MEDIUM, "LZO compression initializing");
     106  ASSERT(!(compctx->flags & COMP_F_SWAP));
     107  compctx->wu.lzo.wmem_size = LZO_WORKSPACE;
    121108  if (lzo_init () != LZO_E_OK)
    122109    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;
     110  compctx->wu.lzo.wmem = (lzo_voidp) lzo_malloc (compctx->wu.lzo.wmem_size);
     111  check_malloc_return (compctx->wu.lzo.wmem);
    130112}
    131113
    132 void
    133 lzo_compress_uninit (struct lzo_compress_workspace *lzowork)
     114static void
     115lzo_compress_uninit (struct compress_context *compctx)
    134116{
    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     }
     117  lzo_free (compctx->wu.lzo.wmem);
     118  compctx->wu.lzo.wmem = NULL;
    144119}
    145120
    146121static inline bool
    147 lzo_compression_enabled (struct lzo_compress_workspace *lzowork)
     122lzo_compression_enabled (struct compress_context *compctx)
    148123{
    149 #ifndef ENABLE_LZO_STUB
    150   if ((lzowork->flags & (LZO_SELECTED|LZO_ON)) == (LZO_SELECTED|LZO_ON))
     124  if (compctx->flags & COMP_F_ASYM)
     125    return false;
     126  else
    151127    {
    152       if (lzowork->flags & LZO_ADAPTIVE)
    153         return lzo_adaptive_compress_test (&lzowork->ac);
     128      if (compctx->flags & COMP_F_ADAPTIVE)
     129        return lzo_adaptive_compress_test (&compctx->wu.lzo.ac);
    154130      else
    155131        return true;
    156132    }
    157 #endif
    158   return false;
    159133}
    160134
    161 void
     135static void
    162136lzo_compress (struct buffer *buf, struct buffer work,
    163               struct lzo_compress_workspace *lzowork,
     137              struct compress_context *compctx,
    164138              const struct frame* frame)
    165139{
    166 #ifndef ENABLE_LZO_STUB
    167140  lzo_uint zlen = 0;
    168141  int err;
    169142  bool compressed = false;
    170 #endif
    171 
    172   ASSERT (lzowork->defined);
    173143
    174144  if (buf->len <= 0)
    175145    return;
    176146
    177 #ifndef ENABLE_LZO_STUB
    178147  /*
    179148   * In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
    180149   * and our adaptive level must give the OK.
    181150   */
    182   if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (lzowork))
     151  if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (compctx))
    183152    {
     153      const size_t ps = PAYLOAD_SIZE (frame);
    184154      ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
    185       ASSERT (buf_safe (&work, LZO_EXTRA_BUFFER (PAYLOAD_SIZE (frame))));
     155      ASSERT (buf_safe (&work, ps + COMP_EXTRA_BUFFER (ps)));
    186156
    187       if (!(buf->len <= PAYLOAD_SIZE (frame)))
     157      if (buf->len > ps)
    188158        {
    189159          dmsg (D_COMP_ERRORS, "LZO compression buffer overflow");
    190160          buf->len = 0;
    191161          return;
    192162        }
    193163
    194       err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, lzowork->wmem);
     164      err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, compctx->wu.lzo.wmem);
    195165      if (err != LZO_E_OK)
    196166        {
    197167          dmsg (D_COMP_ERRORS, "LZO compression error: %d", err);
    lzo_compress (struct buffer *buf, struct buffer work, 
    203173      work.len = zlen;
    204174      compressed = true;
    205175
    206       dmsg (D_COMP, "compress %d -> %d", buf->len, work.len);
    207       lzowork->pre_compress += buf->len;
    208       lzowork->post_compress += work.len;
     176      dmsg (D_COMP, "LZO compress %d -> %d", buf->len, work.len);
     177      compctx->pre_compress += buf->len;
     178      compctx->post_compress += work.len;
    209179
    210180      /* 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);
     181      if (compctx->flags & COMP_F_ADAPTIVE)
     182        lzo_adaptive_compress_data (&compctx->wu.lzo.ac, buf->len, work.len);
    213183    }
    214184
    215185  /* did compression save us anything ? */
    216186  if (compressed && work.len < buf->len)
    217187    {
    218188      uint8_t *header = buf_prepend (&work, 1);
    219       *header = YES_COMPRESS;
     189      *header = LZO_COMPRESS_BYTE;
    220190      *buf = work;
    221191    }
    222192  else
    223 #endif
    224193    {
    225194      uint8_t *header = buf_prepend (buf, 1);
    226       *header = NO_COMPRESS;
     195      *header = NO_COMPRESS_BYTE;
    227196    }
    228197}
    229198
    230 void
     199static void
    231200lzo_decompress (struct buffer *buf, struct buffer work,
    232                 struct lzo_compress_workspace *lzowork,
     201                struct compress_context *compctx,
    233202                const struct frame* frame)
    234203{
    235 #ifndef ENABLE_LZO_STUB
    236204  lzo_uint zlen = EXPANDED_SIZE (frame);
    237205  int err;
    238 #endif
    239206  uint8_t c;            /* flag indicating whether or not our peer compressed */
    240207
    241   ASSERT (lzowork->defined);
    242 
    243208  if (buf->len <= 0)
    244209    return;
    245210
    lzo_decompress (struct buffer *buf, struct buffer work, 
    248213  c = *BPTR (buf);
    249214  ASSERT (buf_advance (buf, 1));
    250215
    251   if (c == YES_COMPRESS)        /* packet was compressed */
     216  if (c == LZO_COMPRESS_BYTE)   /* packet was compressed */
    252217    {
    253 #ifndef ENABLE_LZO_STUB
    254218      ASSERT (buf_safe (&work, zlen));
    255219      err = LZO_DECOMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen,
    256                             lzowork->wmem);
     220                            compctx->wu.lzo.wmem);
    257221      if (err != LZO_E_OK)
    258222        {
    259223          dmsg (D_COMP_ERRORS, "LZO decompression error: %d", err);
    lzo_decompress (struct buffer *buf, struct buffer work, 
    264228      ASSERT (buf_safe (&work, zlen));
    265229      work.len = zlen;
    266230
    267       dmsg (D_COMP, "decompress %d -> %d", buf->len, work.len);
    268       lzowork->pre_decompress += buf->len;
    269       lzowork->post_decompress += work.len;
     231      dmsg (D_COMP, "LZO decompress %d -> %d", buf->len, work.len);
     232      compctx->pre_decompress += buf->len;
     233      compctx->post_decompress += work.len;
    270234
    271235      *buf = work;
    272 #else
    273       dmsg (D_COMP_ERRORS, "LZO decompression error: LZO capability not compiled");
    274       buf->len = 0;
    275       return;
    276 #endif
    277236    }
    278   else if (c == NO_COMPRESS)    /* packet was not compressed */
     237  else if (c == NO_COMPRESS_BYTE)       /* packet was not compressed */
    279238    {
    280239      ;
    281240    }
    lzo_decompress (struct buffer *buf, struct buffer work, 
    286245    }
    287246}
    288247
    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 }
     248const struct compress_alg lzo_alg = {
     249  "lzo",
     250  lzo_compress_init,
     251  lzo_compress_uninit,
     252  lzo_compress,
     253  lzo_decompress
     254};
    307255
    308256#else
    309257static void dummy(void) {}
  • src/openvpn/lzo.h

    diff --git a/src/openvpn/lzo.h b/src/openvpn/lzo.h
    index 472204d..f33e587 100644
    a b  
    3232 */
    3333
    3434
    35 #ifdef ENABLE_LZO
     35#if defined(ENABLE_LZO)
    3636
    3737/**
    3838 * @addtogroup compression
    3939 * @{
    4040 */
    4141
    42 #ifndef ENABLE_LZO_STUB
    4342#if defined(HAVE_LZO_LZOUTIL_H)
    4443#include "lzo/lzoutil.h"
    4544#elif defined(HAVE_LZOUTIL_H)
     
    5049#elif defined(HAVE_LZO1X_H)
    5150#include "lzo1x.h"
    5251#endif
    53 #endif
    5452
    5553#include "buffer.h"
    5654#include "mtu.h"
    5755#include "common.h"
    5856#include "status.h"
    5957
    60 /**************************************************************************/
    61 /** @name Bit-flags which control data channel packet compression *//******/
    62 /** @{ */
    63 #define LZO_SELECTED   (1<<0)   /**< Bit-flag indicating that compression
    64                                  *   of data channel packets is enabled. */
    65 #define LZO_ON         (1<<1)   /**< Bit-flag indicating that compression
    66                                  *   of data channel packets is active. */
    67 #define LZO_ADAPTIVE   (1<<2)   /**< Bit-flag indicating that adaptive
    68                                  *   compression of data channel packets
    69                                  *   has been selected. */
    70 /** @} name Bit-flags which control data channel packet compression *//****/
     58extern const struct compress_alg lzo_alg;
    7159
    7260/**************************************************************************/
    7361/** @name LZO library interface defines *//** @{ *//***********************/
    74 #ifndef ENABLE_LZO_STUB
    7562#define LZO_COMPRESS    lzo1x_1_15_compress
    7663                                /**< LZO library compression function.
    7764                                 *
     
    9380                                 *   verify the integrity of incoming
    9481                                 *   packets, you might want to consider
    9582                                 *   using the non-safe version. */
    96 #endif /* ENABLE_LZO_STUB */
    9783/** @} name LZO library interface *//**************************************/
    9884
    9985
    10086/**************************************************************************/
    101 /** @name Miscellaneous compression defines *//** @{ *//*******************/
    102 #define LZO_EXTRA_BUFFER(len) ((len)/8 + 128 + 3)
    103                                 /**< LZO 2.0 worst-case size expansion. */
    104 #ifndef ENABLE_LZO_STUB
    105 #define COMPRESS_THRESHOLD 100  /**< Minimum packet size to attempt
    106                                  *   compression. */
    107 #endif /* ENABLE_LZO_STUB */
    108 /** @} name Miscellaneous compression defines *//**************************/
    109 
    110 
    111 /**************************************************************************/
    112 /** @name Compression header defines *//** @{ *//**************************/
    113 #define LZO_PREFIX_LEN 1        /**< Length in bytes of prepended
    114                                  *   compression header. */
    115 #define YES_COMPRESS 0x66       /**< Single-byte compression header
    116                                  *   indicating this packet has been
    117                                  *   compressed. */
    118 #define NO_COMPRESS  0xFA       /**< Single-byte compression header
    119                                  *   indicating this packet has not been
    120                                  *   compressed. */
    121 /** @} name Compression header defines *//*********************************/
    122 
    123 /**************************************************************************/
    12487/** @name Adaptive compression defines *//** @{ *//************************/
    125 #ifndef ENABLE_LZO_STUB
    12688#define AC_SAMP_SEC    2        /**< Number of seconds in a sample period. */
    12789#define AC_MIN_BYTES   1000     /**< Minimum number of bytes a sample
    12890                                 *   period must contain for it to be
     
    13294                                 *   turned off. */
    13395#define AC_OFF_SEC     60       /**< Seconds to wait after compression has
    13496                                 *   been turned off before retesting. */
    135 #endif /* ENABLE_LZO_STUB */
    13697/** @} name Adaptive compression defines *//*******************************/
    13798
    138 #ifndef ENABLE_LZO_STUB
    139 
    14099/**
    141100 * Adaptive compression state.
    142101 */
    struct lzo_adaptive_compress { 
    147106  int n_comp;
    148107};
    149108
    150 #endif /* ENABLE_LZO_STUB */
    151 
    152109
    153110/**
    154111 * State for the compression and decompression routines.
    struct lzo_adaptive_compress { 
    162119 */
    163120struct lzo_compress_workspace
    164121{
    165   bool defined;
    166   unsigned int flags;
    167 #ifndef ENABLE_LZO_STUB
    168122  lzo_voidp wmem;
    169123  int wmem_size;
    170124  struct lzo_adaptive_compress ac;
    171 
    172   /* statistics */
    173   counter_type pre_decompress;
    174   counter_type post_decompress;
    175   counter_type pre_compress;
    176   counter_type post_compress;
    177 #endif
    178125};
    179126
    180 
    181 /**************************************************************************/
    182 /** @name Functions for initialization and cleanup *//** @{ *//************/
    183 
    184 /**
    185  * Adjust %frame parameters for data channel payload compression.
    186  *
    187  * Data channel packet compression requires a single-byte header to
    188  * indicate whether a packet has been compressed or not. The packet
    189  * handling buffers must also allow for worst-case payload compression
    190  * where the compressed content size is actually larger than the original
    191  * content size. This function adjusts the parameters of a given frame
    192  * structure to include the header and allow for worst-case compression
    193  * expansion.
    194  *
    195  * @param frame        - The frame structure to adjust.
    196  */
    197 void lzo_adjust_frame_parameters(struct frame *frame);
    198 
    199 /**
    200  * Initialize a compression workspace structure.
    201  *
    202  * This function initializes the given workspace structure \a lzowork.
    203  * This includes allocating a work buffer for internal use and setting its
    204  * flags to the given value of \a flags.
    205  *
    206  * This function also initializes the lzo library.
    207  *
    208  * @param lzowork      - A pointer to the workspace structure to
    209  *                       initialize.
    210  * @param flags        - The initial flags to set in the workspace
    211  *                       structure.
    212  */
    213 void lzo_compress_init (struct lzo_compress_workspace *lzowork, unsigned int flags);
    214 
    215 /**
    216  * Cleanup a compression workspace structure.
    217  *
    218  * This function cleans up the given workspace structure \a lzowork.  This
    219  * includes freeing the structure's internal work buffer.
    220  *
    221  * @param lzowork      - A pointer to the workspace structure to clean up.
    222  */
    223 void lzo_compress_uninit (struct lzo_compress_workspace *lzowork);
    224 
    225 /**
    226  * Set a workspace structure's flags.
    227  *
    228  * @param lzowork      - The workspace structure of which to modify the
    229  *                       flags.
    230  * @param flags        - The new value to assign to the workspace
    231  *                       structure's flags.
    232  */
    233 void lzo_modify_flags (struct lzo_compress_workspace *lzowork, unsigned int flags);
    234 
    235 /** @} name Functions for initialization and cleanup *//*******************/
    236 
    237 
    238 /**************************************************************************/
    239 /** @name Function for packets to be sent to a remote OpenVPN peer *//*****/
    240 /** @{ */
    241 
    242 /**
    243  * Process an outgoing packet according to a VPN tunnel's settings.
    244  * @ingroup compression
    245  *
    246  * This function processes the packet contained in \a buf.  Its behavior
    247  * depends on the settings contained within \a lzowork.  If compression is
    248  * enabled and active, this function compresses the packet.  After
    249  * compression, the size of the uncompressed and compressed packets are
    250  * compared, and the smallest is used.
    251  *
    252  * This function prepends a one-byte header indicating whether the packet
    253  * was or was not compressed, so as to let the peer know how to handle the
    254  * packet.
    255  *
    256  * If an error occurs during processing, an error message is logged and
    257  * the length of \a buf is set to zero.
    258  *
    259  * @param buf          - A pointer to the buffer containing the outgoing
    260  *                       packet.  This pointer will be modified to point
    261  *                       to the processed packet on return.
    262  * @param work         - A preallocated working buffer.
    263  * @param lzowork      - The compression workspace structure associated
    264  *                       with this VPN tunnel.
    265  * @param frame        - The frame parameters of this tunnel.
    266  *
    267  * @return Void.\n  On return, \a buf will point to a buffer containing
    268  *     the processed, possibly compressed, packet data with a compression
    269  *     header prepended.
    270  */
    271 void lzo_compress (struct buffer *buf, struct buffer work,
    272                    struct lzo_compress_workspace *lzowork,
    273                    const struct frame* frame);
    274 
    275 /** @} name Function for packets to be sent to a remote OpenVPN peer *//***/
    276 
    277 
    278 /**************************************************************************/
    279 /** @name Function for packets received from a remote OpenVPN peer *//*****/
    280 /** @{ */
    281 
    282 /**
    283  * Inspect an incoming packet and decompress if it is compressed.
    284  *
    285  * This function inspects the incoming packet contained in \a buf.  If its
    286  * one-byte compression header indicates that it was compressed (i.e. \c
    287  * YES_COMPRESS), then it will be decompressed.  If its header indicates
    288  * that it was not compressed (i.e. \c NO_COMPRESS), then the buffer is
    289  * not modified except for removing the compression header.
    290  *
    291  * If an error occurs during processing, for example if the compression
    292  * header has a value other than \c YES_COMPRESS or \c NO_COMPRESS, then
    293  * the error is logged and the length of \a buf is set to zero.
    294  *
    295  * @param buf          - A pointer to the buffer containing the incoming
    296  *                       packet.  This pointer will be modified to point
    297  *                       to the processed packet on return.
    298  * @param work         - A preallocated working buffer.
    299  * @param lzowork      - The compression workspace structure associated
    300  *                       with this VPN tunnel.
    301  * @param frame        - The frame parameters of this tunnel.
    302  *
    303  * @return Void.\n  On return, \a buf will point to a buffer containing
    304  *     the uncompressed packet data and the one-byte compression header
    305  *     will have been removed.
    306  */
    307 void lzo_decompress (struct buffer *buf, struct buffer work,
    308                      struct lzo_compress_workspace *lzowork,
    309                      const struct frame* frame);
    310 
    311 /** @} name Function for packets received from a remote OpenVPN peer *//***/
    312 
    313 
    314 /**************************************************************************/
    315 /** @name Utility functions *//** @{ *//***********************************/
    316 
    317 /**
    318  * Print statistics on compression and decompression performance.
    319  *
    320  * @param lzo_compwork - The workspace structure from which to get the
    321  *                       statistics.
    322  * @param so           - The status output structure to which to write the
    323  *                       statistics.
    324  */
    325 void lzo_print_stats (const struct lzo_compress_workspace *lzo_compwork, struct status_output *so);
    326 
    327 /**
    328  * Check whether compression is enabled for a workspace structure.
    329  *
    330  * @param lzowork      - The workspace structure to check.
    331  *
    332  * @return true if compression is enabled; false otherwise.
    333  */
    334 static inline bool
    335 lzo_defined (const struct lzo_compress_workspace *lzowork)
    336 {
    337   return lzowork->defined;
    338 }
    339 
    340 /** @} name Utility functions *//******************************************/
    341 
    342 
    343127/** @} addtogroup compression */
    344128
    345129
    346 #endif /* ENABLE_LZO */
     130#endif /* ENABLE_LZO && USE_COMP */
    347131#endif
  • src/openvpn/openvpn.h

    diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h
    index bdfa685..606a4f5 100644
    a b  
    3131#include "crypto.h"
    3232#include "ssl.h"
    3333#include "packet_id.h"
    34 #include "lzo.h"
     34#include "comp.h"
    3535#include "tun.h"
    3636#include "interval.h"
    3737#include "status.h"
    struct context_buffers 
    104104  struct buffer decrypt_buf;
    105105#endif
    106106
    107   /* workspace buffers for LZO compression */
    108 #ifdef ENABLE_LZO
    109   struct buffer lzo_compress_buf;
    110   struct buffer lzo_decompress_buf;
     107  /* workspace buffers for compression */
     108#ifdef USE_COMP
     109  struct buffer compress_buf;
     110  struct buffer decompress_buf;
    111111#endif
    112112
    113113  /*
    struct context_2 
    372372
    373373#endif /* ENABLE_CRYPTO */
    374374
    375 #ifdef ENABLE_LZO
    376   struct lzo_compress_workspace lzo_compwork;
    377                                 /**< Compression workspace used by the
     375#ifdef USE_COMP
     376  struct compress_context *comp_context;
     377                                /**< Compression context used by the
    378378                                 *   \link compression Data Channel
    379379                                 *   Compression module\endlink. */
    380380#endif
  • src/openvpn/options.c

    diff --git a/src/openvpn/options.c b/src/openvpn/options.c
    index 88ed88a..cb5778f 100644
    a b const char title_string[] = 
    8484#endif /* defined(ENABLE_CRYPTO_POLARSSL) */
    8585#endif /* ENABLE_SSL */
    8686#endif /* ENABLE_CRYPTO */
     87#ifdef USE_COMP
    8788#ifdef ENABLE_LZO
    88 #ifdef ENABLE_LZO_STUB
    89   " [LZO (STUB)]"
    90 #else
    9189  " [LZO]"
    9290#endif
     91#ifdef ENABLE_SNAPPY
     92  " [SNAPPY]"
     93#endif
     94#ifdef ENABLE_COMP_STUB
     95  " [COMP_STUB]"
    9396#endif
     97#endif /* USE_COMP */
    9498#if EPOLL
    9599  " [EPOLL]"
    96100#endif
    static const char usage_message[] = 
    362366#ifdef ENABLE_DEBUG
    363367  "--gremlin mask  : Special stress testing mode (for debugging only).\n"
    364368#endif
    365 #ifdef ENABLE_LZO
    366   "--comp-lzo      : Use fast LZO compression -- may add up to 1 byte per\n"
     369#if defined(USE_COMP)
     370  "--compress alg  : Use compression algorithm alg\n"
     371#if defined(ENABLE_LZO)
     372  "--comp-lzo      : Use LZO compression -- may add up to 1 byte per\n"
    367373  "                  packet for uncompressible data.\n"
    368374  "--comp-noadapt  : Don't use adaptive compression when --comp-lzo\n"
    369375  "                  is specified.\n"
    370376#endif
     377#endif
    371378#ifdef ENABLE_MANAGEMENT
    372379  "--management ip port [pass] : Enable a TCP server on ip:port to handle\n"
    373380  "                  management functions.  pass is a password file\n"
    show_settings (const struct options *o) 
    15091516
    15101517  SHOW_BOOL (fast_io);
    15111518
    1512 #ifdef ENABLE_LZO
    1513   SHOW_INT (lzo);
     1519#ifdef USE_COMP
     1520  SHOW_INT (comp.alg);
     1521  SHOW_INT (comp.flags);
    15141522#endif
    15151523
    15161524  SHOW_STR (route_script);
    pre_pull_restore (struct options *o) 
    28772885 *                 the other end of the connection]
    28782886 *
    28792887 * --comp-lzo
     2888 * --compress alg
    28802889 * --fragment
    28812890 *
    28822891 * Crypto Options:
    options_string (const struct options *o, 
    29582967      tt = NULL;
    29592968    }
    29602969
    2961 #ifdef ENABLE_LZO
    2962   if (o->lzo & LZO_SELECTED)
    2963     buf_printf (&out, ",comp-lzo");
     2970#ifdef USE_COMP
     2971  if (o->comp.alg != COMP_ALG_UNDEF)
     2972    buf_printf (&out, ",comp-lzo"); /* for compatibility, this simply indicates that compression context is active, not necessarily LZO per-se */
    29642973#endif
    29652974
    29662975#ifdef ENABLE_FRAGMENT
    add_option (struct options *options, 
    61326141      options->passtos = true;
    61336142    }
    61346143#endif
    6135 #ifdef ENABLE_LZO
     6144#if defined(USE_COMP)
    61366145  else if (streq (p[0], "comp-lzo"))
    61376146    {
    61386147      VERIFY_PERMISSION (OPT_P_COMP);
    6139       if (p[1])
     6148
     6149#if defined(ENABLE_LZO)
     6150      if (p[1] && streq (p[1], "no"))
     6151#endif
     6152        {
     6153          options->comp.alg = COMP_ALG_STUB;
     6154          options->comp.flags = 0;
     6155        }
     6156#if defined(ENABLE_LZO)
     6157      else if (p[1])
    61406158        {
    61416159          if (streq (p[1], "yes"))
    6142             options->lzo = LZO_SELECTED|LZO_ON;
    6143           else if (streq (p[1], "no"))
    6144             options->lzo = LZO_SELECTED;
     6160            {
     6161              options->comp.alg = COMP_ALG_LZO;
     6162              options->comp.flags = 0;
     6163            }
    61456164          else if (streq (p[1], "adaptive"))
    6146             options->lzo = LZO_SELECTED|LZO_ON|LZO_ADAPTIVE;
     6165            {
     6166              options->comp.alg = COMP_ALG_LZO;
     6167              options->comp.flags = COMP_F_ADAPTIVE;
     6168            }
    61476169          else
    61486170            {
    61496171              msg (msglevel, "bad comp-lzo option: %s -- must be 'yes', 'no', or 'adaptive'", p[1]);
    add_option (struct options *options, 
    61516173            }
    61526174        }
    61536175      else
    6154         options->lzo = LZO_SELECTED|LZO_ON|LZO_ADAPTIVE;
     6176        {
     6177          options->comp.alg = COMP_ALG_LZO;
     6178          options->comp.flags = COMP_F_ADAPTIVE;
     6179        }
     6180#endif
    61556181    }
    61566182  else if (streq (p[0], "comp-noadapt"))
    61576183    {
    61586184      VERIFY_PERMISSION (OPT_P_COMP);
    6159       options->lzo &= ~LZO_ADAPTIVE;
     6185      options->comp.flags &= ~COMP_F_ADAPTIVE;
     6186    }
     6187  else if (streq (p[0], "compress"))
     6188    {
     6189      VERIFY_PERMISSION (OPT_P_COMP);
     6190      if (p[1])
     6191        {
     6192          if (streq (p[1], "stub"))
     6193            {
     6194              options->comp.alg = COMP_ALG_STUB;
     6195              options->comp.flags = (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
     6196            }
     6197#if defined(ENABLE_LZO)
     6198          else if (streq (p[1], "lzo"))
     6199            {
     6200              options->comp.alg = COMP_ALG_LZO;
     6201              options->comp.flags = 0;
     6202            }
     6203#endif
     6204#if defined(ENABLE_SNAPPY)
     6205          else if (streq (p[1], "snappy"))
     6206            {
     6207              options->comp.alg = COMP_ALG_SNAPPY;
     6208              options->comp.flags = COMP_F_SWAP;
     6209            }
     6210#endif
     6211          else
     6212            {
     6213              msg (msglevel, "bad comp option: %s", p[1]);
     6214              goto err;
     6215            }
     6216        }
     6217      else
     6218        {
     6219          options->comp.alg = COMP_ALG_STUB;
     6220          options->comp.flags = COMP_F_SWAP;
     6221        }
    61606222    }
    6161 #endif /* ENABLE_LZO */
     6223#endif /* USE_COMP */
    61626224#ifdef ENABLE_CRYPTO
    61636225  else if (streq (p[0], "show-ciphers"))
    61646226    {
  • src/openvpn/options.h

    diff --git a/src/openvpn/options.h b/src/openvpn/options.h
    index db1d3f7..9d7aaf2 100644
    a b  
    3939#include "plugin.h"
    4040#include "manage.h"
    4141#include "proxy.h"
    42 #include "lzo.h"
     42#include "comp.h"
    4343#include "pushlist.h"
    4444#include "clinat.h"
    4545
    struct options 
    314314  /* optimize TUN/TAP/UDP writes */
    315315  bool fast_io;
    316316
    317 #ifdef ENABLE_LZO
    318   /* LZO_x flags from lzo.h */
    319   unsigned int lzo;
     317#ifdef USE_COMP
     318  struct compress_options comp;
    320319#endif
    321320
    322321  /* buffer sizes */
  • src/openvpn/sig.c

    diff --git a/src/openvpn/sig.c b/src/openvpn/sig.c
    index 0ebde24..5dee92b 100644
    a b print_status (const struct context *c, struct status_output *so) 
    265265  status_printf (so, "TCP/UDP read bytes," counter_format, c->c2.link_read_bytes);
    266266  status_printf (so, "TCP/UDP write bytes," counter_format, c->c2.link_write_bytes);
    267267  status_printf (so, "Auth read bytes," counter_format, c->c2.link_read_bytes_auth);
    268 #ifdef ENABLE_LZO
    269   if (lzo_defined (&c->c2.lzo_compwork))
    270     lzo_print_stats (&c->c2.lzo_compwork, so);
     268#ifdef USE_COMP
     269  if (c->c2.comp_context)
     270    comp_print_stats (c->c2.comp_context, so);
    271271#endif
    272272#ifdef PACKET_TRUNCATION_CHECK
    273273  status_printf (so, "TUN read truncations," counter_format, c->c2.n_trunc_tun_read);
  • new file src/openvpn/snappy.c

    diff --git a/src/openvpn/snappy.c b/src/openvpn/snappy.c
    new file mode 100644
    index 0000000..24440ba
    - +  
     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-2012 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#ifdef HAVE_CONFIG_H
     26#include "config.h"
     27#elif defined(_MSC_VER)
     28#include "config-msvc.h"
     29#endif
     30
     31#include "syshead.h"
     32
     33#if defined(ENABLE_SNAPPY)
     34
     35#include "snappy-c.h"
     36
     37#include "comp.h"
     38#include "error.h"
     39#include "otime.h"
     40
     41#include "memdbg.h"
     42
     43/* Initial command byte to tell our peer if we compressed */
     44#define SNAPPY_COMPRESS_BYTE 0x68
     45
     46static void
     47snap_compress_init (struct compress_context *compctx)
     48{
     49  msg (D_INIT_MEDIUM, "Snappy compression initializing");
     50  ASSERT(compctx->flags & COMP_F_SWAP);
     51}
     52
     53static void
     54snap_compress_uninit (struct compress_context *compctx)
     55{
     56}
     57
     58static void
     59snap_compress (struct buffer *buf, struct buffer work,
     60               struct compress_context *compctx,
     61               const struct frame* frame)
     62{
     63  snappy_status status;
     64  bool compressed = false;
     65
     66  if (buf->len <= 0)
     67    return;
     68
     69  /*
     70   * In order to attempt compression, length must be at least COMPRESS_THRESHOLD.
     71   */
     72  if (buf->len >= COMPRESS_THRESHOLD)
     73    {
     74      const size_t ps = PAYLOAD_SIZE (frame);
     75      size_t zlen = ps + COMP_EXTRA_BUFFER (ps);
     76
     77      ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
     78      ASSERT (buf_safe (&work, zlen));
     79
     80      if (buf->len > ps)
     81        {
     82          dmsg (D_COMP_ERRORS, "Snappy compression buffer overflow");
     83          buf->len = 0;
     84          return;
     85        }
     86
     87      status = snappy_compress((const char *)BPTR(buf), (size_t)BLEN(buf), (char *)BPTR(&work), &zlen);
     88      if (status != SNAPPY_OK)
     89        {
     90          dmsg (D_COMP_ERRORS, "Snappy compression error: %d", status);
     91          buf->len = 0;
     92          return;
     93        }
     94
     95      ASSERT (buf_safe (&work, zlen));
     96      work.len = zlen;
     97      compressed = true;
     98
     99      dmsg (D_COMP, "Snappy compress %d -> %d", buf->len, work.len);
     100      compctx->pre_compress += buf->len;
     101      compctx->post_compress += work.len;
     102    }
     103
     104  /* did compression save us anything? */
     105  {
     106    uint8_t comp_head_byte = NO_COMPRESS_BYTE_SWAP;
     107    if (compressed && work.len < buf->len)
     108      {
     109        *buf = work;
     110        comp_head_byte = SNAPPY_COMPRESS_BYTE;
     111      }
     112
     113    {
     114      uint8_t *head = BPTR (buf);
     115      uint8_t *tail  = BEND (buf);
     116      ASSERT (buf_safe (buf, 1));
     117      ++buf->len;
     118
     119      /* move head byte of payload to tail */
     120      *tail = *head;
     121      *head = comp_head_byte;
     122    }
     123  }
     124}
     125
     126static void
     127snap_decompress (struct buffer *buf, struct buffer work,
     128                 struct compress_context *compctx,
     129                 const struct frame* frame)
     130{
     131  size_t zlen = EXPANDED_SIZE (frame);
     132  snappy_status status;
     133  uint8_t c;            /* flag indicating whether or not our peer compressed */
     134
     135  if (buf->len <= 0)
     136    return;
     137
     138  ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
     139
     140  /* do unframing/swap (assumes buf->len > 0) */
     141  {
     142    uint8_t *head = BPTR (buf);
     143    c = *head;
     144    --buf->len;
     145    *head = *BEND (buf);
     146  }
     147
     148  if (c == SNAPPY_COMPRESS_BYTE)        /* packet was compressed */
     149    {
     150      ASSERT (buf_safe (&work, zlen));
     151      status = snappy_uncompress((const char *)BPTR(buf), (size_t)BLEN(buf), (char *)BPTR(&work), &zlen);
     152      if (status != SNAPPY_OK)
     153        {
     154          dmsg (D_COMP_ERRORS, "Snappy decompression error: %d", status);
     155          buf->len = 0;
     156          return;
     157        }
     158
     159      ASSERT (buf_safe (&work, zlen));
     160      work.len = zlen;
     161
     162      dmsg (D_COMP, "Snappy decompress %d -> %d", buf->len, work.len);
     163      compctx->pre_decompress += buf->len;
     164      compctx->post_decompress += work.len;
     165
     166      *buf = work;
     167    }
     168  else if (c == NO_COMPRESS_BYTE_SWAP)  /* packet was not compressed */
     169    {
     170      ;
     171    }
     172  else
     173    {
     174      dmsg (D_COMP_ERRORS, "Bad Snappy decompression header byte: %d", c);
     175      buf->len = 0;
     176    }
     177}
     178
     179const struct compress_alg snappy_alg = {
     180  "snappy",
     181  snap_compress_init,
     182  snap_compress_uninit,
     183  snap_compress,
     184  snap_decompress
     185};
     186
     187#else
     188static void dummy(void) {}
     189#endif /* ENABLE_SNAPPY */
  • new file src/openvpn/snappy.h

    diff --git a/src/openvpn/snappy.h b/src/openvpn/snappy.h
    new file mode 100644
    index 0000000..361a631
    - +  
     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-2012 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#ifndef OPENVPN_SNAPPY_H
     26#define OPENVPN_SNAPPY_H
     27
     28#if defined(ENABLE_SNAPPY)
     29
     30#include "buffer.h"
     31
     32extern const struct compress_alg snappy_alg;
     33
     34struct snappy_workspace
     35{
     36};
     37
     38#endif /* ENABLE_SNAPPY */
     39#endif
  • src/openvpn/ssl.c

    diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
    index 43b3980..cf36191 100644
    a b push_peer_info(struct buffer *buf, struct tls_session *session) 
    18091809          buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
    18101810      }
    18111811
    1812       /* push LZO status */
    1813 #ifdef ENABLE_LZO_STUB
    1814       buf_printf (&out, "IV_LZO_STUB=1\n");
     1812      /* push compression status */
     1813#ifdef USE_COMP
     1814      comp_generate_peer_info_string(&session->opt->comp_options, &out);
    18151815#endif
    18161816
    18171817      /* push env vars that begin with UV_ */
  • src/openvpn/ssl_common.h

    diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
    index c62294f..47dbefb 100644
    a b struct tls_options 
    285285  struct env_set *es;
    286286  const struct plugin_list *plugins;
    287287
     288  /* compression parms */
     289#ifdef USE_COMP
     290  struct compress_options comp_options;
     291#endif
     292
    288293  /* configuration file boolean options */
    289294# define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)
    290295# define SSLF_USERNAME_AS_COMMON_NAME  (1<<1)
  • src/openvpn/syshead.h

    diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h
    index 4db29cc..629ee80 100644
    a b socket_defined (const socket_descriptor_t sd) 
    720720#define ENABLE_CLIENT_NAT
    721721
    722722/*
     723 * Compression support
     724 */
     725#if defined(ENABLE_SNAPPY) || defined(ENABLE_LZO) || defined(ENABLE_COMP_STUB)
     726#define USE_COMP
     727#endif
     728
     729/*
    723730 * Enable --memstats option
    724731 */
    725732#ifdef TARGET_LINUX