aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt11
-rw-r--r--CMakeOptions.txt1
-rw-r--r--INSTALL7
-rw-r--r--cmake/modules/FindBROTLI.cmake50
-rw-r--r--cmakeconfig.h.in3
-rw-r--r--debian/control2
-rw-r--r--debian/libwireshark0.symbols2
-rw-r--r--docbook/release-notes.adoc2
-rw-r--r--epan/CMakeLists.txt3
-rw-r--r--epan/dissectors/packet-http.c17
-rw-r--r--epan/dissectors/packet-http2.c46
-rw-r--r--epan/epan.c18
-rw-r--r--epan/tvbuff.h18
-rw-r--r--epan/tvbuff_brotli.c192
-rw-r--r--packaging/rpm/wireshark.spec.in24
-rw-r--r--test/captures/http-brotli.pcapngbin0 -> 1840 bytes
-rw-r--r--test/captures/http2-brotli.pcapngbin0 -> 6484 bytes
-rw-r--r--test/fixtures_ws.py1
-rw-r--r--test/suite_dissection.py26
-rwxr-xr-xtools/debian-setup.sh4
-rwxr-xr-xtools/macos-setup-brew.sh2
-rwxr-xr-xtools/macos-setup.sh65
-rwxr-xr-xtools/rpm-setup.sh16
-rw-r--r--tools/win-setup.ps12
24 files changed, 496 insertions, 16 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e3478f06b..df62819651 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1104,6 +1104,9 @@ ws_find_package(CARES ENABLE_CARES HAVE_C_ARES "1.5.0")
# Zlib compression
ws_find_package(ZLIB ENABLE_ZLIB HAVE_ZLIB)
+# Brotli compression
+ws_find_package(BROTLI ENABLE_BROTLI HAVE_BROTLI)
+
# LZ4 compression
ws_find_package(LZ4 ENABLE_LZ4 HAVE_LZ4)
@@ -1809,6 +1812,11 @@ if(WIN32)
list (APPEND OPTIONAL_DLLS "${ZLIB_DLL_DIR}/${ZLIB_DLL}")
list (APPEND OPTIONAL_PDBS "${ZLIB_DLL_DIR}/${ZLIB_PDB}")
endif(ZLIB_FOUND)
+ if (BROTLI_FOUND)
+ foreach( _dll ${BROTLI_DLLS} )
+ list (APPEND OPTIONAL_DLLS "${BROTLI_DLL_DIR}/${_dll}")
+ endforeach(_dll)
+ endif(BROTLI_FOUND)
# With libs downloaded to c:/wireshark-win64-libs this currently
# (early 2018) expands to about 1900 characters.
@@ -2756,6 +2764,9 @@ if(RPMBUILD_EXECUTABLE)
if (SYSTEMD_FOUND)
list(APPEND _rpmbuild_with_args --with sdjournal)
endif()
+ if (BROTLI_FOUND)
+ list(APPEND _rpmbuild_with_args --with brotli)
+ endif()
execute_process(
COMMAND ${PERL_EXECUTABLE}
diff --git a/CMakeOptions.txt b/CMakeOptions.txt
index f4d4ce1f31..b99e949c44 100644
--- a/CMakeOptions.txt
+++ b/CMakeOptions.txt
@@ -65,6 +65,7 @@ option(ENABLE_PCAP_NG_DEFAULT "Enable pcapng as default file format" ON)
option(ENABLE_ZLIB "Build with zlib compression support" ON)
option(ENABLE_LZ4 "Build with LZ4 compression support" ON)
+option(ENABLE_BROTLI "Build with brotli compression support" ON)
option(ENABLE_SNAPPY "Build with Snappy compression support" ON)
option(ENABLE_NGHTTP2 "Build with HTTP/2 header decompression support" ON)
option(ENABLE_LUA "Build with Lua dissector support" ON)
diff --git a/INSTALL b/INSTALL
index f173ae01c4..cc7a4875db 100644
--- a/INSTALL
+++ b/INSTALL
@@ -153,6 +153,13 @@ README.windows for those instructions.
the capture-file utilities that come in this package, use
this switch.
+ -DENABLE_BROTLI=OFF
+ By default, if 'configure' finds brotli, the wiretap library
+ will be built so that it can read brotli compressed capture
+ files. If you have brotli but do not wish to build it into
+ the wiretap library, used by Wireshark, TShark, and the
+ capture-file utilities that come in this package, use this switch.
+
-DENABLE_PLUGINS=OFF
By default, if your system can support run-time loadable modules,
the packet analyzers are build with support for plugins.
diff --git a/cmake/modules/FindBROTLI.cmake b/cmake/modules/FindBROTLI.cmake
new file mode 100644
index 0000000000..4ab8dbb41c
--- /dev/null
+++ b/cmake/modules/FindBROTLI.cmake
@@ -0,0 +1,50 @@
+#
+# - Find brotli
+# Find brotli includes and libraries
+#
+# BROTLI_INCLUDE_DIRS - where to find brotli header files
+# BROTLI_LIBRARIES - List of libraries when using brotli.
+# BROTLI_FOUND - True if brotli found.
+# BROTLI_DLL_DIR - (Windows) Path to the brotli DLLs
+# BROTLI_DLLS - (Windows) Name of the brotli DLLs
+
+include( FindWSWinLibs )
+FindWSWinLibs( "brotli-.*" "BROTLI_HINTS" )
+
+find_path(BROTLI_INCLUDE_DIR
+ NAMES "brotli/decode.h"
+ HINTS "${BROTLI_HINTS}/include"
+)
+
+find_library(BROTLIDEC_LIBRARY
+ NAMES brotlidec
+ HINTS "${BROTLI_HINTS}/lib"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args( BROTLI DEFAULT_MSG BROTLIDEC_LIBRARY BROTLI_INCLUDE_DIR )
+
+if( BROTLI_FOUND )
+ set( BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR} )
+ set( BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY} )
+
+ if (WIN32)
+ set ( BROTLI_DLL_DIR "${BROTLI_HINTS}/bin"
+ CACHE PATH "Path to the brotli DLLs"
+ )
+ file( GLOB _brotli_dlls RELATIVE "${BROTLI_DLL_DIR}"
+ "${BROTLI_DLL_DIR}/brotlicommon*.dll"
+ "${BROTLI_DLL_DIR}/brotlidec*.dll"
+ )
+ set ( BROTLI_DLLS ${_brotli_dlls}
+ # We're storing filenames only. Should we use STRING instead?
+ CACHE FILEPATH "brotli DLL list"
+ )
+ mark_as_advanced( BROTLI_DLL_DIR BROTLI_DLLS )
+ endif()
+else()
+ set( BROTLI_INCLUDE_DIRS )
+ set( BROTLI_LIBRARIES )
+endif()
+
+mark_as_advanced( BROTLI_LIBRARIES BROTLI_INCLUDE_DIRS )
diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in
index 94f94feaf5..924d9347eb 100644
--- a/cmakeconfig.h.in
+++ b/cmakeconfig.h.in
@@ -136,6 +136,9 @@
/* Define to use zlib library */
#cmakedefine HAVE_ZLIB 1
+/* Define to use brotli library */
+#cmakedefine HAVE_BROTLI 1
+
/* Define to use lz4 library */
#cmakedefine HAVE_LZ4 1
diff --git a/debian/control b/debian/control
index e77637c971..5667fed82c 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,7 @@ Build-Depends: lsb-release,
libmaxminddb-dev, dpkg-dev (>= 1.16.1~), libsystemd-dev | libsystemd-journal-dev,
libnl-genl-3-dev [linux-any], libnl-route-3-dev [linux-any], asciidoctor,
cmake (>= 3.5) | cmake3, libsbc-dev, libnghttp2-dev, libssh-gcrypt-dev,
- liblz4-dev, libsnappy-dev, libspandsp-dev, libxml2-dev
+ liblz4-dev, libsnappy-dev, libspandsp-dev, libxml2-dev, libbrotli-dev
Build-Conflicts: libsnmp4.2-dev, libsnmp-dev
Vcs-Svn: svn://svn.debian.org/svn/collab-maint/ext-maint/wireshark/trunk
Vcs-Browser: http://svn.debian.org/wsvn/collab-maint/ext-maint/wireshark/trunk/
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols
index 02fccde73f..3844b5fa32 100644
--- a/debian/libwireshark0.symbols
+++ b/debian/libwireshark0.symbols
@@ -1680,6 +1680,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
tvb_captured_length@Base 1.12.0~rc1
tvb_captured_length_remaining@Base 1.12.0~rc1
tvb_child_uncompress@Base 1.12.0~rc1
+ tvb_child_uncompress_brotli@Base 3.1.0
tvb_clone@Base 1.12.0~rc1
tvb_clone_offset_len@Base 1.12.0~rc1
tvb_composite_append@Base 1.9.1
@@ -1801,6 +1802,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
tvb_strnlen@Base 1.9.1
tvb_strsize@Base 1.9.1
tvb_uncompress@Base 1.9.1
+ tvb_uncompress_brotli@Base 3.1.0
tvb_unicode_strsize@Base 1.9.1
tvb_ws_mempbrk_pattern_guint8@Base 1.99.3
tvbparse_casestring@Base 1.9.1
diff --git a/docbook/release-notes.adoc b/docbook/release-notes.adoc
index 4cc82eec27..3ad46bd5fa 100644
--- a/docbook/release-notes.adoc
+++ b/docbook/release-notes.adoc
@@ -34,7 +34,7 @@ Features” section below for more details.
The following features are new (or have been significantly updated)
since version 3.0.0:
-* Watch this space.
+* Brotli decompression support in HTTP/HTTP2 (requires the brotli library).
// === Removed Features and Support
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index bd13510591..2cd73eaceb 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -16,6 +16,7 @@ if (HAVE_HFI_SECTION_INIT)
endif()
include_directories(
+ ${BROTLI_INCLUDE_DIRS}
${GLIB2_INCLUDE_DIRS}
${CARES_INCLUDE_DIRS}
${GCRYPT_INCLUDE_DIRS}
@@ -265,6 +266,7 @@ set(LIBWIRESHARK_NONGENERATED_FILES
tvbparse.c
tvbuff.c
tvbuff_base64.c
+ tvbuff_brotli.c
tvbuff_composite.c
tvbuff_real.c
tvbuff_subset.c
@@ -378,6 +380,7 @@ target_link_libraries(epan
wsutil
${GLIB2_LIBRARIES}
PRIVATE
+ ${BROTLI_LIBRARIES}
${CARES_LIBRARIES}
${GCRYPT_LIBRARIES}
${GIO2_LIBRARIES}
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
index 4ee11d234e..0f3698508d 100644
--- a/epan/dissectors/packet-http.c
+++ b/epan/dissectors/packet-http.c
@@ -237,9 +237,9 @@ static gboolean http_desegment_body = TRUE;
static gboolean http_dechunk_body = TRUE;
/*
- * Decompression of zlib encoded entities.
+ * Decompression of zlib or brotli encoded entities.
*/
-#ifdef HAVE_ZLIB
+#if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
static gboolean http_decompress_body = TRUE;
#else
static gboolean http_decompress_body = FALSE;
@@ -1704,6 +1704,7 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_item *e_ti = NULL;
proto_tree *e_tree = NULL;
+#ifdef HAVE_ZLIB
if (http_decompress_body &&
(g_ascii_strcasecmp(headers.content_encoding, "gzip") == 0 ||
g_ascii_strcasecmp(headers.content_encoding, "deflate") == 0 ||
@@ -1713,6 +1714,16 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
uncomp_tvb = tvb_child_uncompress(tvb, next_tvb, 0,
tvb_captured_length(next_tvb));
}
+#endif
+
+#ifdef HAVE_BROTLI
+ if (http_decompress_body &&
+ g_ascii_strcasecmp(headers.content_encoding, "br") == 0)
+ {
+ uncomp_tvb = tvb_child_uncompress_brotli(tvb, next_tvb, 0,
+ tvb_captured_length(next_tvb));
+ }
+#endif
/*
* Add the encoded entity to the protocol tree
@@ -4017,7 +4028,7 @@ proto_register_http(void)
"Whether to reassemble bodies of entities that are transferred "
"using the \"Transfer-Encoding: chunked\" method",
&http_dechunk_body);
-#ifdef HAVE_ZLIB
+#if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
prefs_register_bool_preference(http_module, "decompress_body",
"Uncompress entity bodies",
"Whether to uncompress entity bodies that are compressed "
diff --git a/epan/dissectors/packet-http2.c b/epan/dissectors/packet-http2.c
index 331ec4ac37..6f3332a0f8 100644
--- a/epan/dissectors/packet-http2.c
+++ b/epan/dissectors/packet-http2.c
@@ -65,9 +65,9 @@ VALUE_STRING_ENUM(http2_header_repr_type);
VALUE_STRING_ARRAY(http2_header_repr_type);
/*
- * Decompression of zlib encoded entities.
+ * Decompression of zlib or brotli encoded entities.
*/
-#ifdef HAVE_ZLIB
+#if defined(HAVE_ZLIB) || defined(HAVE_BROTLI)
static gboolean http2_decompress_body = TRUE;
#else
static gboolean http2_decompress_body = FALSE;
@@ -1985,18 +1985,36 @@ dissect_frame_prio(tvbuff_t *tvb, proto_tree *http2_tree, guint offset, guint8 f
}
#ifdef HAVE_NGHTTP2
-static int
-can_uncompress_body(packet_info *pinfo)
+enum body_uncompression {
+ BODY_UNCOMPRESSION_NONE,
+ BODY_UNCOMPRESSION_ZLIB,
+ BODY_UNCOMPRESSION_BROTLI
+};
+
+static enum body_uncompression
+get_body_uncompression_info(packet_info *pinfo)
{
http2_data_stream_body_info_t *body_info = get_data_stream_body_info(pinfo);
gchar *content_encoding = body_info->content_encoding;
/* Check we have a content-encoding header appropriate as well as checking if this is partial content.
* We can't decompress part of a gzip encoded entity */
- return http2_decompress_body
- && body_info->is_partial_content == FALSE
- && content_encoding != NULL
- && (strncmp(content_encoding, "gzip", 4) == 0 || strncmp(content_encoding, "deflate", 7) == 0);
+ if (!http2_decompress_body || body_info->is_partial_content == TRUE || content_encoding == NULL) {
+ return BODY_UNCOMPRESSION_NONE;
+ }
+
+#ifdef HAVE_ZLIB
+ if (strncmp(content_encoding, "gzip", 4) == 0 || strncmp(content_encoding, "deflate", 7) == 0) {
+ return BODY_UNCOMPRESSION_ZLIB;
+ }
+#endif
+#ifdef HAVE_BROTLI
+ if (strncmp(content_encoding, "br", 2) == 0) {
+ return BODY_UNCOMPRESSION_BROTLI;
+ }
+#endif
+
+ return BODY_UNCOMPRESSION_NONE;
}
/* Try to dissect reassembled http2.data.data according to content_type. */
@@ -2027,9 +2045,17 @@ dissect_http2_data_full_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *http
gint datalen = tvb_reported_length(tvb);
- if (can_uncompress_body(pinfo)) {
+ enum body_uncompression uncompression = get_body_uncompression_info(pinfo);
+ if (uncompression != BODY_UNCOMPRESSION_NONE) {
proto_item *compressed_proto_item = NULL;
- tvbuff_t *uncompressed_tvb = tvb_child_uncompress(tvb, tvb, 0, datalen);
+
+ tvbuff_t *uncompressed_tvb = NULL;
+ if (uncompression == BODY_UNCOMPRESSION_ZLIB) {
+ uncompressed_tvb = tvb_child_uncompress(tvb, tvb, 0, datalen);
+ } else if (uncompression == BODY_UNCOMPRESSION_BROTLI) {
+ uncompressed_tvb = tvb_child_uncompress_brotli(tvb, tvb, 0, datalen);
+ }
+
http2_data_stream_body_info_t *body_info = get_data_stream_body_info(pinfo);
gchar *compression_method = body_info->content_encoding;
diff --git a/epan/epan.c b/epan/epan.c
index 2c475e64b0..04d9d08cef 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -80,6 +80,10 @@
#include <nghttp2/nghttp2ver.h>
#endif
+#ifdef HAVE_BROTLI
+#include <brotli/decode.h>
+#endif
+
#ifdef HAVE_LIBXML2
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
@@ -769,6 +773,14 @@ epan_get_compiled_version_info(GString *str)
g_string_append(str, "without nghttp2");
#endif /* HAVE_NGHTTP2 */
+ /* brotli */
+ g_string_append(str, ", ");
+#ifdef HAVE_BROTLI
+ g_string_append(str, "with brotli");
+#else
+ g_string_append(str, "without brotli");
+#endif /* HAVE_BROTLI */
+
/* LZ4 */
g_string_append(str, ", ");
#ifdef HAVE_LZ4
@@ -808,6 +820,12 @@ epan_get_runtime_version_info(GString *str)
/* Gcrypt */
g_string_append_printf(str, ", with Gcrypt %s", gcry_check_version(NULL));
+
+ /* brotli */
+#ifdef HAVE_BROTLI
+ g_string_append_printf(str, ", with brotli %d.%d.%d", BrotliDecoderVersion() >> 24,
+ (BrotliDecoderVersion() >> 12) & 0xFFF, BrotliDecoderVersion() & 0xFFF);
+#endif
}
/*
diff --git a/epan/tvbuff.h b/epan/tvbuff.h
index 763a659762..7b93f98772 100644
--- a/epan/tvbuff.h
+++ b/epan/tvbuff.h
@@ -907,6 +907,24 @@ WS_DLL_PUBLIC tvbuff_t *tvb_uncompress(tvbuff_t *tvb, const int offset,
WS_DLL_PUBLIC tvbuff_t *tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb,
const int offset, int comprlen);
+/* From tvbuff_brotli.c */
+
+/**
+ * Uncompresses a brotli compressed packet inside a tvbuff at offset with
+ * length comprlen. Returns an uncompressed tvbuffer if uncompression
+ * succeeded or NULL if uncompression failed.
+ */
+WS_DLL_PUBLIC tvbuff_t *tvb_uncompress_brotli(tvbuff_t *tvb, const int offset,
+ int comprlen);
+
+/**
+ * Uncompresses a brotli compressed packet inside a tvbuff at offset with
+ * length comprlen. Returns an uncompressed tvbuffer attached to tvb if
+ * uncompression succeeded or NULL if uncompression failed.
+ */
+WS_DLL_PUBLIC tvbuff_t *tvb_child_uncompress_brotli(tvbuff_t *parent, tvbuff_t *tvb,
+ const int offset, int comprlen);
+
/* From tvbuff_base64.c */
/** Return a tvb that contains the binary representation of a base64
diff --git a/epan/tvbuff_brotli.c b/epan/tvbuff_brotli.c
new file mode 100644
index 0000000000..3e38c6508b
--- /dev/null
+++ b/epan/tvbuff_brotli.c
@@ -0,0 +1,192 @@
+/* tvbuff_brotli.c
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <string.h>
+
+#ifdef HAVE_BROTLI
+#include <brotli/decode.h>
+#endif
+
+#include "tvbuff.h"
+
+#ifdef HAVE_BROTLI
+
+/*
+ * 512KiB is the buffer size used by the brotli tool, so we
+ * use that too.
+ */
+#define TVB_BROTLI_BUFSIZ (1 << 19)
+
+static void*
+brotli_g_malloc_wrapper(void *opaque _U_, size_t size)
+{
+ return g_malloc(size);
+}
+
+static void
+brotli_g_free_wrapper(void *opaque _U_, void *address)
+{
+ g_free(address);
+}
+
+/*
+ * Uncompresses a brotli compressed packet inside a message of tvb at offset with
+ * length comprlen. Returns an uncompressed tvbuffer if uncompression
+ * succeeded or NULL if uncompression failed.
+ */
+
+tvbuff_t *
+tvb_uncompress_brotli(tvbuff_t *tvb, const int offset, int comprlen)
+{
+ guint8 *compr;
+ guint8 *uncompr = NULL;
+ tvbuff_t *uncompr_tvb;
+ BrotliDecoderState *decoder;
+ guint8 *strmbuf;
+ const size_t bufsiz = TVB_BROTLI_BUFSIZ;
+ size_t available_in;
+ const guint8 *next_in;
+ size_t available_out;
+ guint8 *next_out;
+ size_t total_out;
+ guint needs_more_output;
+ guint finished;
+
+ if (tvb == NULL || comprlen <= 0) {
+ return NULL;
+ }
+
+ compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
+ if (compr == NULL) {
+ return NULL;
+ }
+
+ decoder = BrotliDecoderCreateInstance(
+ &brotli_g_malloc_wrapper /*alloc_func*/,
+ &brotli_g_free_wrapper /*free_func*/,
+ NULL /*opaque*/);
+ if (decoder == NULL) {
+ wmem_free(NULL, compr);
+ return NULL;
+ }
+ strmbuf = (guint8 *)g_malloc(bufsiz);
+
+ available_in = comprlen;
+ next_in = compr;
+ total_out = 0;
+ needs_more_output = 0;
+ finished = 0;
+ while (available_in > 0 || needs_more_output) {
+ needs_more_output = 0;
+ available_out = bufsiz;
+ next_out = strmbuf;
+
+ BrotliDecoderResult result = BrotliDecoderDecompressStream(
+ decoder, &available_in, &next_in, &available_out, &next_out, &total_out);
+ switch (result) {
+ case BROTLI_DECODER_RESULT_SUCCESS:
+ if (available_in > 0) {
+ goto cleanup;
+ }
+ finished = 1;
+ break;
+ case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
+ needs_more_output = 1;
+ break;
+ case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
+ /*
+ * It's possible that not enough frames were captured
+ * to decompress this fully, so return what we've done
+ * so far, if any.
+ */
+ break;
+ case BROTLI_DECODER_RESULT_ERROR:
+ default:
+ goto cleanup;
+ }
+
+ /*
+ * Check if decompressed size is too large.
+ */
+ if (total_out > G_MAXINT) {
+ goto cleanup;
+ }
+
+ /*
+ * BrotliDecoderDecompressStream sets available_out to the number of bytes
+ * left unused from the buffer. But we are interested in the bytes it wrote
+ * to the buffer in this pass, so we calculate pass_out.
+ */
+ size_t pass_out = bufsiz - available_out;
+ if (pass_out > 0) {
+ uncompr = (guint8 *)g_realloc(uncompr, total_out);
+ memcpy(uncompr + (total_out - pass_out), strmbuf, pass_out);
+ }
+ }
+
+ if (uncompr == NULL) {
+ /*
+ * This is for the case when the validly decompressed
+ * length is 0.
+ */
+ if (finished) {
+ uncompr = (guint8 *)g_strdup("");
+ } else {
+ goto cleanup;
+ }
+ }
+
+ uncompr_tvb = tvb_new_real_data((guint8 *)uncompr, (guint)total_out, (gint)total_out);
+ tvb_set_free_cb(uncompr_tvb, g_free);
+
+ g_free(strmbuf);
+ wmem_free(NULL, compr);
+ BrotliDecoderDestroyInstance(decoder);
+ return uncompr_tvb;
+
+cleanup:
+ g_free(strmbuf);
+ g_free(uncompr);
+ wmem_free(NULL, compr);
+ BrotliDecoderDestroyInstance(decoder);
+ return NULL;
+}
+#else
+tvbuff_t *
+tvb_uncompress_brotli(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
+{
+ return NULL;
+}
+#endif
+
+tvbuff_t *
+tvb_child_uncompress_brotli(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
+{
+ tvbuff_t *new_tvb = tvb_uncompress_brotli(tvb, offset, comprlen);
+ if (new_tvb)
+ tvb_set_child_real_data_tvbuff(parent, new_tvb);
+ return new_tvb;
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/packaging/rpm/wireshark.spec.in b/packaging/rpm/wireshark.spec.in
index 56e1caecce..eab250cddf 100644
--- a/packaging/rpm/wireshark.spec.in
+++ b/packaging/rpm/wireshark.spec.in
@@ -19,6 +19,7 @@
%bcond_with nghttp2
%bcond_with sdjournal
%bcond_with guides
+%bcond_with brotli
# Set at most one of these two:
@@ -145,6 +146,21 @@ Requires: systemd-libs
%endif
%endif
+%if %{with brotli}
+%if 0%{?suse_version}
+BuildRequires: libbrotli-devel
+# On SUSE libbrotli-devel installs the libbrotlidec.so, libbrotlienc.so
+# and libbrotlicommon.so symlinks, but only installs the libbrotlicommon1 and libbrotlienc1
+# packages, leaving the libbrotlidec.so symlink broken, so we have to include libbrotlidec1
+# as a build-time dependency...
+BuildRequires: libbrotlidec1
+Requires: libbrotlidec1
+%else
+BuildRequires: brotli-devel
+Requires: brotli
+%endif
+%endif
+
# Uncomment these if you want to be sure you get them...
#BuildRequires: krb5-devel
#BuildRequires: libsmi-devel
@@ -315,6 +331,11 @@ cmake3 \
%else
-DBUILD_sdjournal=OFF \
%endif
+%if %{with brotli}
+ -DENABLE_BROTLI=ON \
+%else
+ -DENABLE_BROTLI=OFF \
+%endif
-DDISABLE_WERROR=ON \
%if %{with ninja}
-G Ninja \
@@ -476,6 +497,9 @@ update-mime-database %{_datadir}/mime &> /dev/null || :
%{_libdir}/pkgconfig/wireshark.pc
%changelog
+* Mon Apr 22 2019 Daniel Bakai
+- Added brotli (as an option, defaulting to not required).
+
* Fri Sep 28 2018 Gerald Combs
- Add sdjournal
diff --git a/test/captures/http-brotli.pcapng b/test/captures/http-brotli.pcapng
new file mode 100644
index 0000000000..5d7a499d1f
--- /dev/null
+++ b/test/captures/http-brotli.pcapng
Binary files differ
diff --git a/test/captures/http2-brotli.pcapng b/test/captures/http2-brotli.pcapng
new file mode 100644
index 0000000000..7e07e857b5
--- /dev/null
+++ b/test/captures/http2-brotli.pcapng
Binary files differ
diff --git a/test/fixtures_ws.py b/test/fixtures_ws.py
index a7d633ac35..161da3f3ce 100644
--- a/test/fixtures_ws.py
+++ b/test/fixtures_ws.py
@@ -169,6 +169,7 @@ def features(cmd_tshark, make_env):
have_libgcrypt17=gcry_m and float(gcry_m.group(1)) >= 1.7,
have_gnutls='with GnuTLS' in tshark_v,
have_pkcs11='and PKCS #11 support' in tshark_v,
+ have_brotli='with brotli' in tshark_v,
)
diff --git a/test/suite_dissection.py b/test/suite_dissection.py
index 9a62e933cc..c9234245cc 100644
--- a/test/suite_dissection.py
+++ b/test/suite_dissection.py
@@ -16,6 +16,20 @@ import fixtures
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
+class case_dissect_http(subprocesstest.SubprocessTestCase):
+ def test_http_brotli_decompression(self, cmd_tshark, features, dirs, capture_file):
+ '''HTTP brotli decompression'''
+ if not features.have_brotli:
+ self.skipTest('Requires brotli.')
+ self.assertRun((cmd_tshark,
+ '-r', capture_file('http-brotli.pcapng'),
+ '-Y', 'http.response.code==200',
+ '-Tfields', '-etext',
+ ))
+ self.assertTrue(self.grepOutput('This is a test file for testing brotli decompression in Wireshark'))
+
+@fixtures.mark_usefixtures('test_env')
+@fixtures.uses_fixtures
class case_dissect_http2(subprocesstest.SubprocessTestCase):
def test_http2_data_reassembly(self, cmd_tshark, features, dirs, capture_file):
'''HTTP2 data reassembly'''
@@ -30,6 +44,18 @@ class case_dissect_http2(subprocesstest.SubprocessTestCase):
))
self.assertTrue(self.grepOutput('DATA'))
+ def test_http2_brotli_decompression(self, cmd_tshark, features, dirs, capture_file):
+ '''HTTP2 brotli decompression'''
+ if not features.have_nghttp2:
+ self.skipTest('Requires nghttp2.')
+ if not features.have_brotli:
+ self.skipTest('Requires brotli.')
+ self.assertRun((cmd_tshark,
+ '-r', capture_file('http2-brotli.pcapng'),
+ '-Y', 'http2.data.data matches "This is a test file for testing brotli decompression in Wireshark"',
+ ))
+ self.assertTrue(self.grepOutput('DATA'))
+
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_dissect_tcp(subprocesstest.SubprocessTestCase):
diff --git a/tools/debian-setup.sh b/tools/debian-setup.sh
index 931d869139..3cb3738d95 100755
--- a/tools/debian-setup.sh
+++ b/tools/debian-setup.sh
@@ -137,6 +137,10 @@ echo "libgnutls28-dev is unavailable" >&2
add_package ADDITIONAL_LIST libmaxminddb-dev ||
echo "libmaxminddb-dev is unavailable" >&2
+# Debian >= stretch-backports, Ubuntu >= 16.04
+add_package ADDITIONAL_LIST libbrotli-dev ||
+echo "libbrotli-dev is unavailable" >&2
+
# libsystemd-journal-dev: Ubuntu 14.04
# libsystemd-dev: Ubuntu >= 16.04
add_package DEBDEPS_LIST libsystemd-dev ||
diff --git a/tools/macos-setup-brew.sh b/tools/macos-setup-brew.sh
index 648c445e69..15cd58478b 100755
--- a/tools/macos-setup-brew.sh
+++ b/tools/macos-setup-brew.sh
@@ -13,7 +13,7 @@
brew update
#install some libs needed by Wireshark
-brew install c-ares glib libgcrypt gnutls lua@5.1 cmake python nghttp2 snappy lz4 libxml2 ninja libmaxminddb doxygen libsmi spandsp
+brew install c-ares glib libgcrypt gnutls lua@5.1 cmake python nghttp2 snappy lz4 libxml2 ninja libmaxminddb doxygen libsmi spandsp brotli
#install Qt5
brew install qt5
diff --git a/tools/macos-setup.sh b/tools/macos-setup.sh
index 6fcf9a926c..ee39a0fdba 100755
--- a/tools/macos-setup.sh
+++ b/tools/macos-setup.sh
@@ -172,6 +172,7 @@ if [ "$SPANDSP_VERSION" ]; then
fi
BCG729_VERSION=1.0.2
PYTHON3_VERSION=3.7.1
+BROTLI_VERSION=1.0.7
#
# GNU autotools; they're provided with releases up to Snow Leopard, but
@@ -1711,11 +1712,70 @@ uninstall_python3() {
fi
}
+install_brotli() {
+ if [ "$BROTLI_VERSION" -a ! -f brotli-$BROTLI_VERSION-done ] ; then
+ echo "Downloading, building, and installing brotli:"
+ [ -f brotli-$BROTLI_VERSION.tar.gz ] || curl -L -o brotli-$BROTLI_VERSION.tar.gz https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz || exit 1
+ $no_build && echo "Skipping installation" && return
+ gzcat brotli-$BROTLI_VERSION.tar.gz | tar xf - || exit 1
+ cd brotli-$BROTLI_VERSION
+ mkdir build_dir
+ cd build_dir
+ MACOSX_DEPLOYMENT_TARGET=$min_osx_target SDKROOT="$SDKPATH" cmake ../ || exit 1
+ make $MAKE_BUILD_OPTS || exit 1
+ $DO_MAKE_INSTALL || exit 1
+ cd ../..
+ touch brotli-$BROTLI_VERSION-done
+ fi
+}
+
+uninstall_brotli() {
+ if [ ! -z "$installed_brotli_version" ] ; then
+ echo "Uninstalling brotli:"
+ cd brotli-$installed_brotli_version
+ #
+ # brotli uses cmake on macOS and doesn't support "make uninstall"
+ #
+ # $DO_MAKE_UNINSTALL || exit 1
+ sudo rm -rf /usr/local/bin/brotli
+ sudo rm -rf /usr/local/lib/libbrotli*
+ sudo rm -rf /usr/local/include/brotli
+ sudo rm -rf /usr/local/lib/pkgconfig/libbrotli*
+ #
+ # brotli uses cmake on macOS and doesn't support "make distclean"
+ #
+ # make distclean || exit 1
+ cd ..
+ rm brotli-$installed_brotli_version-done
+
+ if [ "$#" -eq 1 -a "$1" = "-r" ] ; then
+ #
+ # Get rid of the previously downloaded and unpacked version.
+ #
+ rm -rf brotli-$installed_brotli_version
+ rm -rf brotli-$installed_brotli_version.tar.gz
+ fi
+
+ installed_brotli_version=""
+ fi
+}
+
install_all() {
#
# Check whether the versions we have installed are the versions
# requested; if not, uninstall the installed versions.
#
+ if [ ! -z "$installed_brotli_version" -a \
+ "$installed_brotli_version" != "$BROTLI_VERSION" ] ; then
+ echo "Installed brotli version is $installed_brotli_version"
+ if [ -z "$BROTLI_VERSION" ] ; then
+ echo "brotli is not requested"
+ else
+ echo "Requested brotli version is $BROTLI_VERSION"
+ fi
+ uninstall_brotli -r
+ fi
+
if [ ! -z "$installed_python3_version" -a \
"$installed_python3_version" != "$PYTHON3_VERSION" ] ; then
echo "Installed python3 version is $installed_python3_version"
@@ -2188,6 +2248,8 @@ install_all() {
install_bcg729
install_python3
+
+ install_brotli
}
uninstall_all() {
@@ -2204,6 +2266,8 @@ uninstall_all() {
# We also do a "make distclean", so that we don't have leftovers from
# old configurations.
#
+ uninstall_brotli
+
uninstall_python3
uninstall_bcg729
@@ -2406,6 +2470,7 @@ then
installed_spandsp_version=`ls spandsp-*-done 2>/dev/null | sed 's/spandsp-\(.*\)-done/\1/'`
installed_bcg729_version=`ls bcg729-*-done 2>/dev/null | sed 's/bcg729-\(.*\)-done/\1/'`
installed_python3_version=`ls python3-*-done 2>/dev/null | sed 's/python3-\(.*\)-done/\1/'`
+ installed_brotli_version=`ls brotli-*-done 2>/dev/null | sed 's/brotli-\(.*\)-done/\1/'`
cd $topdir
fi
diff --git a/tools/rpm-setup.sh b/tools/rpm-setup.sh
index ba07180e82..75b9a766a0 100755
--- a/tools/rpm-setup.sh
+++ b/tools/rpm-setup.sh
@@ -106,6 +106,19 @@ add_package() {
eval "${list}=\"\${${list}} \${pkgname}\""
}
+# Adds packages $2-$n to list variable $1 if all the packages are found
+add_packages() {
+ local list="$1" pkgnames="${@:2}"
+
+ # fail if any package is not known
+ for pkgname in $pkgnames; do
+ $PM $PM_SEARCH "$pkgname" &> /dev/null || return 1
+ done
+
+ # all packages are found, append it to list
+ eval "${list}=\"\${${list}} \${pkgnames}\""
+}
+
# python3: OpenSUSE 43.3, Fedora 26
# python34: Centos 7
add_package BASIC_LIST python3 || add_package BASIC_LIST python34 ||
@@ -197,6 +210,9 @@ echo "ninja is unavailable" >&2
add_package ADDITIONAL_LIST libxslt || add_package ADDITIONAL_LIST libxslt1 ||
echo "xslt is unavailable" >&2
+add_package ADDITIONAL_LIST brotli-devel || add_packages ADDITIONAL_LIST libbrotli-devel libbrotlidec1 ||
+echo "brotli is unavailable" >&2
+
ACTUAL_LIST=$BASIC_LIST
# Now arrange for optional support libraries
diff --git a/tools/win-setup.ps1 b/tools/win-setup.ps1
index 6cfd06d162..62eea5c938 100644
--- a/tools/win-setup.ps1
+++ b/tools/win-setup.ps1
@@ -76,6 +76,7 @@ $Win32CurrentTag = "2019-04-08"
$Win64Archives = @{
"AirPcap_Devpack_4_1_0_1622.zip" = "09d637f28a79b1d2ecb09f35436271a90c0f69bd0a1ee82b803abaaf63c18a69";
"bcg729-1.0.4-win64ws.zip" = "9a095fda4c39860d96f0c568830faa6651cd17635f68e27aa6de46c689aa0ee2";
+ "brotli-1.0.2-4-win64ws.zip" = "f60636764f0e2539ad86d37826e90445a346291f8d046bd4f5c998301f200195";
"c-ares-1.15.0-win64ws.zip" = "ade864fd08e887d353a9c939fa6e68b0bf3e08761b6e81f60ce15e6543256552";
"gnutls-3.6.3-1-win64ws.zip" = "994ac2578e7b4ca01e589ab2598927d53f7370bc3ff679f3006b0e6bb7a06df4";
"krb5-1.17-1-win64ws.zip" = "1f4a7ab86ae331ea9e58c9776a60def81ae9fe622882b2e8da2ad6ce6f6fb1d8";
@@ -97,6 +98,7 @@ $Win64Archives = @{
$Win32Archives = @{
"AirPcap_Devpack_4_1_0_1622.zip" = "09d637f28a79b1d2ecb09f35436271a90c0f69bd0a1ee82b803abaaf63c18a69";
"bcg729-1.0.4-win32ws.zip" = "b785ec78dec6bca8252130eb884bfa28c1140001dd7369a535579176de9e4271";
+ "brotli-1.0.2-4-win32ws.zip" = "193a9b35e42a73f77dabe2c99c57173d7f2bb215118c1cd027a6cf522cc3dc14";
"c-ares-1.15.0-win32ws.zip" = "a54151203a631b478470aaa21b3a1fde6178f2fea9f15a1a6da4bfcecc92cfcd";
"gnutls-3.6.3-1-win32ws.zip" = "42d8313ffb888f525d6c39330c39bcc2182e68ee8433a09dd85e1f1e1474f592";
"krb5-1.17-1-win32ws.zip" = "f90cac08355ccfe624652d3e05f8e2e077b8830382315d4ea0a6fa52af08260b";