Ticket #271: 8206.patch

File 8206.patch, 49.5 KB (added by Samuli Seppänen, 11 years ago)

Git-am -style patch extracted from SVN using svnrev2git.py

  • init.c

    From: James Yonan <james@openvpn.net>
    Date: mar, 18 set 2012 00:11:04 +0300
    Subject: [PATCH] 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 no
    
    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.
    
    Version 2.1.21a
    
    ---
    
    a b  
    17101710    }
    17111711#endif
    17121712
    1713 #ifdef USE_LZO
     1713#ifdef USE_COMP
    17141714  if (found & OPT_P_COMP)
    17151715    {
    1716       if (lzo_defined (&c->c2.lzo_compwork))
    1717         {
    1718           msg (D_PUSH, "OPTIONS IMPORT: LZO parms modified");
    1719           lzo_modify_flags (&c->c2.lzo_compwork, c->options.lzo);
    1720         }
     1716      msg (D_PUSH, "OPTIONS IMPORT: compression parms modified");
     1717      comp_uninit (c->c2.comp_context);
     1718      c->c2.comp_context = comp_init (&c->options.comp);
    17211719    }
    17221720#endif
    17231721
     
    21982196  to.sci = &options->sc_info;
    21992197#endif
    22002198
     2199#ifdef USE_COMP
     2200  to.comp_options = options->comp;
     2201#endif 
     2202
    22012203  /* TLS handshake authentication (--tls-auth) */
    22022204  if (options->tls_auth_file)
    22032205    {
     
    22802282static void
    22812283do_init_frame (struct context *c)
    22822284{
    2283 #ifdef USE_LZO
     2285#ifdef USE_COMP
    22842286  /*
    2285    * Initialize LZO compression library.
     2287   * modify frame parameters if compression is enabled
    22862288   */
    2287   if (c->options.lzo & LZO_SELECTED)
     2289  if (comp_enabled(&c->options.comp))
    22882290    {
    2289       lzo_adjust_frame_parameters (&c->c2.frame);
     2291      comp_add_to_extra_frame (&c->c2.frame);
    22902292
     2293#if !defined(USE_SNAPPY)
    22912294      /*
    2292        * LZO usage affects buffer alignment.
     2295       * Compression usage affects buffer alignment when non-swapped algs
     2296       * such as LZO is used.
     2297       * Newer algs like Snappy and comp-stub with COMP_F_SWAP don't need
     2298       * any special alignment because of the control-byte swap approach.
     2299       * LZO alignment (on the other hand) is problematic because
     2300       * the presence of the control byte means that either the output of
     2301       * decryption must be written to an unaligned buffer, or the input
     2302       * to compression (or packet dispatch if packet is uncompressed)
     2303       * must be read from an unaligned buffer.
     2304       * This code tries to align the input to compression (or packet
     2305       * dispatch if packet is uncompressed) at the cost of requiring
     2306       * decryption output to be written to an unaligned buffer, so
     2307       * it's more of a tradeoff than an optimal solution and we don't
     2308       * include it when we are doing a modern build with Snappy.
     2309       * Strictly speaking, on the server it would be better to execute
     2310       * this code for every connection after we decide the compression
     2311       * method, but currently the frame code doesn't appear to be
     2312       * flexible enough for this, since the frame is already established
     2313       * before it is known which compression options will be pushed.
    22932314       */
    2294       if (CIPHER_ENABLED (c))
     2315      if (comp_unswapped_prefix (&c->options.comp) && CIPHER_ENABLED (c))
    22952316        {
    2296           frame_add_to_align_adjust (&c->c2.frame, LZO_PREFIX_LEN);
     2317          frame_add_to_align_adjust (&c->c2.frame, COMP_PREFIX_LEN);
    22972318          frame_or_align_flags (&c->c2.frame,
    22982319                                FRAME_HEADROOM_MARKER_FRAGMENT
    22992320                                |FRAME_HEADROOM_MARKER_DECRYPT);
    23002321        }
     2322#endif
    23012323
    23022324#ifdef ENABLE_FRAGMENT
    2303       lzo_adjust_frame_parameters (&c->c2.frame_fragment_omit); /* omit LZO frame delta from final frame_fragment */
     2325      comp_add_to_extra_frame (&c->c2.frame_fragment_omit); /* omit compression frame delta from final frame_fragment */
    23042326#endif
    23052327    }
    2306 #endif /* USE_LZO */
     2328#endif /* USE_COMP */
    23072329
    23082330#ifdef ENABLE_SOCKS
    23092331  /*
     
    23322354   */
    23332355  frame_finalize_options (c, NULL);
    23342356
     2357#ifdef USE_COMP
     2358  /*
     2359   * Modify frame parameters if compression is enabled.
     2360   * Should be called after frame_finalize_options.
     2361   */
     2362  if (comp_enabled(&c->options.comp))
     2363    {
     2364      comp_add_to_extra_buffer (&c->c2.frame);
    23352365#ifdef ENABLE_FRAGMENT
     2366      comp_add_to_extra_buffer (&c->c2.frame_fragment_omit); /* omit compression frame delta from final frame_fragment */
     2367#endif
     2368    }
     2369#endif /* USE_COMP */
     2370
     2371#ifdef ENABLE_FRAGMENT
    23362372  /*
    23372373   * Set frame parameter for fragment code.  This is necessary because
    23382374   * the fragmentation code deals with payloads which have already been
     
    24742510  b->decrypt_buf = alloc_buf (BUF_SIZE (frame));
    24752511#endif
    24762512
    2477 #ifdef USE_LZO
    2478   b->lzo_compress_buf = alloc_buf (BUF_SIZE (frame));
    2479   b->lzo_decompress_buf = alloc_buf (BUF_SIZE (frame));
     2513#ifdef USE_COMP
     2514  b->compress_buf = alloc_buf (BUF_SIZE (frame));
     2515  b->decompress_buf = alloc_buf (BUF_SIZE (frame));
    24802516#endif
    24812517
    24822518  return b;
     
    24912527      free_buf (&b->read_tun_buf);
    24922528      free_buf (&b->aux_buf);
    24932529
    2494 #ifdef USE_LZO
    2495       free_buf (&b->lzo_compress_buf);
    2496       free_buf (&b->lzo_decompress_buf);
     2530#ifdef USE_COMP
     2531      free_buf (&b->compress_buf);
     2532      free_buf (&b->decompress_buf);
    24972533#endif
    24982534
    24992535#ifdef USE_CRYPTO
     
    33273363      goto sig;
    33283364  }
    33293365
    3330 #ifdef USE_LZO
    3331   /* initialize LZO compression library. */
    3332   if ((options->lzo & LZO_SELECTED) && (c->mode == CM_P2P || child))
    3333     lzo_compress_init (&c->c2.lzo_compwork, options->lzo);
     3366#ifdef USE_COMP
     3367  /* initialize compression library. */
     3368  if (comp_enabled(&options->comp) && (c->mode == CM_P2P || child))
     3369    c->c2.comp_context = comp_init (&options->comp);
    33343370#endif
    33353371
    33363372  /* initialize MTU variables */
     
    34443480        /* if xinetd/inetd mode, don't allow restart */
    34453481        do_close_check_if_restart_permitted (c);
    34463482
    3447 #ifdef USE_LZO
    3448         if (lzo_defined (&c->c2.lzo_compwork))
    3449           lzo_compress_uninit (&c->c2.lzo_compwork);
     3483#ifdef USE_COMP
     3484        if (c->c2.comp_context)
     3485          {
     3486            comp_uninit (c->c2.comp_context);
     3487            c->c2.comp_context = NULL;
     3488          }
    34503489#endif
    34513490
    34523491        /* free buffers */
     
    35793618      dest->c2.link_socket_info->lsa = &dest->c1.link_socket_addr;
    35803619      dest->c2.link_socket_info->connection_established = false;
    35813620    }
     3621
     3622#ifdef USE_COMP
     3623  dest->c2.comp_context = NULL;
     3624#endif
    35823625}
    35833626
    35843627void
     
    36273670  dest->c2.event_set = NULL;
    36283671  if (src->options.ce.proto == PROTO_UDPv4)
    36293672    do_event_set_init (dest, false);
     3673
     3674#ifdef USE_COMP
     3675  dest->c2.comp_context = NULL;
     3676#endif
    36303677}
    36313678
    36323679void
  • configure.ac

    a b  
    6969   [LZO="yes"]
    7070)
    7171
    72 AC_ARG_ENABLE(lzo-stub,
    73    [  --enable-lzo-stub       Don't compile LZO compression support but still allow limited interoperability with LZO-enabled peers],
    74    [LZO_STUB="$enableval"],
    75    [LZO_STUB="no"]
     72AC_ARG_ENABLE(snappy,
     73   [  --disable-snappy        Disable Snappy compression support],
     74   [SNAPPY="$enableval"],
     75   [SNAPPY="yes"]
    7676)
    7777
     78AC_ARG_ENABLE(comp-stub,
     79   [  --enable-comp-stub      Don't compile compression support but still allow limited interoperability with compression-enabled peers],
     80   [COMP_STUB="$enableval"],
     81   [COMP_STUB="no"]
     82)
     83
    7884AC_ARG_ENABLE(crypto,
    7985   [  --disable-crypto        Disable OpenSSL crypto support],
    8086   [CRYPTO="$enableval"],
     
    240246   [LDFLAGS="$LDFLAGS -L$withval"]
    241247)
    242248
     249AC_ARG_WITH(snappy-headers,
     250   [  --with-snappy-headers=DIR  Snappy Include files location],
     251   [SNAPPY_HDR_DIR="$withval"]
     252   [CPPFLAGS="$CPPFLAGS -I$withval"]
     253)
     254
     255AC_ARG_WITH(snappy-lib,
     256   [  --with-snappy-lib=DIR      Snappy Library location],
     257   [LDFLAGS="$LDFLAGS -L$withval"]
     258)
     259
    243260AC_ARG_WITH(pkcs11-helper-headers,
    244261   [  --with-pkcs11-helper-headers=DIR pkcs11-helper Include files location],
    245262   [PKCS11_HELPER_HDR_DIR="$withval"]
     
    329346
    330347dnl Checks for programs.
    331348AC_PROG_CC
     349AC_PROG_CXX
    332350AC_PROG_INSTALL
    333351AC_PROG_GCC_TRADITIONAL
    334352AC_GNU_SOURCE
     
    663681dnl check for LZO library
    664682dnl
    665683
    666 if test "$LZO" = "yes" && test "$LZO_STUB" = "no"; then
     684if test "$LZO" = "yes" && test "$COMP_STUB" = "no"; then
    667685   LZO_H=""
    668686   AC_CHECKING([for LZO Library and Header files])
    669687   AC_CHECK_HEADER(lzo/lzo1x.h,
     
    693711   else
    694712     AC_MSG_RESULT([LZO headers were not found])
    695713     AC_MSG_RESULT([LZO library available from http://www.oberhumer.com/opensource/lzo/])
    696      AC_MSG_ERROR([Or try ./configure --disable-lzo OR ./configure --enable-lzo-stub])
     714     AC_MSG_ERROR([Or try ./configure --disable-lzo OR ./configure --enable-comp-stub])
    697715   fi
    698716fi
    699717
     718dnl
     719dnl check for Snappy library
     720dnl
     721
     722if test "$SNAPPY" = "yes" && test "$COMP_STUB" = "no"; then
     723   havesnappylib=0
     724   AC_LANG_PUSH([C++])
     725   AC_CHECKING([for Snappy Library and Header files])
     726   AC_CHECK_HEADER(snappy-c.h,
     727        [AC_CHECK_LIB(snappy, snappy_compress,
     728            [
     729                   OPENVPN_ADD_LIBS(-lstdc++)
     730                   OPENVPN_ADD_LIBS(-lsnappy)
     731                   AC_DEFINE(USE_SNAPPY, 1, [Use Snappy compression library])
     732                   havesnappylib=1
     733            ],
     734            [AC_MSG_RESULT([Snappy library not found.])]
     735        )],
     736        [AC_MSG_RESULT([Snappy headers not found.])]
     737   )
     738   AC_LANG_POP([C++])
     739   if test $havesnappylib = 0 ; then
     740     AC_MSG_RESULT([Snappy library available from http://code.google.com/p/snappy/])
     741     AC_MSG_ERROR([Or try ./configure --disable-snappy OR ./configure --enable-comp-stub])
     742   fi
     743fi
     744
    700745dnl enable multi-client mode
    701 if test "$LZO_STUB" = "yes"; then
    702    AC_DEFINE(LZO_STUB, 1, [Enable LZO stub capability])
     746if test "$COMP_STUB" = "yes"; then
     747   AC_DEFINE(COMP_STUB, 1, [Enable compression stub capability])
    703748fi
    704749
    705750dnl
  • version.m4

    a b  
    11dnl define the OpenVPN version
    2 define(PRODUCT_VERSION,[2.1.20])
     2define(PRODUCT_VERSION,[2.1.21a])
    33dnl define the TAP version
    44define(PRODUCT_TAP_ID,[tap0901])
    55define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
  • lzo.c

    a b  
    2424
    2525#include "syshead.h"
    2626
    27 #ifdef USE_LZO
     27#if defined(USE_LZO) && defined(USE_COMP)
    2828
    29 #include "lzo.h"
     29#include "comp.h"
    3030#include "error.h"
    3131#include "otime.h"
    3232
    3333#include "memdbg.h"
    3434
    35 #ifndef LZO_STUB
     35/* Initial command byte to tell our peer if we compressed */
     36#define LZO_COMPRESS_BYTE 0x66
    3637
    3738static bool
    3839lzo_adaptive_compress_test (struct lzo_adaptive_compress *ac)
     
    8182  ac->n_comp += n_comp;
    8283}
    8384
    84 #endif /* LZO_STUB */
    85 
    86 void lzo_adjust_frame_parameters (struct frame *frame)
     85static void
     86lzo_compress_init (struct compress_context *compctx)
    8787{
    88   /* Leave room for our one-byte compressed/didn't-compress prefix byte. */
    89   frame_add_to_extra_frame (frame, LZO_PREFIX_LEN);
    90 
    91   /* Leave room for compression buffer to expand in worst case scenario
    92      where data is totally uncompressible */
    93   frame_add_to_extra_buffer (frame, LZO_EXTRA_BUFFER (EXPANDED_SIZE(frame)));
    94 }
    95 
    96 void
    97 lzo_compress_init (struct lzo_compress_workspace *lzowork, unsigned int flags)
    98 {
    99   CLEAR (*lzowork);
    100 
    101   lzowork->flags = flags;
    102 #ifndef LZO_STUB
    103   lzowork->wmem_size = LZO_WORKSPACE;
    104 
     88  msg (D_INIT_MEDIUM, "LZO compression initializing");
     89  ASSERT(!(compctx->flags & COMP_F_SWAP));
     90  compctx->wu.lzo.wmem_size = LZO_WORKSPACE;
    10591  if (lzo_init () != LZO_E_OK)
    10692    msg (M_FATAL, "Cannot initialize LZO compression library");
    107   lzowork->wmem = (lzo_voidp) lzo_malloc (lzowork->wmem_size);
    108   check_malloc_return (lzowork->wmem);
    109   msg (D_INIT_MEDIUM, "LZO compression initialized");
    110 #else
    111   msg (D_INIT_MEDIUM, "LZO stub compression initialized");
    112 #endif
    113   lzowork->defined = true;
     93  compctx->wu.lzo.wmem = (lzo_voidp) lzo_malloc (compctx->wu.lzo.wmem_size);
     94  check_malloc_return (compctx->wu.lzo.wmem);
    11495}
    11596
    116 void
    117 lzo_compress_uninit (struct lzo_compress_workspace *lzowork)
     97static void
     98lzo_compress_uninit (struct compress_context *compctx)
    11899{
    119   if (lzowork)
    120     {
    121       ASSERT (lzowork->defined);
    122 #ifndef LZO_STUB
    123       lzo_free (lzowork->wmem);
    124       lzowork->wmem = NULL;
    125 #endif
    126       lzowork->defined = false;
    127     }
     100  lzo_free (compctx->wu.lzo.wmem);
     101  compctx->wu.lzo.wmem = NULL;
    128102}
    129103
    130104static inline bool
    131 lzo_compression_enabled (struct lzo_compress_workspace *lzowork)
     105lzo_compression_enabled (struct compress_context *compctx)
    132106{
    133 #ifndef LZO_STUB
    134   if ((lzowork->flags & (LZO_SELECTED|LZO_ON)) == (LZO_SELECTED|LZO_ON))
     107  if (compctx->flags & COMP_F_ASYM)
     108    return false;
     109  else
    135110    {
    136       if (lzowork->flags & LZO_ADAPTIVE)
    137         return lzo_adaptive_compress_test (&lzowork->ac);
     111      if (compctx->flags & COMP_F_ADAPTIVE)
     112        return lzo_adaptive_compress_test (&compctx->wu.lzo.ac);
    138113      else
    139114        return true;
    140115    }
    141 #endif
    142   return false;
    143116}
    144117
    145 /* Magic numbers to tell our peer if we compressed or not */
    146 #define YES_COMPRESS 0x66
    147 #define NO_COMPRESS  0xFA
    148 
    149 void
     118static void
    150119lzo_compress (struct buffer *buf, struct buffer work,
    151               struct lzo_compress_workspace *lzowork,
     120              struct compress_context *compctx,
    152121              const struct frame* frame)
    153122{
    154 #ifndef LZO_STUB
    155123  lzo_uint zlen = 0;
    156124  int err;
    157125  bool compressed = false;
    158 #endif
    159126
    160   ASSERT (lzowork->defined);
    161 
    162127  if (buf->len <= 0)
    163128    return;
    164129
    165 #ifndef LZO_STUB
    166130  /*
    167131   * In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
    168132   * and our adaptive level must give the OK.
    169133   */
    170   if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (lzowork))
     134  if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (compctx))
    171135    {
     136      const size_t ps = PAYLOAD_SIZE (frame);
    172137      ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
    173       ASSERT (buf_safe (&work, LZO_EXTRA_BUFFER (PAYLOAD_SIZE (frame))));
     138      ASSERT (buf_safe (&work, ps + COMP_EXTRA_BUFFER (ps)));
    174139
    175       if (!(buf->len <= PAYLOAD_SIZE (frame)))
     140      if (buf->len > ps)
    176141        {
    177142          dmsg (D_COMP_ERRORS, "LZO compression buffer overflow");
    178143          buf->len = 0;
    179144          return;
    180145        }
    181146
    182       err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, lzowork->wmem);
     147      err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, compctx->wu.lzo.wmem);
    183148      if (err != LZO_E_OK)
    184149        {
    185150          dmsg (D_COMP_ERRORS, "LZO compression error: %d", err);
     
    191156      work.len = zlen;
    192157      compressed = true;
    193158
    194       dmsg (D_COMP, "compress %d -> %d", buf->len, work.len);
    195       lzowork->pre_compress += buf->len;
    196       lzowork->post_compress += work.len;
     159      dmsg (D_COMP, "LZO compress %d -> %d", buf->len, work.len);
     160      compctx->pre_compress += buf->len;
     161      compctx->post_compress += work.len;
    197162
    198163      /* tell adaptive level about our success or lack thereof in getting any size reduction */
    199       if (lzowork->flags & LZO_ADAPTIVE)
    200         lzo_adaptive_compress_data (&lzowork->ac, buf->len, work.len);
     164      if (compctx->flags & COMP_F_ADAPTIVE)
     165        lzo_adaptive_compress_data (&compctx->wu.lzo.ac, buf->len, work.len);
    201166    }
    202167
    203168  /* did compression save us anything ? */
    204169  if (compressed && work.len < buf->len)
    205170    {
    206171      uint8_t *header = buf_prepend (&work, 1);
    207       *header = YES_COMPRESS;
     172      *header = LZO_COMPRESS_BYTE;
    208173      *buf = work;
    209174    }
    210175  else
    211 #endif
    212176    {
    213177      uint8_t *header = buf_prepend (buf, 1);
    214       *header = NO_COMPRESS;
     178      *header = NO_COMPRESS_BYTE;
    215179    }
    216180}
    217181
    218 void
     182static void
    219183lzo_decompress (struct buffer *buf, struct buffer work,
    220                 struct lzo_compress_workspace *lzowork,
     184                struct compress_context *compctx,
    221185                const struct frame* frame)
    222186{
    223 #ifndef LZO_STUB
    224187  lzo_uint zlen = EXPANDED_SIZE (frame);
    225188  int err;
    226 #endif
    227189  uint8_t c;            /* flag indicating whether or not our peer compressed */
    228190
    229   ASSERT (lzowork->defined);
    230 
    231191  if (buf->len <= 0)
    232192    return;
    233193
     
    236196  c = *BPTR (buf);
    237197  ASSERT (buf_advance (buf, 1));
    238198
    239   if (c == YES_COMPRESS)        /* packet was compressed */
     199  if (c == LZO_COMPRESS_BYTE)   /* packet was compressed */
    240200    {
    241 #ifndef LZO_STUB
    242201      ASSERT (buf_safe (&work, zlen));
    243202      err = LZO_DECOMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen,
    244                             lzowork->wmem);
     203                            compctx->wu.lzo.wmem);
    245204      if (err != LZO_E_OK)
    246205        {
    247206          dmsg (D_COMP_ERRORS, "LZO decompression error: %d", err);
     
    252211      ASSERT (buf_safe (&work, zlen));
    253212      work.len = zlen;
    254213
    255       dmsg (D_COMP, "decompress %d -> %d", buf->len, work.len);
    256       lzowork->pre_decompress += buf->len;
    257       lzowork->post_decompress += work.len;
     214      dmsg (D_COMP, "LZO decompress %d -> %d", buf->len, work.len);
     215      compctx->pre_decompress += buf->len;
     216      compctx->post_decompress += work.len;
    258217
    259218      *buf = work;
    260 #else
    261       dmsg (D_COMP_ERRORS, "LZO decompression error: LZO capability not compiled");
    262       buf->len = 0;
    263       return;
    264 #endif
    265219    }
    266   else if (c == NO_COMPRESS)    /* packet was not compressed */
     220  else if (c == NO_COMPRESS_BYTE)       /* packet was not compressed */
    267221    {
    268222      ;
    269223    }
     
    274228    }
    275229}
    276230
    277 void
    278 lzo_modify_flags (struct lzo_compress_workspace *lzowork, unsigned int flags)
    279 {
    280   ASSERT (lzowork->defined);
    281   lzowork->flags = flags;
    282 }
     231const struct compress_alg lzo_alg = {
     232  "lzo",
     233  lzo_compress_init,
     234  lzo_compress_uninit,
     235  lzo_compress,
     236  lzo_decompress
     237};
    283238
    284 /*
    285  * Print statistics
    286  */
    287 void lzo_print_stats (const struct lzo_compress_workspace *lzo_compwork, struct status_output *so)
    288 {
    289   ASSERT (lzo_compwork->defined);
    290 
    291 #ifndef LZO_STUB
    292   status_printf (so, "pre-compress bytes," counter_format, lzo_compwork->pre_compress);
    293   status_printf (so, "post-compress bytes," counter_format, lzo_compwork->post_compress);
    294   status_printf (so, "pre-decompress bytes," counter_format, lzo_compwork->pre_decompress);
    295   status_printf (so, "post-decompress bytes," counter_format, lzo_compwork->post_decompress);
    296 #endif
    297 }
    298 
    299239#else
    300240static void dummy(void) {}
    301241#endif /* USE_LZO */
  • lzo.h

    a b  
    2525#ifndef OPENVPN_LZO_H
    2626#define OPENVPN_LZO_H
    2727
    28 #ifdef USE_LZO
     28#if defined(USE_LZO) && defined(USE_COMP)
    2929
    30 #ifndef LZO_STUB
    3130#ifdef LZO_HEADER_DIR
    3231#include "lzo/lzoutil.h"
    3332#include "lzo/lzo1x.h"
     
    3534#include "lzoutil.h"
    3635#include "lzo1x.h"
    3736#endif
    38 #endif
    3937
    4038#include "buffer.h"
    4139#include "mtu.h"
    4240#include "common.h"
    4341#include "status.h"
    4442
    45 /* LZO flags */
    46 #define LZO_SELECTED   (1<<0)
    47 #define LZO_ON         (1<<1)
    48 #define LZO_ADAPTIVE   (1<<2) 
     43extern const struct compress_alg lzo_alg;
    4944
    5045/*
    51  * Length of prepended prefix on LZO packets
    52  */
    53 #define LZO_PREFIX_LEN 1
    54 
    55 /*
    56  * LZO 2.0 worst case size expansion
    57  */
    58 #define LZO_EXTRA_BUFFER(len) ((len)/8 + 128 + 3)
    59 
    60 #ifndef LZO_STUB
    61 
    62 /*
    6346 * Use LZO compress routine lzo1x_1_15_compress which is described
    6447 * as faster but needs a bit more memory than the standard routine.
    6548 * Use safe decompress (i.e. check for buffer overflows).
     
    7356#define LZO_DECOMPRESS  lzo1x_decompress_safe
    7457
    7558/*
    76  * Don't try to compress any packet smaller than this.
    77  */
    78 #define COMPRESS_THRESHOLD 100
    79 
    80 /*
    8159 * Adaptive compress parameters
    8260 */
    8361#define AC_SAMP_SEC    2      /* number of seconds in sample period */
     
    9573  int n_comp;
    9674};
    9775
    98 #endif /* LZO_STUB */
    99 
    10076/*
    10177 * Compress and Uncompress routines.
    10278 */
    10379
    10480struct lzo_compress_workspace
    10581{
    106   bool defined;
    107   unsigned int flags;
    108 #ifndef LZO_STUB
    10982  lzo_voidp wmem;
    11083  int wmem_size;
    11184  struct lzo_adaptive_compress ac;
    112 
    113   /* statistics */
    114   counter_type pre_decompress;
    115   counter_type post_decompress;
    116   counter_type pre_compress;
    117   counter_type post_compress;
    118 #endif
    11985};
    12086
    121 void lzo_adjust_frame_parameters(struct frame *frame);
    122 
    123 void lzo_compress_init (struct lzo_compress_workspace *lzowork, unsigned int flags);
    124 
    125 void lzo_compress_uninit (struct lzo_compress_workspace *lzowork);
    126 
    127 void lzo_modify_flags (struct lzo_compress_workspace *lzowork, unsigned int flags);
    128 
    129 void lzo_compress (struct buffer *buf, struct buffer work,
    130                    struct lzo_compress_workspace *lzowork,
    131                    const struct frame* frame);
    132 
    133 void lzo_decompress (struct buffer *buf, struct buffer work,
    134                      struct lzo_compress_workspace *lzowork,
    135                      const struct frame* frame);
    136 
    137 void lzo_print_stats (const struct lzo_compress_workspace *lzo_compwork, struct status_output *so);
    138 
    139 static inline bool
    140 lzo_defined (const struct lzo_compress_workspace *lzowork)
    141 {
    142   return lzowork->defined;
    143 }
    144 
    145 
    14687#endif /* USE_LZO */
    14788#endif
  • openvpn.8

    a b  
    22562256limit repetitive logging of similar message types.
    22572257.\"*********************************************************
    22582258.TP
     2259.B --compress [algorithm]
     2260Enable a compression algorithm.
     2261
     2262The
     2263.B algorithm
     2264parameter may be "snappy", "lzo", "stub", or "no".  Snappy and LZO
     2265are different compression algorithms, with Snappy generally
     2266offering the best performance.
     2267
     2268"no" indicates that compression should be turned off, but the packet
     2269framing for compression is still enabled, allowing a different
     2270setting to be later pushed.
     2271.\"*********************************************************
     2272.TP
    22592273.B --comp-lzo [mode]
    2260 Use fast LZO compression -- may add up to 1 byte per
     2274Use LZO compression -- may add up to 1 byte per
    22612275packet for incompressible data.
    22622276.B mode
    22632277may be "yes", "no", or "adaptive" (default).
    22642278
     2279This option is deprecated in favor of the newer
     2280.B --compress
     2281option.
     2282
    22652283In a server mode setup, it is possible to selectively turn
    22662284compression on or off for individual clients.
    22672285
  • sig.c

    a b  
    264264  status_printf (so, "TCP/UDP read bytes," counter_format, c->c2.link_read_bytes);
    265265  status_printf (so, "TCP/UDP write bytes," counter_format, c->c2.link_write_bytes);
    266266  status_printf (so, "Auth read bytes," counter_format, c->c2.link_read_bytes_auth);
    267 #ifdef USE_LZO
    268   if (lzo_defined (&c->c2.lzo_compwork))
    269     lzo_print_stats (&c->c2.lzo_compwork, so);
     267#ifdef USE_COMP
     268  if (c->c2.comp_context)
     269    comp_print_stats (c->c2.comp_context, so);
    270270#endif
    271271#ifdef PACKET_TRUNCATION_CHECK
    272272  status_printf (so, "TUN read truncations," counter_format, c->c2.n_trunc_tun_read);
  • comp.c

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

    a b  
    39413941          buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
    39423942      }
    39433943
    3944       /* push LZO status */
    3945 #ifdef LZO_STUB
    3946       buf_printf (&out, "IV_LZO_STUB=1\n");
     3944      /* push compression status */
     3945#ifdef USE_COMP
     3946      comp_generate_peer_info_string(&session->opt->comp_options, &out);
    39473947#endif
    39483948
    39493949      /* push env vars that begin with UV_ */
  • comp.h

    a b  
     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 USE_LZO
     99#include "lzo.h"
     100#endif
     101
     102#ifdef USE_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 USE_LZO
     122  struct lzo_compress_workspace lzo;
     123#endif
     124#ifdef USE_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
  • syshead.h

    a b  
    709709#define ENABLE_CLIENT_NAT
    710710
    711711/*
    712  * Support LZO as a stub in client? (LZO lib not included, but we
    713  * we still support LZO protocol changes that allow us to
    714  * communicate with an LZO-enabled server)
     712 * Compression support
    715713 */
    716 #ifdef LZO_STUB
    717 #undef USE_LZO
    718 #undef LZO_VERSION_NUM
    719 #define USE_LZO 1
    720 #define LZO_VERSION_NUM "STUB"
     714#if defined(USE_SNAPPY) || defined(USE_LZO) || defined(COMP_STUB)
     715#define USE_COMP
    721716#endif
    722717
    723718/*
  • ssl.h

    a b  
    499499  struct env_set *es;
    500500  const struct plugin_list *plugins;
    501501
     502  /* compression parms */
     503#ifdef USE_COMP
     504  struct compress_options comp_options;
     505#endif 
     506
    502507  /* configuration file boolean options */
    503508# define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)
    504509# define SSLF_USERNAME_AS_COMMON_NAME  (1<<1)
  • openvpn.h

    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"
     
    104104  struct buffer decrypt_buf;
    105105#endif
    106106
    107   /* workspace buffers for LZO compression */
    108 #ifdef USE_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  /*
     
    339339#endif /* USE_CRYPTO */
    340340
    341341  /*
    342    * LZO compression library workspace.
     342   * compression context
    343343   */
    344 #ifdef USE_LZO
    345   struct lzo_compress_workspace lzo_compwork;
     344#ifdef USE_COMP
     345  struct compress_context *comp_context;
    346346#endif
    347347
    348348  /*
  • Makefile.am

    a b  
    8080        circ_list.h \
    8181        clinat.c clinat.h \
    8282        common.h \
     83        comp.c comp.h compstub.c \
    8384        config-win32.h \
    8485        crypto.c crypto.h \
    8586        dhcp.c dhcp.h \
     
    134135        session_id.c session_id.h \
    135136        shaper.c shaper.h \
    136137        sig.c sig.h \
     138        snappy.c snappy.h \
    137139        socket.c socket.h \
    138140        socks.c socks.h \
    139141        ssl.c ssl.h \
  • options.c

    a b  
    5959  " [CRYPTO]"
    6060#endif
    6161#endif
     62#ifdef USE_COMP
    6263#ifdef USE_LZO
    6364  " [LZO" LZO_VERSION_NUM "]"
    6465#endif
     66#ifdef USE_SNAPPY
     67  " [SNAPPY]"
     68#endif
     69#endif
    6570#if EPOLL
    6671  " [EPOLL]"
    6772#endif
     
    324329#ifdef ENABLE_DEBUG
    325330  "--gremlin mask  : Special stress testing mode (for debugging only).\n"
    326331#endif
    327 #ifdef USE_LZO
    328   "--comp-lzo      : Use fast LZO compression -- may add up to 1 byte per\n"
     332#if defined(USE_COMP)
     333  "--compress alg  : Use compression algorithm alg\n"
     334#if defined(USE_LZO)
     335  "--comp-lzo      : Use LZO compression -- may add up to 1 byte per\n"
    329336  "                  packet for uncompressible data.\n"
    330337  "--comp-noadapt  : Don't use adaptive compression when --comp-lzo\n"
    331338  "                  is specified.\n"
    332339#endif
     340#endif
    333341#ifdef ENABLE_MANAGEMENT
    334342  "--management ip port [pass] : Enable a TCP server on ip:port to handle\n"
    335343  "                  management functions.  pass is a password file\n"
     
    13331341
    13341342  SHOW_BOOL (fast_io);
    13351343
    1336 #ifdef USE_LZO
    1337   SHOW_INT (lzo);
     1344#ifdef USE_COMP
     1345  SHOW_INT (comp.alg);
     1346  SHOW_INT (comp.flags);
    13381347#endif
    13391348
    13401349  SHOW_STR (route_script);
     
    24772486 *                 the other end of the connection]
    24782487 *
    24792488 * --comp-lzo
     2489 * --compress alg
    24802490 * --fragment
    24812491 *
    24822492 * Crypto Options:
     
    25512561      tt = NULL;
    25522562    }
    25532563
    2554 #ifdef USE_LZO
    2555   if (o->lzo & LZO_SELECTED)
    2556     buf_printf (&out, ",comp-lzo");
     2564#ifdef USE_COMP
     2565  if (o->comp.alg != COMP_ALG_UNDEF)
     2566    buf_printf (&out, ",comp-lzo"); /* for compatibility, this simply indicates that compression context is active, not necessarily LZO per-se */
    25572567#endif
    25582568
    25592569#ifdef ENABLE_FRAGMENT
     
    55695579      options->passtos = true;
    55705580    }
    55715581#endif
    5572 #ifdef USE_LZO
     5582#if defined(USE_COMP)
    55735583  else if (streq (p[0], "comp-lzo"))
    55745584    {
    55755585      VERIFY_PERMISSION (OPT_P_COMP);
    5576       if (p[1])
     5586
     5587#if defined(USE_LZO)
     5588      if (p[1] && streq (p[1], "no"))
     5589#endif
    55775590        {
     5591          options->comp.alg = COMP_ALG_STUB;
     5592          options->comp.flags = 0;
     5593        }
     5594#if defined(USE_LZO)
     5595      else if (p[1])
     5596        {
    55785597          if (streq (p[1], "yes"))
    5579             options->lzo = LZO_SELECTED|LZO_ON;
    5580           else if (streq (p[1], "no"))
    5581             options->lzo = LZO_SELECTED;
     5598            {
     5599              options->comp.alg = COMP_ALG_LZO;
     5600              options->comp.flags = 0;
     5601            }
    55825602          else if (streq (p[1], "adaptive"))
    5583             options->lzo = LZO_SELECTED|LZO_ON|LZO_ADAPTIVE;
     5603            {
     5604              options->comp.alg = COMP_ALG_LZO;
     5605              options->comp.flags = COMP_F_ADAPTIVE;
     5606            }
    55845607          else
    55855608            {
    55865609              msg (msglevel, "bad comp-lzo option: %s -- must be 'yes', 'no', or 'adaptive'", p[1]);
     
    55885611            }
    55895612        }
    55905613      else
    5591         options->lzo = LZO_SELECTED|LZO_ON|LZO_ADAPTIVE;
     5614        {
     5615          options->comp.alg = COMP_ALG_LZO;
     5616          options->comp.flags = COMP_F_ADAPTIVE;
     5617        }
     5618#endif
    55925619    }
    55935620  else if (streq (p[0], "comp-noadapt"))
    55945621    {
    55955622      VERIFY_PERMISSION (OPT_P_COMP);
    5596       options->lzo &= ~LZO_ADAPTIVE;
     5623      options->comp.flags &= ~COMP_F_ADAPTIVE;
    55975624    }
    5598 #endif /* USE_LZO */
     5625  else if (streq (p[0], "compress"))
     5626    {
     5627      VERIFY_PERMISSION (OPT_P_COMP);
     5628      if (p[1])
     5629        {
     5630          if (streq (p[1], "no"))
     5631            {
     5632              options->comp.alg = COMP_ALG_STUB;
     5633              options->comp.flags = COMP_F_SWAP;
     5634            }
     5635          if (streq (p[1], "stub"))
     5636            {
     5637              options->comp.alg = COMP_ALG_STUB;
     5638              options->comp.flags = (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
     5639            }
     5640#if defined(USE_LZO)
     5641          else if (streq (p[1], "lzo"))
     5642            {
     5643              options->comp.alg = COMP_ALG_LZO;
     5644              options->comp.flags = 0;
     5645            }
     5646#endif
     5647#if defined(USE_SNAPPY)
     5648          else if (streq (p[1], "snappy"))
     5649            {
     5650              options->comp.alg = COMP_ALG_SNAPPY;
     5651              options->comp.flags = COMP_F_SWAP;
     5652            }
     5653#endif
     5654          else
     5655            {
     5656              msg (msglevel, "bad comp option: %s", p[1]);
     5657              goto err;
     5658            }
     5659        }
     5660      else
     5661        {
     5662          options->comp.alg = COMP_ALG_STUB;
     5663          options->comp.flags = COMP_F_SWAP;
     5664        }
     5665    }
     5666#endif /* USE_COMP */
    55995667#ifdef USE_CRYPTO
    56005668  else if (streq (p[0], "show-ciphers"))
    56015669    {
  • options.h

    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
     
    335335  /* optimize TUN/TAP/UDP writes */
    336336  bool fast_io;
    337337
    338 #ifdef USE_LZO
    339   /* LZO_x flags from lzo.h */
    340   unsigned int lzo;
     338#ifdef USE_COMP
     339  struct compress_options comp;
    341340#endif
    342341
    343342  /* buffer sizes */
  • forward.c

    a b  
    437437
    438438  if (comp_frag)
    439439    {
    440 #ifdef USE_LZO
     440#ifdef USE_COMP
    441441      /* Compress the packet. */
    442       if (lzo_defined (&c->c2.lzo_compwork))
    443         lzo_compress (&c->c2.buf, b->lzo_compress_buf, &c->c2.lzo_compwork, &c->c2.frame);
     442      if (c->c2.comp_context)
     443        (*c->c2.comp_context->alg.compress)(&c->c2.buf, b->compress_buf, c->c2.comp_context, &c->c2.frame);
    444444#endif
    445445#ifdef ENABLE_FRAGMENT
    446446      if (c->c2.fragment)
     
    849849        fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);
    850850#endif
    851851
    852 #ifdef USE_LZO
     852#ifdef USE_COMP
    853853      /* decompress the incoming packet */
    854       if (lzo_defined (&c->c2.lzo_compwork))
    855         lzo_decompress (&c->c2.buf, c->c2.buffers->lzo_decompress_buf, &c->c2.lzo_compwork, &c->c2.frame);
     854      if (c->c2.comp_context)
     855        (*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf, c->c2.comp_context, &c->c2.frame);
    856856#endif
    857857
    858858#ifdef PACKET_TRUNCATION_CHECK
  • compstub.c

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

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

    a b  
     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(USE_SNAPPY) && defined(USE_COMP)
     29
     30#include "buffer.h"
     31
     32extern const struct compress_alg snappy_alg;
     33
     34struct snappy_workspace
     35{
     36};
     37
     38#endif /* USE_SNAPPY */
     39#endif