forked from osmocom/wireshark
cql: add lz4 and snappy decompression
We do not use the STARTUP negotiation since a stream can be captured in its middle but try to decompress if the flag is present and fallback if it fails. Change-Id: Iecbf49a45220b04be7808869c9884548eb1e7694 Signed-off-by: Benoît Canet <benoit@scylladb.com> Reviewed-on: https://code.wireshark.org/review/17952 Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
This commit is contained in:
parent
5c42d8a24c
commit
47649d1c7f
|
@ -830,6 +830,16 @@ if(ENABLE_ZLIB)
|
|||
set(PACKAGELIST ${PACKAGELIST} ZLIB)
|
||||
endif()
|
||||
|
||||
# LZ4 compression
|
||||
if(ENABLE_LZ4)
|
||||
set(PACKAGELIST ${PACKAGELIST} LZ4)
|
||||
endif()
|
||||
|
||||
# Snappy compression
|
||||
if(ENABLE_SNAPPY)
|
||||
set(PACKAGELIST ${PACKAGELIST} SNAPPY)
|
||||
endif()
|
||||
|
||||
# Embedded Lua interpreter
|
||||
if(ENABLE_LUA)
|
||||
set(PACKAGELIST ${PACKAGELIST} LUA)
|
||||
|
@ -975,6 +985,12 @@ if(HAVE_LIBZLIB)
|
|||
# bug in the Windows setup of GTK[23] which has a faulty zconf.h.
|
||||
include_directories(BEFORE ${ZLIB_INCLUDE_DIRS})
|
||||
endif()
|
||||
if(HAVE_LIBLZ4)
|
||||
set(HAVE_LZ4 1)
|
||||
endif()
|
||||
if(SNAPPY_FOUND)
|
||||
set(HAVE_SNAPPY 1)
|
||||
endif()
|
||||
if (Qt5Widgets_FOUND)
|
||||
#
|
||||
# Qt5CoreConfigExtras.cmake in Qt 5.5.0 sets -fPIC unconditionally:
|
||||
|
@ -1452,6 +1468,8 @@ set(LIBEPAN_LIBS
|
|||
${GNUTLS_LIBRARIES}
|
||||
${SMI_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${LZ4_LIBRARIES}
|
||||
${SNAPPY_LIBRARIES}
|
||||
${M_LIBRARIES}
|
||||
${WINSPARKLE_LIBRARIES}
|
||||
)
|
||||
|
|
|
@ -61,6 +61,8 @@ option(ENABLE_PCAP_NG_DEFAULT "Enable pcap-ng as default file format" ON)
|
|||
|
||||
option(ENABLE_PORTAUDIO "Build with PortAudio support" ON)
|
||||
option(ENABLE_ZLIB "Build with zlib compression support" ON)
|
||||
option(ENABLE_LZ4 "Build with LZ4 compression support" ON)
|
||||
option(ENABLE_SNAPPY "Build with Snappy compression support" ON)
|
||||
option(ENABLE_LUA "Build with Lua dissector support" ON)
|
||||
option(ENABLE_SMI "Build with libsmi snmp support" ON)
|
||||
option(ENABLE_GNUTLS "Build with GNU TLS support" ON)
|
||||
|
|
160
acinclude.m4
160
acinclude.m4
|
@ -1920,3 +1920,163 @@ AC_DEFUN([AC_WIRESHARK_QT_TOOL_CHECK_LRELEASE],
|
|||
])
|
||||
AC_MSG_RESULT([ok, $lrelease_version])
|
||||
])
|
||||
|
||||
#
|
||||
# AC_WIRESHARK_LZ4_CHECK
|
||||
#
|
||||
AC_DEFUN([AC_WIRESHARK_LZ4_CHECK],
|
||||
[
|
||||
AC_WIRESHARK_PUSH_FLAGS
|
||||
|
||||
if test "x$lz4_dir" != "x"
|
||||
then
|
||||
#
|
||||
# The user specified a directory in which lz4 resides,
|
||||
# so add the "include" subdirectory of that directory to
|
||||
# the include file search path and the "lib" subdirectory
|
||||
# of that directory to the library search path.
|
||||
#
|
||||
# XXX - if there's also a lz4 in a directory that's
|
||||
# already in CPPFLAGS or LDFLAGS, this won't make us find
|
||||
# the version in the specified directory, as the compiler
|
||||
# and/or linker will search that other directory before it
|
||||
# searches the specified directory.
|
||||
#
|
||||
LZ4_CFLAGS="-I$lz4_dir/include"
|
||||
fi
|
||||
|
||||
#
|
||||
# Make sure we have "lz4.h". If we don't, it means we probably
|
||||
# don't have lz4, so don't use it.
|
||||
#
|
||||
AC_CHECK_HEADER(lz4.h,,
|
||||
[
|
||||
if test "x$lz4_dir" != "x"
|
||||
then
|
||||
#
|
||||
# The user used "--with-lz4=" to specify a directory
|
||||
# containing lz4, but we didn't find the header file
|
||||
# there; that either means they didn't specify the
|
||||
# right directory or are confused about whether lz4
|
||||
# is, in fact, installed. Report the error and give up.
|
||||
#
|
||||
AC_MSG_ERROR([lz4 header not found in directory specified in --with-lz4])
|
||||
else
|
||||
if test "x$want_lz4" = "xyes"
|
||||
then
|
||||
#
|
||||
# The user tried to force us to use the library, but we
|
||||
# couldn't find the header file; report an error.
|
||||
#
|
||||
AC_MSG_ERROR(Header file lz4.h not found.)
|
||||
else
|
||||
#
|
||||
# We couldn't find the header file; don't use the
|
||||
# library, as it's probably not present.
|
||||
#
|
||||
want_lz4=no
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
if test "x$want_lz4" != "xno"
|
||||
then
|
||||
#
|
||||
# Well, we at least have the lz4 header file.
|
||||
# We link with lz4 to support uncompression of
|
||||
# CQL traffic.
|
||||
#
|
||||
LZ4_LIBS="-llz4"
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="$LZ4_LIBS $LIBS"
|
||||
AC_DEFINE(HAVE_LZ4, 1, [Define to use lz4 library])
|
||||
#
|
||||
# Check for "LZ4_decompress_safe()" in lz4, which we need
|
||||
# in order to read compressed capture files.
|
||||
#
|
||||
AC_CHECK_FUNCS(LZ4_decompress_safe)
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
AC_WIRESHARK_POP_FLAGS
|
||||
])
|
||||
|
||||
#
|
||||
# AC_WIRESHARK_SNAPPY_CHECK
|
||||
#
|
||||
AC_DEFUN([AC_WIRESHARK_SNAPPY_CHECK],
|
||||
[
|
||||
AC_WIRESHARK_PUSH_FLAGS
|
||||
|
||||
if test "x$snappy_dir" != "x"
|
||||
then
|
||||
#
|
||||
# The user specified a directory in which snappy resides,
|
||||
# so add the "include" subdirectory of that directory to
|
||||
# the include file search path and the "lib" subdirectory
|
||||
# of that directory to the library search path.
|
||||
#
|
||||
# XXX - if there's also a snappy in a directory that's
|
||||
# already in CPPFLAGS or LDFLAGS, this won't make us find
|
||||
# the version in the specified directory, as the compiler
|
||||
# and/or linker will search that other directory before it
|
||||
# searches the specified directory.
|
||||
#
|
||||
SNAPPY_CFLAGS="-I$snappy_dir/include"
|
||||
fi
|
||||
|
||||
#
|
||||
# Make sure we have "snappy-c.h". If we don't, it means we probably
|
||||
# don't have snappy, so don't use it.
|
||||
#
|
||||
AC_CHECK_HEADER(snappy-c.h,,
|
||||
[
|
||||
if test "x$snappy_dir" != "x"
|
||||
then
|
||||
#
|
||||
# The user used "--with-snappy=" to specify a directory
|
||||
# containing snappy, but we didn't find the header file
|
||||
# there; that either means they didn't specify the
|
||||
# right directory or are confused about whether snappy
|
||||
# is, in fact, installed. Report the error and give up.
|
||||
#
|
||||
AC_MSG_ERROR([snappy-c.header not found in directory specified in --with-snappy])
|
||||
else
|
||||
if test "x$want_snappy" = "xyes"
|
||||
then
|
||||
#
|
||||
# The user tried to force us to use the library, but we
|
||||
# couldn't find the header file; report an error.
|
||||
#
|
||||
AC_MSG_ERROR(Header file snappy-c.h not found.)
|
||||
else
|
||||
#
|
||||
# We couldn't find the header file; don't use the
|
||||
# library, as it's probably not present.
|
||||
#
|
||||
want_snappy=no
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
if test "x$want_snappy" != "xno"
|
||||
then
|
||||
#
|
||||
# Well, we at least have the snappy-c.header file.
|
||||
# We link with snappy to support uncompression of
|
||||
# compressed CQL traffic.
|
||||
#
|
||||
SNAPPY_LIBS=-lsnappy
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="$SNAPPY_LIBS $LIBS"
|
||||
AC_DEFINE(HAVE_SNAPPY, 1, [Define to use snappy library])
|
||||
#
|
||||
# Check for "snappy_uncompress()" in snappy, which we need
|
||||
# in order to read compressed capture files.
|
||||
#
|
||||
AC_CHECK_FUNCS(snappy_uncompress)
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
AC_WIRESHARK_POP_FLAGS
|
||||
])
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# - Find lz4
|
||||
# Find LZ4 includes and library
|
||||
#
|
||||
# LZ4_INCLUDE_DIRS - where to find lz4.h, etc.
|
||||
# LZ4_LIBRARIES - List of libraries when using lz4.
|
||||
# LZ4_FOUND - True if lz4 found.
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(LZ4 lz4 liblz4)
|
||||
|
||||
find_path(LZ4_INCLUDE_DIR
|
||||
NAMES lz4.h
|
||||
HINTS "${LZ4_INCLUDEDIR}"
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
find_library(LZ4_LIBRARY
|
||||
NAMES lz4 liblz4
|
||||
HINTS "${LZ4_LIBDIR}"
|
||||
PATHS
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args( LZ4 DEFAULT_MSG LZ4_INCLUDE_DIR LZ4_LIBRARY )
|
||||
|
||||
if( LZ4_FOUND )
|
||||
set( LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} )
|
||||
set( LZ4_LIBRARIES ${LZ4_LIBRARY} )
|
||||
else()
|
||||
set( LZ4_INCLUDE_DIRS )
|
||||
set( LZ4_LIBRARIES )
|
||||
endif()
|
||||
|
||||
mark_as_advanced( LZ4_LIBRARIES LZ4_INCLUDE_DIRS )
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# - Find snappy
|
||||
# Find Snappy includes and library
|
||||
#
|
||||
# SNAPPY_INCLUDE_DIRS - where to find snappy.h, etc.
|
||||
# SNAPPY_LIBRARIES - List of libraries when using snappy.
|
||||
# SNAPPY_FOUND - True if snappy found.
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(SNAPPY libsnappy)
|
||||
|
||||
find_path(SNAPPY_INCLUDE_DIR
|
||||
NAMES snappy.h
|
||||
HINTS "${SNAPPY_INCLUDEDIR}"
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
find_library(SNAPPY_LIBRARY
|
||||
NAMES snappy
|
||||
HINTS "${SNAPPY_LIBDIR}"
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args( SNAPPY DEFAULT_MSG SNAPPY_INCLUDE_DIR SNAPPY_LIBRARY )
|
||||
|
||||
if( SNAPPY_FOUND )
|
||||
set( SNAPPY_INCLUDE_DIRS ${SNAPPY_INCLUDE_DIR} )
|
||||
set( SNAPPY_LIBRARIES ${SNAPPY_LIBRARY} )
|
||||
else()
|
||||
set( SNAPPY_INCLUDE_DIRS )
|
||||
set( SNAPPY_LIBRARIES )
|
||||
endif()
|
||||
|
||||
mark_as_advanced( SNAPPY_LIBRARIES SNAPPY_INCLUDE_DIRS )
|
|
@ -160,6 +160,12 @@
|
|||
/* Define to use zlib library */
|
||||
#cmakedefine HAVE_ZLIB 1
|
||||
|
||||
/* Define to use lz4 library */
|
||||
#cmakedefine HAVE_LZ4 1
|
||||
|
||||
/* Define to use snappy library */
|
||||
#cmakedefine HAVE_SNAPPY 1
|
||||
|
||||
/* Define to 1 if you have the <linux/sockios.h> header file. */
|
||||
#cmakedefine HAVE_LINUX_SOCKIOS_H 1
|
||||
|
||||
|
|
88
configure.ac
88
configure.ac
|
@ -1995,6 +1995,92 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
dnl lz4 check
|
||||
LZ4_LIBS=''
|
||||
AC_MSG_CHECKING(whether to use lz4 compression and decompression)
|
||||
|
||||
AC_ARG_WITH(lz4,
|
||||
AC_HELP_STRING([--with-lz4@<:@=DIR@:>@],
|
||||
[use lz4 (located in directory DIR, if supplied) for lz4 compression and decompression @<:@default=yes, if available@:>@]),
|
||||
[
|
||||
if test "x$withval" = "xno"
|
||||
then
|
||||
want_lz4=no
|
||||
elif test "x$withval" = "xyes"
|
||||
then
|
||||
want_lz4=yes
|
||||
else
|
||||
want_lz4=yes
|
||||
lz4_dir="$withval"
|
||||
fi
|
||||
],[
|
||||
#
|
||||
# Use lz4 if it's present, otherwise don't.
|
||||
#
|
||||
want_lz4=ifavailable
|
||||
lz4_dir=
|
||||
])
|
||||
have_lz4=no
|
||||
if test "x$want_lz4" = "xno" ; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_WIRESHARK_LZ4_CHECK
|
||||
if test "x$want_lz4" = "xno" ; then
|
||||
AC_MSG_RESULT(lz4 not found - disabling lz4 compression and decompression)
|
||||
else
|
||||
if test "x$ac_cv_func_LZ4_decompress_safe" = "xno" ; then
|
||||
AC_MSG_RESULT(LZ4_decompress_safe not found in lz4 - disabling cql lz4 decompression)
|
||||
else
|
||||
have_lz4=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(LZ4_LIBS)
|
||||
|
||||
dnl snappy check
|
||||
SNAPPY_LIBS=''
|
||||
AC_MSG_CHECKING(whether to use snappy compression and decompression)
|
||||
|
||||
AC_ARG_WITH(snappy,
|
||||
AC_HELP_STRING([--with-snappy@<:@=DIR@:>@],
|
||||
[use snappy (located in directory DIR, if supplied) for snappy compression and decompression @<:@default=yes, if available@:>@]),
|
||||
[
|
||||
if test "x$withval" = "xno"
|
||||
then
|
||||
want_snappy=no
|
||||
elif test "x$withval" = "xyes"
|
||||
then
|
||||
want_snappy=yes
|
||||
else
|
||||
want_snappy=yes
|
||||
snappy_dir="$withval"
|
||||
fi
|
||||
],[
|
||||
#
|
||||
# Use snappy if it's present, otherwise don't.
|
||||
#
|
||||
want_snappy=ifavailable
|
||||
snappy_dir=
|
||||
])
|
||||
have_snappy=no
|
||||
if test "x$want_snappy" = "xno" ; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_WIRESHARK_SNAPPY_CHECK
|
||||
if test "x$want_snappy" = "xno" ; then
|
||||
AC_MSG_RESULT(snappy not found - disabling snappy compression and decompression)
|
||||
else
|
||||
if test "x$ac_cv_func_snappy_uncompress" = "xno" ; then
|
||||
AC_MSG_RESULT(snappy_uncompress not found in snappy - disabling cql snappy decompression)
|
||||
else
|
||||
have_snappy=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(SNAPPY_LIBS)
|
||||
|
||||
dnl Lua check
|
||||
AC_ARG_WITH(lua,
|
||||
AC_HELP_STRING( [--with-lua@<:@=DIR@:>@],
|
||||
|
@ -3083,4 +3169,6 @@ echo " Have ssh_userauth_agent : $ssh_userauth_agent_message"
|
|||
echo " Use nl library : $libnl_message"
|
||||
echo " Use SBC codec library : $have_sbc"
|
||||
echo " Use nghttp2 library : $nghttp2_message"
|
||||
echo " Use LZ4 library : $have_lz4"
|
||||
echo " Use Snappy library : $have_snappy"
|
||||
#echo " Use GDK-Pixbuf with GResource: $have_gresource_pixbuf"
|
||||
|
|
|
@ -189,17 +189,19 @@ add_lemon_files(LEMON_FILES GENERATED_FILES
|
|||
set(epan_LIBS
|
||||
wiretap
|
||||
wsutil
|
||||
${GLIB2_LIBRARIES}
|
||||
${PCAP_LIBRARIES}
|
||||
${CARES_LIBRARIES}
|
||||
${KERBEROS_LIBRARIES}
|
||||
${GEOIP_LIBRARIES}
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GEOIP_LIBRARIES}
|
||||
${GLIB2_LIBRARIES}
|
||||
${GNUTLS_LIBRARIES}
|
||||
${SMI_LIBRARIES}
|
||||
${KERBEROS_LIBRARIES}
|
||||
${LUA_LIBRARIES}
|
||||
${LZ4_LIBRARIES}
|
||||
${M_LIBRARIES}
|
||||
${NGHTTP2_LIBRARIES}
|
||||
${LUA_LIBRARIES}
|
||||
${PCAP_LIBRARIES}
|
||||
${SMI_LIBRARIES}
|
||||
${SNAPPY_LIBRARIES}
|
||||
${WIN_PSAPI_LIBRARY}
|
||||
)
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ DIST_SUBDIRS = $(SUBDIRS) $(wslua_dist_dir)
|
|||
AM_CPPFLAGS = $(INCLUDEDIRS) -I$(builddir)/wslua $(WS_CPPFLAGS) \
|
||||
$(GLIB_CFLAGS) $(LUA_CFLAGS) $(LIBGNUTLS_CFLAGS) \
|
||||
$(LIBGCRYPT_CFLAGS) $(LIBSMI_CFLAGS) $(LIBGEOIP_CFLAGS) \
|
||||
$(KRB5_CFLAGS)
|
||||
$(LZ4_CFLAGS) $(KRB5_CFLAGS) $(SNAPPY_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libwireshark_generated.la libwireshark_asmopt.la
|
||||
lib_LTLIBRARIES = libwireshark.la
|
||||
|
@ -323,13 +323,15 @@ libwireshark_la_LIBADD = \
|
|||
${top_builddir}/wiretap/libwiretap.la \
|
||||
${top_builddir}/wsutil/libwsutil.la \
|
||||
@C_ARES_LIBS@ \
|
||||
@GEOIP_LIBS@ \
|
||||
@KRB5_LIBS@ \
|
||||
@LIBGCRYPT_LIBS@ \
|
||||
@LIBGNUTLS_LIBS@ \
|
||||
@KRB5_LIBS@ \
|
||||
@SSL_LIBS@ \
|
||||
@LIBSMI_LDFLAGS@ \
|
||||
@GEOIP_LIBS@ \
|
||||
@LZ4_LIBS@ \
|
||||
@NGHTTP2_LIBS@ \
|
||||
@SSL_LIBS@ \
|
||||
@SNAPPY_LIBS@ \
|
||||
@GLIB_LIBS@
|
||||
|
||||
libwireshark_la_DEPENDENCIES = \
|
||||
|
|
|
@ -31,10 +31,17 @@
|
|||
#include <epan/dissectors/packet-tcp.h>
|
||||
#include <epan/wmem/wmem.h>
|
||||
#include <epan/expert.h>
|
||||
|
||||
#ifdef HAVE_LZ4
|
||||
#include <lz4.h>
|
||||
#endif
|
||||
#ifdef HAVE_SNAPPY
|
||||
#include <snappy-c.h>
|
||||
#endif
|
||||
|
||||
#define CQL_DEFAULT_PORT 9042 /* Not IANA registered */
|
||||
|
||||
/* the code can reasonably attempt to decompress buffer up to 10MB */
|
||||
#define MAX_UNCOMPRESSED_SIZE (10 * 1024 * 1024)
|
||||
|
||||
void proto_reg_handoff_cql(void);
|
||||
void proto_register_cql(void);
|
||||
|
@ -71,6 +78,7 @@ static int hf_cql_value_count = -1;
|
|||
static int hf_cql_short_bytes_length = -1;
|
||||
static int hf_cql_bytes_length = -1;
|
||||
static int hf_cql_bytes = -1;
|
||||
static int hf_cql_raw_compressed_bytes = -1;
|
||||
static int hf_cql_paging_state = -1;
|
||||
static int hf_cql_page_size = -1;
|
||||
static int hf_cql_timestamp = -1;
|
||||
|
@ -515,10 +523,18 @@ cql_transaction_lookup(cql_conversation_type* conv,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
CQL_COMPRESSION_NONE = 0,
|
||||
CQL_COMPRESSION_LZ4 = 1,
|
||||
CQL_COMPRESSION_SNAPPY = 2,
|
||||
CQL_DECOMPRESSION_ATTEMPTED = 3,
|
||||
} cql_compression_level;
|
||||
|
||||
static int
|
||||
dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
|
||||
dissect_cql_tcp_pdu(tvbuff_t* raw_tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
|
||||
{
|
||||
proto_item* ti;
|
||||
tvbuff_t* tvb = NULL;
|
||||
proto_tree* cql_tree;
|
||||
proto_tree* version_tree;
|
||||
proto_tree* cql_subtree = NULL;
|
||||
|
@ -526,6 +542,7 @@ dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* d
|
|||
proto_tree* metadata_subtree = NULL;
|
||||
|
||||
gint offset = 0;
|
||||
guint8 flags = 0;
|
||||
guint8 first_byte = 0;
|
||||
guint8 cql_version = 0;
|
||||
guint8 server_to_client = 0;
|
||||
|
@ -548,6 +565,7 @@ dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* d
|
|||
conversation_t* conversation;
|
||||
cql_conversation_type* cql_conv;
|
||||
cql_transaction_type* cql_trans = NULL;
|
||||
cql_compression_level compression_level = CQL_COMPRESSION_NONE;
|
||||
|
||||
static const int * cql_header_bitmaps_v3[] = {
|
||||
&hf_cql_flag_compression,
|
||||
|
@ -568,10 +586,10 @@ dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* d
|
|||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CQL");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
first_byte = tvb_get_guint8(tvb, 0);
|
||||
first_byte = tvb_get_guint8(raw_tvb, 0);
|
||||
cql_version = first_byte & (guint8)0x7F;
|
||||
server_to_client = first_byte & (guint8)0x80;
|
||||
opcode = tvb_get_guint8(tvb, 4);
|
||||
opcode = tvb_get_guint8(raw_tvb, 4);
|
||||
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO, "v%d %s Type %s",
|
||||
cql_version,
|
||||
|
@ -587,34 +605,34 @@ dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* d
|
|||
conversation_add_proto_data(conversation, proto_cql, cql_conv);
|
||||
}
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_cql, tvb, 0, -1, ENC_NA);
|
||||
ti = proto_tree_add_item(tree, proto_cql, raw_tvb, 0, -1, ENC_NA);
|
||||
cql_tree = proto_item_add_subtree(ti, ett_cql_protocol);
|
||||
|
||||
ti = proto_tree_add_item(cql_tree, hf_cql_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
ti = proto_tree_add_item(cql_tree, hf_cql_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
version_tree = proto_item_add_subtree(ti, ett_cql_version);
|
||||
proto_tree_add_item(version_tree, hf_cql_protocol_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(version_tree, hf_cql_direction, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(version_tree, hf_cql_protocol_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(version_tree, hf_cql_direction, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset += 1;
|
||||
switch(cql_version){
|
||||
case 3:
|
||||
proto_tree_add_bitmask(cql_tree, tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v3, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_bitmask(cql_tree, raw_tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v3, ENC_BIG_ENDIAN);
|
||||
break;
|
||||
case 4:
|
||||
proto_tree_add_bitmask(cql_tree, tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v4, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_bitmask(cql_tree, raw_tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v4, ENC_BIG_ENDIAN);
|
||||
break;
|
||||
default:
|
||||
proto_tree_add_item(cql_tree, hf_cql_flags_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(cql_tree, hf_cql_flags_bitmap, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
break;
|
||||
}
|
||||
flags = tvb_get_guint8(raw_tvb, offset);
|
||||
offset += 1;
|
||||
proto_tree_add_item_ret_int(cql_tree, hf_cql_stream, tvb, offset, 2, ENC_BIG_ENDIAN, &stream);
|
||||
proto_tree_add_item_ret_int(cql_tree, hf_cql_stream, raw_tvb, offset, 2, ENC_BIG_ENDIAN, &stream);
|
||||
offset += 2;
|
||||
proto_tree_add_item(cql_tree, hf_cql_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(cql_tree, hf_cql_opcode, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset += 1;
|
||||
proto_tree_add_item_ret_uint(cql_tree, hf_cql_length, tvb, offset, 4, ENC_BIG_ENDIAN, &message_length);
|
||||
proto_tree_add_item_ret_uint(cql_tree, hf_cql_length, raw_tvb, offset, 4, ENC_BIG_ENDIAN, &message_length);
|
||||
offset += 4;
|
||||
|
||||
|
||||
/* Track the request/response. */
|
||||
if (!pinfo->fd->flags.visited) {
|
||||
if (server_to_client == 0) {
|
||||
|
@ -637,20 +655,104 @@ dissect_cql_tcp_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* d
|
|||
/* Add state tracking to tree */
|
||||
if (server_to_client == 0 && cql_trans->rep_frame) {
|
||||
/* request */
|
||||
ti = proto_tree_add_uint(cql_tree, hf_cql_response_in, tvb, 0, 0, cql_trans->rep_frame);
|
||||
ti = proto_tree_add_uint(cql_tree, hf_cql_response_in, raw_tvb, 0, 0, cql_trans->rep_frame);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
}
|
||||
if (server_to_client && cql_trans->req_frame) {
|
||||
/* reply */
|
||||
nstime_t ns;
|
||||
|
||||
ti = proto_tree_add_uint(cql_tree, hf_cql_response_to, tvb, 0, 0, cql_trans->req_frame);
|
||||
ti = proto_tree_add_uint(cql_tree, hf_cql_response_to, raw_tvb, 0, 0, cql_trans->req_frame);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
nstime_delta(&ns, &pinfo->fd->abs_ts, &cql_trans->req_time);
|
||||
ti = proto_tree_add_time(cql_tree, hf_cql_response_time, tvb, 0, 0, &ns);
|
||||
ti = proto_tree_add_time(cql_tree, hf_cql_response_time, raw_tvb, 0, 0, &ns);
|
||||
PROTO_ITEM_SET_GENERATED(ti);
|
||||
}
|
||||
|
||||
/* We cannot rely on compression negociation in the STARTUP message because the
|
||||
* capture can be done at a random time hence missing the negociation.
|
||||
* So we will first try to decompress LZ4 then snappy
|
||||
*/
|
||||
if (flags & CQL_HEADER_FLAG_COMPRESSION) {
|
||||
compression_level = CQL_DECOMPRESSION_ATTEMPTED;
|
||||
#ifdef HAVE_LZ4
|
||||
if (tvb_captured_length_remaining(raw_tvb, offset) > 4) {
|
||||
/* Set ret == 0 to make it fail in case decompression is skipped
|
||||
* due to orig_size being too big
|
||||
*/
|
||||
guint32 ret = 0, orig_size = tvb_get_ntohl(raw_tvb, offset);
|
||||
guchar *decompressed_buffer = NULL;
|
||||
offset += 4;
|
||||
|
||||
/* if the decompressed size is reasonably small try to decompress data */
|
||||
if (orig_size <= MAX_UNCOMPRESSED_SIZE) {
|
||||
decompressed_buffer = (guchar*)wmem_alloc(pinfo->pool, orig_size);
|
||||
ret = LZ4_decompress_safe(tvb_get_ptr(raw_tvb, offset, -1),
|
||||
decompressed_buffer,
|
||||
tvb_captured_length_remaining(raw_tvb, offset),
|
||||
orig_size);
|
||||
}
|
||||
/* Decompression attempt failed: rewind offset */
|
||||
if (ret != orig_size) {
|
||||
wmem_free(pinfo->pool, decompressed_buffer);
|
||||
offset -= 4;
|
||||
} else {
|
||||
/* Now re-setup the tvb buffer to have the new data */
|
||||
tvb = tvb_new_child_real_data(raw_tvb, decompressed_buffer, orig_size, orig_size);
|
||||
add_new_data_source(pinfo, tvb, "Decompressed Data");
|
||||
/* mark the decompression as successfull */
|
||||
compression_level = CQL_COMPRESSION_LZ4;
|
||||
message_length= orig_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SNAPPY
|
||||
if (compression_level == CQL_DECOMPRESSION_ATTEMPTED) {
|
||||
guchar *decompressed_buffer = NULL;
|
||||
size_t orig_size = 0;
|
||||
snappy_status ret;
|
||||
|
||||
/* get the raw data length */
|
||||
ret = snappy_uncompressed_length(tvb_get_ptr(raw_tvb, offset, -1),
|
||||
tvb_captured_length_remaining(raw_tvb, offset),
|
||||
&orig_size);
|
||||
/* if we get the length and it's reasonably short to allocate a buffer for it
|
||||
* proceed to try decompressing the data
|
||||
*/
|
||||
if (ret == SNAPPY_OK && orig_size <= MAX_UNCOMPRESSED_SIZE) {
|
||||
decompressed_buffer = (guchar*)wmem_alloc(pinfo->pool, orig_size);
|
||||
|
||||
ret = snappy_uncompress(tvb_get_ptr(raw_tvb, offset, -1),
|
||||
tvb_captured_length_remaining(raw_tvb, offset),
|
||||
decompressed_buffer,
|
||||
&orig_size);
|
||||
} else {
|
||||
/* else mark the input as invalid in order to skip the rest of the
|
||||
* procedure
|
||||
*/
|
||||
ret = SNAPPY_INVALID_INPUT;
|
||||
}
|
||||
/* if the decompression succeeded build the new tvb */
|
||||
if (ret == SNAPPY_OK) {
|
||||
tvb = tvb_new_child_real_data(raw_tvb, decompressed_buffer, orig_size, orig_size);
|
||||
add_new_data_source(pinfo, tvb, "Decompressed Data");
|
||||
compression_level = CQL_COMPRESSION_SNAPPY;
|
||||
message_length= orig_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (compression_level == CQL_COMPRESSION_NONE) {
|
||||
/* In case of decompression failure or uncompressed packet */
|
||||
tvb = tvb_new_subset_remaining(raw_tvb, offset);
|
||||
} else if (compression_level == CQL_DECOMPRESSION_ATTEMPTED) {
|
||||
proto_tree_add_item(cql_tree, hf_cql_raw_compressed_bytes, raw_tvb, offset,
|
||||
tvb_captured_length_remaining(raw_tvb, offset), ENC_NA);
|
||||
return tvb_captured_length(raw_tvb);
|
||||
}
|
||||
offset = 0;
|
||||
|
||||
|
||||
/* Dissect the operation. */
|
||||
if (server_to_client == 0) {
|
||||
switch (opcode) {
|
||||
|
@ -1374,6 +1476,16 @@ proto_register_cql(void)
|
|||
"Raw byte array", HFILL
|
||||
}
|
||||
},
|
||||
{
|
||||
&hf_cql_raw_compressed_bytes,
|
||||
{
|
||||
"Raw compressed bytes", "cql.raw_compressed_bytes",
|
||||
FT_BYTES, BASE_NONE,
|
||||
NULL, 0x0,
|
||||
"Raw byte that failed to be decompressed", HFILL
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
&hf_cql_paging_state,
|
||||
{
|
||||
|
|
17
epan/epan.c
17
epan/epan.c
|
@ -574,6 +574,23 @@ epan_get_compiled_version_info(GString *str)
|
|||
#else
|
||||
g_string_append(str, "without nghttp2");
|
||||
#endif /* HAVE_NGHTTP2 */
|
||||
|
||||
/* LZ4 */
|
||||
g_string_append(str, ", ");
|
||||
#ifdef HAVE_LZ4
|
||||
g_string_append(str, "with LZ4");
|
||||
#else
|
||||
g_string_append(str, "without LZ4");
|
||||
#endif /* HAVE_LZ4 */
|
||||
|
||||
/* Snappy */
|
||||
g_string_append(str, ", ");
|
||||
#ifdef HAVE_SNAPPY
|
||||
g_string_append(str, "with Snappy");
|
||||
#else
|
||||
g_string_append(str, "without Snappy");
|
||||
#endif /* HAVE_SNAPPY */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue