[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#856640: unblock: suricata/3.2.1-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package suricata

The 3.2.1 release includes lots of bugfixes and some of them were direct
security threats (debian security team is already in knowedge of them), which
are special important in security-realted software.
By now, I don't consider updating stretch with only the cherrypicked upstream
commits related to the security issues.

The suricata package is a key package in security related tasks, like an
antivirus, it has to be very updated to stay useful. Thats why I'm asking
for a rather large unblock at this point in the release cycle.
We currently maintain suricata heavily using stable-backports due to this
reason.

The new package is living in experimental and has not been uploaded to unstable
yet.

I'm attaching the debdiff due to it being a bit large.

The debdiff was generated this way:
% debdiff suricata_3.2-2.dsc suricata_3.2.1-1~exp2.dsc

The diffstat follows:
% cat suricata_debdiff.diff  | diffstat
 ChangeLog                                   |   33 
 config.h.in                                 |    6 
 configure                                   |   94 +-
 configure.ac                                |   76 +-
 debian/changelog                            |   15 
 debian/control                              |   18 
 debian/patches/optional-hyperscan.patch     |   21 
 debian/patches/series                       |    1 
 debian/rules                                |   40 -
 debian/suricata-hyperscan.install           |    3 
 debian/suricata-hyperscan.postinst          |    8 
 debian/suricata-hyperscan.prerm             |   21 
 debian/suricata.init                        |    5 
 debian/suricata.install                     |    6 
 debian/suricata.postinst                    |    8 
 debian/suricata.preinst                     |   11 
 debian/suricata.prerm                       |   21 
 doc/userguide/capture-hardware/index.rst    |    1 
 doc/userguide/capture-hardware/napatech.rst |  215 +++++
 doc/userguide/output/lua-output.rst         |   16 
 doc/userguide/rules/dnp3-keywords.rst       |    2 
 doc/userguide/rules/index.rst               |    1 
 doc/userguide/rules/tls-keywords.rst        |   12 
 doc/userguide/rules/xbits.rst               |   48 +
 doc/userguide/suricata.1                    |    2 
 rules/tls-events.rules                      |    3 
 scripts/suricatasc/Makefile.in              |    2 
 src/Makefile.am                             |    1 
 src/Makefile.in                             |   30 
 src/alert-prelude.c                         |    5 
 src/app-layer-dcerpc.c                      |   26 
 src/app-layer-detect-proto.c                |  107 +-
 src/app-layer-detect-proto.h                |    6 
 src/app-layer-dnp3.c                        |    6 
 src/app-layer-dns-common.c                  |    5 
 src/app-layer-dns-tcp.c                     |   34 
 src/app-layer-dns-udp.c                     |   11 
 src/app-layer-enip.c                        |   18 
 src/app-layer-htp-file.c                    |    4 
 src/app-layer-htp.c                         |    4 
 src/app-layer-modbus.c                      |    8 
 src/app-layer-parser.c                      |   33 
 src/app-layer-parser.h                      |    6 
 src/app-layer-smb.c                         |   34 
 src/app-layer-smtp.c                        |   16 
 src/app-layer-ssl.c                         |   24 
 src/app-layer-ssl.h                         |    6 
 src/app-layer-template.c                    |    6 
 src/decode-afl.c                            |  167 ++++
 src/decode-icmpv6.c                         |  141 +++
 src/decode-icmpv6.h                         |   23 
 src/decode.c                                |   49 -
 src/decode.h                                |    8 
 src/defrag-hash.c                           |    2 
 src/defrag.c                                |  170 ++--
 src/defrag.h                                |    2 
 src/detect-app-layer-event.c                |   14 
 src/detect-csum.c                           |    2 
 src/detect-dns-query.c                      |   14 
 src/detect-engine-address.c                 |    5 
 src/detect-engine-alert.c                   |    6 
 src/detect-engine-file.c                    |    2 
 src/detect-engine-filedata-smtp.c           |    4 
 src/detect-engine-mpm.c                     |    2 
 src/detect-engine-payload.c                 |   68 -
 src/detect-engine-siggroup.c                |   50 -
 src/detect-engine-tls.c                     |    6 
 src/detect-engine.c                         |    2 
 src/detect-filemagic.c                      |   32 
 src/detect-filemagic.h                      |    5 
 src/detect-filesize.c                       |    2 
 src/detect-http-header.c                    |    2 
 src/detect-ipproto.c                        |    4 
 src/detect-parse.c                          |    6 
 src/detect-tls-cert-issuer.c                |    3 
 src/detect-tls-cert-subject.c               |    3 
 src/detect-tls-sni.c                        |    5 
 src/detect-xbits.c                          |  215 +++--
 src/detect-xbits.h                          |    2 
 src/detect.c                                |   11 
 src/detect.h                                |    6 
 src/flow.c                                  |   24 
 src/flow.h                                  |    5 
 src/host-bit.c                              |    1 
 src/log-dnslog.c                            |   68 +
 src/log-file.c                              |    6 
 src/log-filestore.c                         |    5 
 src/log-pcap.c                              |    7 
 src/log-tlsstore.c                          |    5 
 src/output-file.c                           |    4 
 src/output-filedata.c                       |    5 
 src/output-json-dns.c                       |    4 
 src/output-json-file.c                      |    4 
 src/output-json-flow.c                      |    2 
 src/output-json-template.c                  |    3 
 src/output-tx.c                             |   40 -
 src/queue.h                                 |   12 
 src/runmode-unittests.c                     |  141 +--
 src/runmode-unix-socket.c                   |  129 +--
 src/runmodes.c                              |    9 
 src/source-af-packet.c                      |   64 +
 src/stream-tcp-reassemble.c                 |   27 
 src/suricata-common.h                       |   31 
 src/suricata.c                              | 1018 +++++++++++++++-------------
 src/suricata.h                              |    8 
 src/tm-threads.c                            |   65 +
 src/unix-manager.c                          |   83 +-
 src/unix-manager.h                          |    2 
 src/util-debug.c                            |   68 -
 src/util-decode-mime.c                      |    6 
 src/util-error.c                            |    2 
 src/util-error.h                            |    2 
 src/util-file.c                             |   52 +
 src/util-file.h                             |    6 
 src/util-logopenfile.c                      |   13 
 src/util-lua-common.c                       |   43 +
 src/util-lua-dns.c                          |   10 
 src/util-magic.c                            |    8 
 src/util-magic.h                            |    4 
 src/util-mpm-ac-bs.c                        |    4 
 src/util-mpm-ac.c                           |   44 -
 src/util-mpm-hs.c                           |    5 
 src/util-mpm.c                              |   36 
 src/util-mpm.h                              |   13 
 src/util-privs.c                            |    1 
 src/util-profiling-keywords.c               |   10 
 src/util-profiling-rulegroups.c             |   10 
 src/util-profiling-rules.c                  |   10 
 src/util-profiling.c                        |   27 
 src/util-spm.c                              |   26 
 src/util-var.c                              |    2 
 src/util-var.h                              |    2 
 suricata.yaml.in                            |   11 
 133 files changed, 2717 insertions(+), 1582 deletions(-)

unblock suricata/3.2.1-1
diff -Nru suricata-3.2/ChangeLog suricata-3.2.1/ChangeLog
--- suricata-3.2/ChangeLog	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/ChangeLog	2017-02-15 08:54:12.000000000 +0100
@@ -1,3 +1,36 @@
+3.2.1 -- 2017-02-15
+
+Feature #1951: Allow building without libmagic/file
+Feature #1972: SURICATA ICMPv6 unknown type 143 for MLDv2 report
+Feature #2010: Suricata should confirm SSSE3 presence at runtime when built with Hyperscan support
+Bug #467: compilation with unittests & debug validation
+Bug #1780: VLAN tags not forwarded in afpacket inline mode
+Bug #1827: Mpm AC fails to alloc memory
+Bug #1843: Mpm Ac: int overflow during init
+Bug #1887: pcap-log sets snaplen to -1
+Bug #1946: can't get response info in some situation
+Bug #1973: suricata fails to start because of unix socket
+Bug #1975: hostbits/xbits memory leak
+Bug #1982: tls: invalid record event triggers on valid traffic
+Bug #1984: http: protocol detection issue if both sides are malformed
+Bug #1985: pcap-log: minor memory leaks
+Bug #1987: log-pcap: pcap files created with invalid snaplen
+Bug #1988: tls_cert_subject bug
+Bug #1989: SMTP protocol detection is case sensitive
+Bug #1991: Suricata cannot parse ports: "![1234, 1235]"
+Bug #1997: tls-store: bug that cause Suricata to crash
+Bug #2001: Handling of unsolicited DNS responses.
+Bug #2003: BUG_ON body sometimes contains side-effectual code
+Bug #2004: Invalid file hash computation when force-hash is used
+Bug #2005: Incoherent sizes between request, capture and http length
+Bug #2007: smb: protocol detection just checks toserver
+Bug #2008: Suricata 3.2, pcap-log no longer works due to timestamp_pattern PCRE
+Bug #2009: Suricata is unable to get offloading settings when run under non-root
+Bug #2012: dns.log does not log unanswered queries
+Bug #2017: EVE Log Missing Fields
+Bug #2019: IPv4 defrag evasion issue
+Bug #2022: dns: out of bound memory read
+
 3.2 -- 2016-12-01
 
 Bug #1117: PCAP file count does not persist
diff -Nru suricata-3.2/config.h.in suricata-3.2.1/config.h.in
--- suricata-3.2/config.h.in	2016-11-29 18:17:03.000000000 +0100
+++ suricata-3.2.1/config.h.in	2017-02-15 08:54:30.000000000 +0100
@@ -90,6 +90,9 @@
 /* Define to 1 if you have the `gettimeofday' function. */
 #undef HAVE_GETTIMEOFDAY
 
+/* Define to 1 if you have the `hs_valid_platform' function. */
+#undef HAVE_HS_VALID_PLATFORM
+
 /* Assuming htp_config_set_response_decompression_layer_limit function in
    bundled libhtp */
 #undef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
@@ -222,6 +225,9 @@
 /* libluajit available */
 #undef HAVE_LUAJIT
 
+/* (Libmagic for file handling) */
+#undef HAVE_MAGIC
+
 /* Define to 1 if your system has a GNU libc compatible `malloc' function, and
    to 0 otherwise. */
 #undef HAVE_MALLOC
diff -Nru suricata-3.2/configure suricata-3.2.1/configure
--- suricata-3.2/configure	2016-11-29 18:17:03.000000000 +0100
+++ suricata-3.2.1/configure	2017-02-15 08:54:30.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for suricata 3.2.
+# Generated by GNU Autoconf 2.69 for suricata 3.2.1.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -643,8 +643,8 @@
 # Identity of this package.
 PACKAGE_NAME='suricata'
 PACKAGE_TARNAME='suricata'
-PACKAGE_VERSION='3.2'
-PACKAGE_STRING='suricata 3.2'
+PACKAGE_VERSION='3.2.1'
+PACKAGE_STRING='suricata 3.2.1'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -977,6 +977,7 @@
 with_libnspr_libraries
 with_libnss_includes
 with_libnss_libraries
+enable_libmagic
 with_libmagic_includes
 with_libmagic_libraries
 enable_napatech
@@ -1580,7 +1581,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures suricata 3.2 to adapt to many kinds of systems.
+\`configure' configures suricata 3.2.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1651,7 +1652,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of suricata 3.2:";;
+     short | recursive ) echo "Configuration of suricata 3.2.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1701,6 +1702,7 @@
                           htp
   --enable-cuda           Enable experimental CUDA pattern matching
   --enable-dag            Enable DAG capture
+  --enable-libmagic       Enable libmagic support [default=yes]
   --enable-napatech       Enabled Napatech Devices
   --enable-lua            Enable Lua support
   --enable-luajit         Enable Luajit support
@@ -1890,7 +1892,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-suricata configure 3.2
+suricata configure 3.2.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2355,7 +2357,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by suricata $as_me 3.2, which was
+It was created by suricata $as_me 3.2.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3223,7 +3225,7 @@
 
 # Define the identity of the package.
  PACKAGE='suricata'
- VERSION='3.2'
+ VERSION='3.2.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -15474,9 +15476,13 @@
 
     if test "x$enable_debug_validation" = "xyes"; then :
 
+        if test "$enable_unittests" = "yes"; then
+            as_fn_error $? "debug_validation can't be enabled with enabled unittests!" "$LINENO" 5
+        else
 
 $as_echo "#define DEBUG_VALIDATION 1" >>confdefs.h
 
+        fi
 
 fi
 
@@ -16197,6 +16203,17 @@
   HYPERSCAN="no"
 fi
 
+        for ac_func in hs_valid_platform
+do :
+  ac_fn_c_check_func "$LINENO" "hs_valid_platform" "ac_cv_func_hs_valid_platform"
+if test "x$ac_cv_func_hs_valid_platform" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_HS_VALID_PLATFORM 1
+_ACEOF
+
+fi
+done
+
         enable_hyperscan="yes"
         if test "$HYPERSCAN" = "no"; then
             echo
@@ -19842,6 +19859,15 @@
     fi
 
   # libmagic
+    enable_magic="no"
+    # Check whether --enable-libmagic was given.
+if test "${enable_libmagic+set}" = set; then :
+  enableval=$enable_libmagic;
+else
+  enable_magic=yes
+fi
+
+    if test "$enable_magic" = "yes"; then
 
 # Check whether --with-libmagic_includes was given.
 if test "${with_libmagic_includes+set}" = set; then :
@@ -19859,25 +19885,21 @@
 fi
 
 
-    if test "$with_libmagic_includes" != "no"; then
-        CPPFLAGS="${CPPFLAGS} -I${with_libmagic_includes}"
-    fi
+        if test "$with_libmagic_includes" != "no"; then
+            CPPFLAGS="${CPPFLAGS} -I${with_libmagic_includes}"
+        fi
 
-    ac_fn_c_check_header_mongrel "$LINENO" "magic.h" "ac_cv_header_magic_h" "$ac_includes_default"
+        ac_fn_c_check_header_mongrel "$LINENO" "magic.h" "ac_cv_header_magic_h" "$ac_includes_default"
 if test "x$ac_cv_header_magic_h" = xyes; then :
 
 else
-  as_fn_error $? "magic.h not found ..." "$LINENO" 5
+  MAGIC="no"
 fi
 
 
-
-    if test "$with_libmagic_libraries" != "no"; then
-        LDFLAGS="${LDFLAGS}  -L${with_libmagic_libraries}"
-    fi
-
-    MAGIC=""
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for magic_open in -lmagic" >&5
+        if test "$MAGIC" != "no"; then
+            MAGIC=""
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for magic_open in -lmagic" >&5
 $as_echo_n "checking for magic_open in -lmagic... " >&6; }
 if ${ac_cv_lib_magic_magic_open+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -19924,16 +19946,25 @@
   MAGIC="no"
 fi
 
+        fi
 
-    if test "$MAGIC" = "no"; then
-        echo
-        echo "   ERROR!  magic library not found, go get it"
-        echo "   from http://www.darwinsys.com/file/ or your distribution:"
-        echo
-        echo "   Ubuntu: apt-get install libmagic-dev"
-        echo "   Fedora: yum install file-devel"
-        echo
-        exit 1
+        if test "x$MAGIC" != "xno"; then
+            if test "$with_libmagic_libraries" != "no"; then
+                LDFLAGS="${LDFLAGS}  -L${with_libmagic_libraries}"
+            fi
+
+$as_echo "#define HAVE_MAGIC 1" >>confdefs.h
+
+        else
+            echo
+            echo "   WARNING!  magic library not found, go get it"
+            echo "   from http://www.darwinsys.com/file/ or your distribution:"
+            echo
+            echo "   Ubuntu: apt-get install libmagic-dev"
+            echo "   Fedora: yum install file-devel"
+            echo
+            enable_magic="no"
+        fi
     fi
 
   # Napatech - Using the 3GD API
@@ -23963,7 +23994,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by suricata $as_me 3.2, which was
+This file was extended by suricata $as_me 3.2.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -24029,7 +24060,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-suricata config.status 3.2
+suricata config.status 3.2.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -25888,6 +25919,7 @@
   Unix socket enabled:                     ${enable_unixsocket}
   Detection enabled:                       ${enable_detection}
 
+  Libmagic support:                        ${enable_magic}
   libnss support:                          ${enable_nss}
   libnspr support:                         ${enable_nspr}
   libjansson support:                      ${enable_jansson}
diff -Nru suricata-3.2/configure.ac suricata-3.2.1/configure.ac
--- suricata-3.2/configure.ac	2016-11-29 18:16:48.000000000 +0100
+++ suricata-3.2.1/configure.ac	2017-02-15 08:54:17.000000000 +0100
@@ -1,4 +1,4 @@
-    AC_INIT(suricata, 3.2)
+    AC_INIT(suricata, 3.2.1)
     m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])AM_SILENT_RULES([yes])
     m4_ifndef([AS_VERSION_COMPARE], [AC_DEFUN([AS_VERSION_COMPARE],[])])
     AC_CONFIG_HEADERS([config.h])
@@ -396,7 +396,11 @@
     AC_ARG_ENABLE(debug-validation,
            AS_HELP_STRING([--enable-debug-validation], [Enable (debug) validation code output]),,[enable_debug_validation=no])
     AS_IF([test "x$enable_debug_validation" = "xyes"], [
-        AC_DEFINE([DEBUG_VALIDATION],[1],[Enable (debug) validation code output])
+        if test "$enable_unittests" = "yes"; then
+            AC_MSG_ERROR([debug_validation can't be enabled with enabled unittests!])
+        else
+            AC_DEFINE([DEBUG_VALIDATION],[1],[Enable (debug) validation code output])
+        fi
     ])
 
   # profiling support
@@ -619,6 +623,7 @@
         fi
 
         AC_CHECK_LIB(hs,hs_compile,,HYPERSCAN="no")
+        AC_CHECK_FUNCS(hs_valid_platform)
         enable_hyperscan="yes"
         if test "$HYPERSCAN" = "no"; then
             echo
@@ -1555,35 +1560,43 @@
     fi
 
   # libmagic
-    AC_ARG_WITH(libmagic_includes,
-            [  --with-libmagic-includes=DIR  libmagic include directory],
-            [with_libmagic_includes="$withval"],[with_libmagic_includes=no])
-    AC_ARG_WITH(libmagic_libraries,
-            [  --with-libmagic-libraries=DIR    libmagic library directory],
-            [with_libmagic_libraries="$withval"],[with_libmagic_libraries="no"])
-
-    if test "$with_libmagic_includes" != "no"; then
-        CPPFLAGS="${CPPFLAGS} -I${with_libmagic_includes}"
-    fi
-
-    AC_CHECK_HEADER(magic.h,,[AC_ERROR(magic.h not found ...)])
-
-    if test "$with_libmagic_libraries" != "no"; then
-        LDFLAGS="${LDFLAGS}  -L${with_libmagic_libraries}"
-    fi
-
-    MAGIC=""
-    AC_CHECK_LIB(magic, magic_open,, MAGIC="no")
-
-    if test "$MAGIC" = "no"; then
-        echo
-        echo "   ERROR!  magic library not found, go get it"
-        echo "   from http://www.darwinsys.com/file/ or your distribution:"
-        echo
-        echo "   Ubuntu: apt-get install libmagic-dev"
-        echo "   Fedora: yum install file-devel"
-        echo
-        exit 1
+    enable_magic="no"
+    AC_ARG_ENABLE(libmagic,
+           AS_HELP_STRING([--enable-libmagic], [Enable libmagic support [default=yes]]),
+                        ,[enable_magic=yes])
+    if test "$enable_magic" = "yes"; then
+        AC_ARG_WITH(libmagic_includes,
+                [  --with-libmagic-includes=DIR  libmagic include directory],
+                [with_libmagic_includes="$withval"],[with_libmagic_includes=no])
+        AC_ARG_WITH(libmagic_libraries,
+                [  --with-libmagic-libraries=DIR    libmagic library directory],
+                [with_libmagic_libraries="$withval"],[with_libmagic_libraries="no"])
+
+        if test "$with_libmagic_includes" != "no"; then
+            CPPFLAGS="${CPPFLAGS} -I${with_libmagic_includes}"
+        fi
+
+        AC_CHECK_HEADER(magic.h,,MAGIC="no")
+        if test "$MAGIC" != "no"; then
+            MAGIC=""
+            AC_CHECK_LIB(magic, magic_open,, MAGIC="no")
+        fi
+
+        if test "x$MAGIC" != "xno"; then
+            if test "$with_libmagic_libraries" != "no"; then
+                LDFLAGS="${LDFLAGS}  -L${with_libmagic_libraries}"
+            fi
+            AC_DEFINE([HAVE_MAGIC],[1],(Libmagic for file handling))
+        else
+            echo
+            echo "   WARNING!  magic library not found, go get it"
+            echo "   from http://www.darwinsys.com/file/ or your distribution:"
+            echo
+            echo "   Ubuntu: apt-get install libmagic-dev"
+            echo "   Fedora: yum install file-devel"
+            echo
+            enable_magic="no"
+        fi
     fi
 
   # Napatech - Using the 3GD API
@@ -1995,6 +2008,7 @@
   Unix socket enabled:                     ${enable_unixsocket}
   Detection enabled:                       ${enable_detection}
 
+  Libmagic support:                        ${enable_magic}
   libnss support:                          ${enable_nss}
   libnspr support:                         ${enable_nspr}
   libjansson support:                      ${enable_jansson}
diff -Nru suricata-3.2/debian/changelog suricata-3.2.1/debian/changelog
--- suricata-3.2/debian/changelog	2017-01-10 09:27:59.000000000 +0100
+++ suricata-3.2.1/debian/changelog	2017-02-20 13:29:37.000000000 +0100
@@ -1,3 +1,18 @@
+suricata (3.2.1-1~exp2) experimental; urgency=medium
+
+  [ Sascha Steinbiss ]
+  * [ced48e4] suricata: migrate from old split binary scheme (Closes: #855573)
+
+ -- Arturo Borrero Gonzalez <arturo@debian.org>  Mon, 20 Feb 2017 13:29:37 +0100
+
+suricata (3.2.1-1~exp1) experimental; urgency=medium
+
+  * [67004c8] New upstream version 3.2.1
+  * [05b1756] d/control: bump dependency on libhyperscan
+  * [4483d1c] suricata: drop suricata-hyperscan binary package (Closes: #851647)
+
+ -- Arturo Borrero Gonzalez <arturo@debian.org>  Wed, 15 Feb 2017 20:54:17 +0100
+
 suricata (3.2-2) unstable; urgency=medium
 
   * Rebuild for unstable.
diff -Nru suricata-3.2/debian/control suricata-3.2.1/debian/control
--- suricata-3.2/debian/control	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/control	2017-02-20 13:29:37.000000000 +0100
@@ -6,14 +6,13 @@
 Build-Depends: autotools-dev,
                debhelper (>= 9),
                dh-autoreconf,
-               dh-exec,
                dh-systemd,
                libcap-ng-dev,
                libgeoip-dev,
                libhiredis-dev,
                libjansson-dev,
                libluajit-5.1-dev [i386 amd64 powerpc mips armel armhf],
-               libhyperscan-dev [i386 amd64 x32],
+               libhyperscan-dev (>= 4.4.0) [i386 amd64 x32],
                libmagic-dev,
                libnet1-dev | libnet-dev,
                libnetfilter-log-dev,
@@ -37,8 +36,8 @@
 Architecture: linux-any
 Pre-Depends: dpkg (>= 1.15.7.2)
 Depends: ${misc:Depends}, ${python:Depends}, ${shlibs:Depends}, libhtp-0.5.23-1 (= ${binary:Version}), lsb-base (>= 3.0-6)
-Conflicts: libhtp1 (<< 0.5.16)
-Replaces: libhtp1 (<< 0.5.16)
+Conflicts: libhtp1 (<< 0.5.16), suricata-hyperscan (<< 3.2)
+Replaces: libhtp1 (<< 0.5.16), suricata-hyperscan (<< 3.2)
 Recommends: suricata-oinkmaster (=${binary:Version}), python, snort-rules-default
 Suggests: libtcmalloc-minimal4
 Description: Next Generation Intrusion Detection and Prevention Tool
@@ -56,17 +55,6 @@
  .
  This version has inline (NFQUEUE) support enabled.
 
-Package: suricata-hyperscan
-Architecture: linux-amd64 linux-i386 linux-x32
-Pre-Depends: dpkg (>= 1.15.7.2)
-Depends: ${misc:Depends}, ${shlibs:Depends}, suricata (=${binary:Version}), libhyperscan4
-Description: Next Generation Intrusion Detection and Prevention Tool, Hyperscan support
- Suricata is a network Intrusion Detection System (IDS). It is based on
- rules (and is fully compatible with snort rules) to detect a variety of
- attacks / probes by searching packet content.
- .
- This package adds Hyperscan support to an installed Suricata version.
-
 Package: suricata-oinkmaster
 Architecture: all
 Depends: oinkmaster, suricata (>= ${source:Version}), ${misc:Depends}
diff -Nru suricata-3.2/debian/patches/optional-hyperscan.patch suricata-3.2.1/debian/patches/optional-hyperscan.patch
--- suricata-3.2/debian/patches/optional-hyperscan.patch	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/patches/optional-hyperscan.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +0,0 @@
-Description: enable optional hyperscan support
- This patch allows one to disable and enable Hyperscan support independently of
- libhyperscan presence.
-Author: Sascha Steinbiss <satta@debian.org>
---- a/configure.ac
-+++ b/configure.ac
-@@ -595,8 +595,12 @@
-   # libhs
-     enable_hyperscan="no"
- 
--    # Try pkg-config first:
--    PKG_CHECK_MODULES([libhs], libhs,, [with_pkgconfig_libhs=no])
-+    AC_ARG_ENABLE([libhs], AS_HELP_STRING([--enable-libhs], [try building with Hyperscan support]))
-+    if test "x$enable_libhs" = "xyes"; then
-+        # Try pkg-config first:
-+        PKG_CHECK_MODULES([libhs], libhs,, [with_pkgconfig_libhs=no])
-+    fi
-+
-     if test "$with_pkgconfig_libhs" != "no"; then
-         CPPFLAGS="${CPPFLAGS} ${libhs_CFLAGS}"
-         LIBS="${LIBS} ${libhs_LIBS}"
diff -Nru suricata-3.2/debian/patches/series suricata-3.2.1/debian/patches/series
--- suricata-3.2/debian/patches/series	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/patches/series	2017-02-20 13:29:37.000000000 +0100
@@ -1,3 +1,2 @@
 reproducible.patch
 debian-default-cfg.patch
-optional-hyperscan.patch
diff -Nru suricata-3.2/debian/rules suricata-3.2.1/debian/rules
--- suricata-3.2/debian/rules	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/rules	2017-02-20 13:29:37.000000000 +0100
@@ -10,11 +10,9 @@
 # Uncomment this to turn on verbose mode.
 export DH_VERBOSE=1
 
+SURICATA_DESTDIR = $(CURDIR)/debian/suricata
 export DEB_BUILD_MAINT_OPTIONS=hardening=+pie,+bindnow
 
-SURICATA_DESTDIR = $(CURDIR)/debian/build-tmp/suricata-no-hs
-SURICATA_HSDESTDIR = $(CURDIR)/debian/build-tmp/suricata-hs
-
 ARCH ?= $(shell dpkg --print-architecture)
 DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
 
@@ -25,9 +23,8 @@
 	ENABLE_LUAJIT="--enable-luajit"
 endif
 
-TARGETS = suricata-no-hs
 ifneq (,$(findstring $(ARCH),$(HYPERSCAN_ARCHS)))
-	TARGETS += suricata-with-hs
+	ENABLE_HYPERSCAN="--enable-libhs"
 endif
 
 CONFIGURE_ARGS = --enable-af-packet --enable-nfqueue --enable-prelude --enable-nflog \
@@ -36,41 +33,22 @@
 	--with-libnspr-includes=/usr/include/nspr --with-libnspr-libraries=/usr/lib/$(DEB_HOST_MULTIARCH) \
 	--disable-coccinelle \
 	--enable-geoip --enable-hiredis \
-	$(ENABLE_LUAJIT)
+	$(ENABLE_LUAJIT) \
+	$(ENABLE_HYPERSCAN)
 
-suricata-no-hs:
+override_dh_auto_configure:
 	dh_auto_configure -- $(CONFIGURE_ARGS)
-	dh_auto_build --parallel
-	make install DESTDIR=$(SURICATA_DESTDIR)
+
+override_dh_auto_install:
+	dh_auto_install
 	rm -rf $(SURICATA_DESTDIR)/usr/lib/python*;\
 	(cd scripts/suricatasc &&\
 		python -B setup.py install --install-layout=deb --prefix $(SURICATA_DESTDIR)/usr)
 	# clean upstream install documentation
 	rm -rf $(SURICATA_DESTDIR)/usr/share/doc/suricata/*
-	make clean
-
-suricata-with-hs:
-	dh_auto_configure -- $(CONFIGURE_ARGS) --enable-libhs
-	dh_auto_build --parallel
-	make install DESTDIR=$(SURICATA_HSDESTDIR)
-	rm -rf $(SURICATA_HSDESTDIR)/usr/lib/python*;\
-	(cd scripts/suricatasc &&\
-		python -B setup.py install --install-layout=deb --prefix $(SURICATA_HSDESTDIR)/usr)
-	# clean upstream install documentation
-	rm -rf $(SURICATA_HSDESTDIR)/usr/share/doc/suricata/*
-	make clean
-
-override_dh_auto_clean:
-	rm -rf $(CURDIR)/debian/build-tmp
-	dh_auto_clean
-
-override_dh_auto_configure:
-	# done in individual targets
-
-override_dh_auto_build: $(TARGETS)
 
 override_dh_strip:
 	dh_strip --dbg-package=suricata-dbg
 
 %:
-	dh  $@ --with autotools-dev,autoreconf,python2
+	dh $@ --parallel --with autotools-dev,autoreconf,python2
diff -Nru suricata-3.2/debian/suricata-hyperscan.install suricata-3.2.1/debian/suricata-hyperscan.install
--- suricata-3.2/debian/suricata-hyperscan.install	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata-hyperscan.install	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-#!/usr/bin/dh-exec --with-scripts=install-rename
-
-debian/build-tmp/suricata-hs/usr/bin/suricata => /usr/bin/suricata.hyperscan
diff -Nru suricata-3.2/debian/suricata-hyperscan.postinst suricata-3.2.1/debian/suricata-hyperscan.postinst
--- suricata-3.2/debian/suricata-hyperscan.postinst	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata-hyperscan.postinst	1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-#!/bin/sh
-set -e
-
-update-alternatives --install /usr/bin/suricata suricata /usr/bin/suricata.hyperscan 110
-
-#DEBHELPER#
-
-exit 0
diff -Nru suricata-3.2/debian/suricata-hyperscan.prerm suricata-3.2.1/debian/suricata-hyperscan.prerm
--- suricata-3.2/debian/suricata-hyperscan.prerm	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata-hyperscan.prerm	1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +0,0 @@
-#!/bin/sh
-set -e
-
-case "$1" in
-  # only remove in remove/deconfigure so we don't disrupt users' preferences
-  remove|deconfigure)
-    update-alternatives --remove suricata /usr/bin/suricata.hyperscan
-    ;;
-
-  upgrade|failed-upgrade)
-    ;;
-
-  *)
-    echo "prerm called with unknown argument \`$1'" >&2
-    exit 0
-    ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff -Nru suricata-3.2/debian/suricata.init suricata-3.2.1/debian/suricata.init
--- suricata-3.2/debian/suricata.init	2016-12-01 16:17:43.000000000 +0100
+++ suricata-3.2.1/debian/suricata.init	2017-02-20 13:29:37.000000000 +0100
@@ -12,13 +12,14 @@
 #                    match against a set of known attacks.
 ### END INIT INFO
 
+# Source function library.
 . /lib/lsb/init-functions
 
-# Source function library.
 if test -f /etc/default/suricata; then
 	. /etc/default/suricata
 else
-	echo "/etc/default/suricata is missing... bailing out!"
+	echo "/etc/default/suricata is missing... bailing out!" >&2
+	exit 1
 fi
 
 # We'll add up all the options above and use them
diff -Nru suricata-3.2/debian/suricata.install suricata-3.2.1/debian/suricata.install
--- suricata-3.2/debian/suricata.install	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata.install	2017-02-20 13:29:37.000000000 +0100
@@ -1,10 +1,6 @@
-#!/usr/bin/dh-exec --with-scripts=install-rename
-
 classification.config /etc/suricata
 reference.config /etc/suricata
 rules/*.rules /etc/suricata/rules
 suricata.yaml	/etc/suricata
 threshold.config /etc/suricata
-debian/build-tmp/suricata-no-hs/usr/bin/suricata => /usr/bin/suricata.generic
-debian/build-tmp/suricata-no-hs/usr/bin/suricatasc usr/bin
-debian/build-tmp/suricata-no-hs/usr/lib/python* usr/lib
+usr/bin/*
diff -Nru suricata-3.2/debian/suricata.postinst suricata-3.2.1/debian/suricata.postinst
--- suricata-3.2/debian/suricata.postinst	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata.postinst	1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-#!/bin/sh
-set -e
-
-update-alternatives --install /usr/bin/suricata suricata /usr/bin/suricata.generic 100
-
-#DEBHELPER#
-
-exit 0
diff -Nru suricata-3.2/debian/suricata.preinst suricata-3.2.1/debian/suricata.preinst
--- suricata-3.2/debian/suricata.preinst	1970-01-01 01:00:00.000000000 +0100
+++ suricata-3.2.1/debian/suricata.preinst	2017-02-20 13:29:37.000000000 +0100
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# we do not need alternatives anymore
+if update-alternatives --quiet --query suricata 2> /dev/null; then
+    echo "Removing legacy alternatives for Hyperscan/non-Hyperscan versions"
+    update-alternatives --remove-all suricata
+fi
+
+#DEBHELPER#
+
+exit 0
diff -Nru suricata-3.2/debian/suricata.prerm suricata-3.2.1/debian/suricata.prerm
--- suricata-3.2/debian/suricata.prerm	2017-01-10 09:23:22.000000000 +0100
+++ suricata-3.2.1/debian/suricata.prerm	1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +0,0 @@
-#!/bin/sh
-set -e
-
-case "$1" in
-  # only remove in remove/deconfigure so we don't disrupt users' preferences
-  remove|deconfigure)
-    update-alternatives --remove suricata /usr/bin/suricata.generic
-    ;;
-
-  upgrade|failed-upgrade)
-    ;;
-
-  *)
-    echo "prerm called with unknown argument \`$1'" >&2
-    exit 0
-    ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff -Nru suricata-3.2/doc/userguide/capture-hardware/index.rst suricata-3.2.1/doc/userguide/capture-hardware/index.rst
--- suricata-3.2/doc/userguide/capture-hardware/index.rst	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/doc/userguide/capture-hardware/index.rst	2017-02-15 08:54:12.000000000 +0100
@@ -4,4 +4,5 @@
 .. toctree::
 
    endace-dag
+   napatech
    myricom
diff -Nru suricata-3.2/doc/userguide/capture-hardware/napatech.rst suricata-3.2.1/doc/userguide/capture-hardware/napatech.rst
--- suricata-3.2/doc/userguide/capture-hardware/napatech.rst	1970-01-01 01:00:00.000000000 +0100
+++ suricata-3.2.1/doc/userguide/capture-hardware/napatech.rst	2017-02-15 08:54:12.000000000 +0100
@@ -0,0 +1,215 @@
+
+
+Napatech Suricata Installation Guide
+=============================================================
+
+Contents
+--------
+
+	* Introduction
+
+	* Package Installation
+
+	* Basic Configuration
+
+	* Advanced Multithreaded Configuration
+
+Introduction
+------------
+
+Napatech packet capture accelerator cards can greatly improve the performance of your Suricata deployment using these
+hardware based features:
+
+	* On board burst buffering (up to 12GB)
+
+	* Zero-copy kernel bypass DMA
+
+	* Non-blocking PCIe performance
+
+	* Port merging
+
+	* Load distribution to up 128 host buffers
+
+	* Precise timestamping
+
+	* Accurate time synchronization
+
+The Napatech Software Suite (driver package) comes in two varieties, NAC and OEM.
+The NAC package distributes deb and rpm packages to ease the installation.
+The OEM package uses a proprietary shell script to handle the installation process.
+In either case, gcc, make and the kernel header files are required to compile the kernel module and
+install the software.
+
+
+Package Installation
+--------------------
+
+*Note that make, gcc, and the kernel headers are required for installation*
+
+*Root privileges are also required*
+
+Napatech NAC Package
+^^^^^^^^^^^^^^^^^^^^
+
+Red Hat Based Distros::
+
+    $ yum install kernel-devel-$(uname -r) gcc make ncurses-libs
+    $ yum install nac-pcap-<release>.x86_64.rpm
+
+Some distributions will require you to use the --nogpgcheck option with yum for the NAC Software Suite package file::
+
+    $ yum --nogpgcheck install nac-pcap-<release>.x86_64.rpm
+
+Debian Based Distros::
+
+	$ apt-get install linux-headers-$(uname .r) gcc make libncurses5
+	$ dpkg .i nac-pcap_<release>_amd64.deb
+
+To complete installation for all distros stop ntservice::
+
+	$ /opt/napatech3/bin/ntstop.sh -m
+
+Remove these existing setup files::
+
+	$ cd /opt/napatech3/config
+	$ rm ntservice.ini setup.ini
+
+Restart ntservice (a new ntservice.ini configuration file will be generated automatically)::
+
+	$ /opt/napatech3/bin/ntstart.sh -m
+
+
+Napatech OEM Package
+^^^^^^^^^^^^^^^^^^^^
+
+*Note that you will be prompted to install the Napatech libpcap library. Answer "yes" if you would like to
+use the Napatech card to capture packets in WIreshark, tcpdump, or another pcap based application.
+Libpcap is not needed for Suricata as native Napatech API support is included*
+
+Red Hat Based Distros::
+
+    $ yum install kernel-devel-$(uname -r) gcc make
+	$ ./package_install_3gd.sh
+
+Debian Based Distros::
+
+    $ apt-get install linux-headers-$(uname .r) gcc make
+	$ ./package_install_3gd.sh
+
+To complete installation for all distros ntservice::
+
+	$ /opt/napatech3/bin/ntstart.sh -m
+
+Suricata Installation
+---------------------
+
+After downloading and extracting the Suricata tarball, you need to run configure to enable Napatech support and
+prepare for compilation::
+
+	$ ./configure --enable_napatech --with-napatech-includes=/opt/napatech3/include --with-napatech-libraries=/opt/napatech3/lib
+	$ make
+	$ make install-full
+
+Now edit the suricata.yaml file to configure the maximum number of streams to use. If you plan on using the load distribution
+(RSS - like) feature in the Napatech accelerator, then the list should contain the same number of streams as host buffers defined in
+ntservice.ini::
+
+	Napatech:
+		# The Host Buffer Allowance for all streams
+		# (-1 = OFF, 1 - 100 = percentage of the host buffer that can be held back)
+		hba: -1
+
+		# use_all_streams set to "yes" will query the Napatech service for all configured
+		# streams and listen on all of them. When set to "no" the streams config array
+		# will be used.
+		use-all-streams: yes
+
+		# The streams to listen on
+		streams: [0, 1, 2, 3, 4, 5, 6, 7]
+
+
+Basic Configuration
+-------------------
+
+For the basic installation we will setup the Napatech capture accelerator to merge all physical
+ports into single stream that Suricata can read from. for this configuration, Suricata will
+handle the packet distribution to multiple threads.
+
+Here are the lines that need changing in /opt/napatech3/bin/ntservice.ini for best single buffer performance::
+
+	TimeSyncReferencePriority = OSTime	# Timestamp clock synchronized to the OS
+	HostBuffersRx = [1,16,0]		# [number of host buffers, Size(MB), NUMA node]
+
+Stop and restart ntservice after making changes to ntservice::
+
+	$ /opt/napatech3/bin/ntstop.sh -m
+	$ /opt/napatech3/bin/ntstart.sh -m
+
+Now we need to execute a few NTPL (Napatech Programming Language) commands to complete the setup. Create
+a file will the following commands::
+
+	Delete=All				# Delete any existing filters
+	Setup[numaNode=0] = streamid==0		# Set stream ID 0 to NUMA 0
+	Assign[priority=0; streamid=0]= all	# Assign all phisical ports to stream ID 0
+
+Next execute those command using the ntpl tool::
+
+	$ /opt/napatech3/bin/ntpl -f <my_ntpl_file>
+
+Now you are ready to start suricata::
+
+	$ suricata -c /usr/local/etc/suricata/suricata.yaml --napatech --runmode workers
+
+Advanced Multithreaded Configuration
+------------------------------------
+
+Now let's do a more advanced configuration where we will use the load distribution (RSS - like) capability in the
+accelerator. We will create 8 streams and setup the accelerator to distribute the load based on a 5 tuple hash.
+Increasing buffer size will minimize packet loss only if your CPU cores are fully saturated. Setting the minimum
+buffer size (16MB) will gave the best performance (minimize L3 cache hits) if your CPU cores are keeping up.
+
+*Note that it is extremely important that the NUMA node the host buffers are define in is the same physical CPU
+socket that the Napatech accelerator is plugged into*
+
+First let's modify the ntservice.ini file to increase the number and size of the host buffers::
+
+	HostBuffersRx = [8,256,0]		# [number of host buffers, Size (MB), NUMA node]
+
+Stop and restart ntservice after making changes to ntservice::
+
+	$ /opt/napatech3/bin/ntstop.sh -m
+	$ /opt/napatech3/bin/ntstart.sh -m
+
+Now let's assign the streams to host buffers and configure the load distribution. The load distribution will be
+setup to support both tunneled and non-tunneled traffic. Create a file that contains the ntpl commands below::
+
+	Delete=All				# Delete any existing filters
+	Setup[numaNode=0] = streamid==0
+	Setup[numaNode=0] = streamid==1
+	Setup[numaNode=0] = streamid==2
+	Setup[numaNode=0] = streamid==3
+	Setup[numaNode=0] = streamid==4
+	Setup[numaNode=0] = streamid==5
+	Setup[numaNode=0] = streamid==6
+	Setup[numaNode=0] = streamid==7
+	HashMode[priority=0; InnerLayer4Type=UDP, TCP, SCTP] = HashInner5TupleSorted
+	HashMode[priority=1; InnerLayer3Type=IPV4] = HashInner2TupleSorted
+	HashMode[priority=2; Layer4Type=UDP, TCP, SCTP] = Hash5TupleSorted
+	HashMode[priority=3; Layer3Type=IPV4] = Hash2TupleSorted
+	HashMode[priority=4]=HashRoundRobin
+	Assign[priority=0; streamid=(0..7)]= all
+
+Next execute those command using the ntpl tool::
+
+	$ /opt/napatech3/bin/ntpl -f <my_ntpl_file>
+
+Now you are ready to start Suricata::
+
+	$ suricata -c /usr/local/etc/suricata/suricata.yaml --napatech --runmode workers
+
+
+Support
+-------
+
+Contact a support engineer at: ntsupport@napatech.com
+
diff -Nru suricata-3.2/doc/userguide/output/lua-output.rst suricata-3.2.1/doc/userguide/output/lua-output.rst
--- suricata-3.2/doc/userguide/output/lua-output.rst	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/doc/userguide/output/lua-output.rst	2017-02-15 08:54:12.000000000 +0100
@@ -178,6 +178,22 @@
       end
   end
 
+SCFlowHasAlerts
+~~~~~~~~~~~~~~~
+
+Returns true if flow has alerts.
+
+Example:
+
+::
+
+  function log(args)
+      has_alerts = SCFlowHasAlerts()
+      if has_alerts then
+          -- do something
+      end
+  end
+
 SCFlowStats
 ~~~~~~~~~~~
 
diff -Nru suricata-3.2/doc/userguide/rules/dnp3-keywords.rst suricata-3.2.1/doc/userguide/rules/dnp3-keywords.rst
--- suricata-3.2/doc/userguide/rules/dnp3-keywords.rst	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/doc/userguide/rules/dnp3-keywords.rst	2017-02-15 08:54:12.000000000 +0100
@@ -1,8 +1,6 @@
 DNP3 Keywords
 =============
 
-**NOTE: DNP3 is currently in development and is not yet available.**
-
 The DNP3 keywords can be used to match on fields in decoded DNP3
 messages. The keywords are based on Snort's DNP3 keywords and aim to
 be 100% compatible.
diff -Nru suricata-3.2/doc/userguide/rules/index.rst suricata-3.2.1/doc/userguide/rules/index.rst
--- suricata-3.2/doc/userguide/rules/index.rst	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/doc/userguide/rules/index.rst	2017-02-15 08:54:12.000000000 +0100
@@ -11,6 +11,7 @@
    http-keywords
    flow-keywords
    flowint
+   xbits
    file-keywords
    thresholding
    dns-keywords
diff -Nru suricata-3.2/doc/userguide/rules/tls-keywords.rst suricata-3.2.1/doc/userguide/rules/tls-keywords.rst
--- suricata-3.2/doc/userguide/rules/tls-keywords.rst	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/doc/userguide/rules/tls-keywords.rst	2017-02-15 08:54:12.000000000 +0100
@@ -27,6 +27,18 @@
 
 ``tls_cert_issuer`` is a 'Sticky buffer'.
 
+tls_sni
+-------
+
+Match TLS/SSL Server Name Indication field.
+
+Examples::
+
+  tls_sni; content:"oisf.net"; nocase; isdataat:!1,relative;
+  tls_sni; content:"oisf.net"; nocase; pcre:"/oisf.net$/";
+
+``tls_sni`` is a 'Sticky buffer'.
+
 tls_cert_notbefore
 ------------------
 
diff -Nru suricata-3.2/doc/userguide/rules/xbits.rst suricata-3.2.1/doc/userguide/rules/xbits.rst
--- suricata-3.2/doc/userguide/rules/xbits.rst	1970-01-01 01:00:00.000000000 +0100
+++ suricata-3.2.1/doc/userguide/rules/xbits.rst	2017-02-15 08:54:12.000000000 +0100
@@ -0,0 +1,48 @@
+Xbits
+=====
+
+Set, unset, toggle and check for bits stored per host or ip_pair.
+
+Syntax::
+
+    xbits:noalert;
+    xbits:<set|unset|isset|toggle>,<name>,track <ip_src|ip_dst|ip_pair>;
+    xbits:<set|unset|isset|toggle>,<name>,track <ip_src|ip_dst|ip_pair> \
+        [,expire <seconds>];
+    xbits:<set|unset|isset|toggle>,<name>,track <ip_src|ip_dst|ip_pair> \
+        [,expire <seconds>];
+
+YAML settings
+-------------
+
+Bits that are stored per host are stored in the Host table.
+
+Bits that are stored per IP pair are stored in the IPPair table.
+
+Threading
+---------
+
+Due to subtle timing issues between threads the order of sets and checks
+can be slightly unpredictible.
+
+Example: create a SSH blacklist
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Below is an example of rules incoming to a SSH server.
+
+The first 2 rules match on a SSH software version often used in bots.
+They drop the traffic and create an 'xbit' 'badssh' for the source ip.
+It expires in an hour::
+
+    drop ssh any any -> $MYSERVER 22 (msg:"DROP libssh incoming";   \
+      flow:to_server,established; ssh.softwareversion:"libssh";     \
+      xbits:set, badssh, track ip_src, expire 3600; sid:4000000005;)
+    drop ssh any any -> $MYSERVER 22 (msg:"DROP PUTTY incoming";    \
+      flow:to_server,established; ssh.softwareversion:"PUTTY";      \
+      xbits:set, badssh, track ip_src, expire 3600; sid:4000000007;)
+
+Then the following rule simply drops any incoming traffic to that server
+that is on that 'badssh' list::
+
+    drop ssh any any -> $MYSERVER 22 (msg:"DROP BLACKLISTED";       \
+      xbits:isset, badssh, track ip_src; sid:4000000006;)
diff -Nru suricata-3.2/doc/userguide/suricata.1 suricata-3.2.1/doc/userguide/suricata.1
--- suricata-3.2/doc/userguide/suricata.1	2016-11-29 18:17:15.000000000 +0100
+++ suricata-3.2.1/doc/userguide/suricata.1	2017-02-15 08:54:46.000000000 +0100
@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH "SURICATA" "1" "November 29, 2016" "3.2" "Suricata"
+.TH "SURICATA" "1" "February 15, 2017" "3.2.1" "Suricata"
 .SH NAME
 suricata \- Suricata
 .
Los ficheros binarios /tmp/5ANamyhz3M/suricata-3.2/doc/userguide/userguide.pdf y /tmp/OrowFu7tes/suricata-3.2.1/doc/userguide/userguide.pdf son distintos
diff -Nru suricata-3.2/rules/tls-events.rules suricata-3.2.1/rules/tls-events.rules
--- suricata-3.2/rules/tls-events.rules	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/rules/tls-events.rules	2017-02-15 08:54:12.000000000 +0100
@@ -26,5 +26,6 @@
 alert tls any any -> any any (msg:"SURICATA TLS invalid SNI type"; flow:established,to_server; app-layer-event:tls.invalid_sni_type; flowint:tls.anomaly.count,+,1; classtype:protocol-command-decode; sid:2230017; rev:1;)
 alert tls any any -> any any (msg:"SURICATA TLS invalid SNI length"; flow:established,to_server; app-layer-event:tls.invalid_sni_length; flowint:tls.anomaly.count,+,1; classtype:protocol-command-decode; sid:2230018; rev:1;)
 alert tls any any -> any any (msg:"SURICATA TLS handshake invalid length"; flow:established; app-layer-event:tls.handshake_invalid_length; flowint:tls.anomaly.count,+,1; classtype:protocol-command-decode; sid:2230019; rev:1;)
+alert tls any any -> any any (msg:"SURICATA TLS too many records in packet"; flow:established; app-layer-event:tls.too_many_records_in_packet; flowint:tls.anomaly.count,+,1; classtype:protocol-command-decode; sid:2230020; rev:1;)
 
-#next sid is 2230020
+#next sid is 2230021
diff -Nru suricata-3.2/scripts/suricatasc/Makefile.in suricata-3.2.1/scripts/suricatasc/Makefile.in
--- suricata-3.2/scripts/suricatasc/Makefile.in	2016-11-29 18:17:05.000000000 +0100
+++ suricata-3.2.1/scripts/suricatasc/Makefile.in	2017-02-15 08:54:31.000000000 +0100
@@ -423,8 +423,8 @@
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
-@HAVE_PYTHON_FALSE@uninstall-local:
 @HAVE_PYTHON_FALSE@clean-local:
+@HAVE_PYTHON_FALSE@uninstall-local:
 @HAVE_PYTHON_FALSE@install-exec-local:
 clean: clean-am
 
diff -Nru suricata-3.2/src/alert-prelude.c suricata-3.2.1/src/alert-prelude.c
--- suricata-3.2/src/alert-prelude.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/alert-prelude.c	2017-02-15 08:54:12.000000000 +0100
@@ -512,10 +512,10 @@
             AddIntData(alert, "tcp_win", TCP_GET_WINDOW(p));
             AddIntData(alert, "tcp_sum", TCP_GET_SUM(p));
             AddIntData(alert, "tcp_urp", TCP_GET_URG_POINTER(p));
-            if (p->tcpvars.ts_val != NULL) {
+            if (p->tcpvars.ts_val != 0) {
                 AddIntData(alert, "tcp_tsval", TCP_GET_TSVAL(p));
             }
-            if (p->tcpvars.ts_ecr != NULL) {
+            if (p->tcpvars.ts_ecr != 0) {
                 AddIntData(alert, "tcp_tsecr", TCP_GET_TSECR(p));
             }
             if (p->tcph != NULL) {
@@ -961,4 +961,3 @@
         AlertPreludeThreadInit, AlertPreludeThreadDeinit, NULL);
 }
 #endif /* PRELUDE */
-
diff -Nru suricata-3.2/src/app-layer-dcerpc.c suricata-3.2.1/src/app-layer-dcerpc.c
--- suricata-3.2/src/app-layer-dcerpc.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-dcerpc.c	2017-02-15 08:54:12.000000000 +0100
@@ -1553,7 +1553,9 @@
                                    (dcerpc->dcerpchdr.type == BIND) ?
                                    "BIND" : "ALTER_CONTEXT");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1579,7 +1581,9 @@
                         //parsed -= input_len;
                         SCLogDebug("Error Parsing CTX Item %u\n", parsed);
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         dcerpc->dcerpcbindbindack.numctxitemsleft = 0;
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
@@ -1606,7 +1610,9 @@
                         } else {
                             SCLogDebug("Error Parsing DCERPC");
                             parsed = 0;
+                            (void)parsed; /* for scan-build */
                             input_len = 0;
+                            (void)input_len; /* for scan-build */
                             DCERPCResetParsingState(dcerpc);
                             SCReturnInt(0);
                         }
@@ -1633,7 +1639,9 @@
                                    (dcerpc->dcerpchdr.type == BIND_ACK) ?
                                    "BIND_ACK" : "ALTER_CONTEXT_RESP");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1652,7 +1660,9 @@
                     } else if (input_len) {
                         SCLogDebug("Error parsing Secondary Address");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1679,7 +1689,9 @@
                     } else if (input_len) {
                         SCLogDebug("Error parsing DCERPC Padding");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1698,7 +1710,9 @@
                     } else if (input_len) {
                         SCLogDebug("Error parsing CTX Items");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1721,7 +1735,9 @@
                     } else if (input_len) {
                         SCLogDebug("Error parsing CTX Items");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         dcerpc->dcerpcbindbindack.numctxitemsleft = 0;
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
@@ -1759,7 +1775,9 @@
                         } else {
                             SCLogDebug("Error Parsing DCERPC");
                             parsed = 0;
+                            (void)parsed; /* for scan-build */
                             input_len = 0;
+                            (void)input_len; /* for scan-build */
                             DCERPCResetParsingState(dcerpc);
                             SCReturnInt(0);
                         }
@@ -1783,8 +1801,10 @@
                         SCLogDebug("Error parsing DCERPC %s",
                                    (dcerpc->dcerpchdr.type == REQUEST) ? "REQUEST" : "RESPONSE");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         dcerpc->padleft = 0;
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1800,7 +1820,9 @@
                     } else if (input_len) {
                         SCLogDebug("Error parsing DCERPC Stub Data");
                         parsed = 0;
+                        (void)parsed; /* for scan-build */
                         input_len = 0;
+                        (void)input_len; /* for scan-build */
                         DCERPCResetParsingState(dcerpc);
                         SCReturnInt(0);
                     }
@@ -1842,7 +1864,9 @@
                         } else {
                             SCLogDebug("Error Parsing DCERPC");
                             parsed = 0;
+                            (void)parsed; /* for scan-build */
                             input_len = 0;
+                            (void)input_len; /* for scan-build */
                             DCERPCResetParsingState(dcerpc);
                             SCReturnInt(0);
                         }
@@ -1875,7 +1899,9 @@
                 } else {
                     SCLogDebug("Error Parsing DCERPC");
                     parsed = 0;
+                    (void)parsed; /* for scan-build */
                     input_len = 0;
+                    (void)input_len; /* for scan-build */
                     DCERPCResetParsingState(dcerpc);
                     SCReturnInt(0);
                 }
diff -Nru suricata-3.2/src/app-layer-detect-proto.c suricata-3.2.1/src/app-layer-detect-proto.c
--- suricata-3.2/src/app-layer-detect-proto.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-detect-proto.c	2017-02-15 08:54:12.000000000 +0100
@@ -75,8 +75,12 @@
     uint32_t min_depth;
     /* the max length of data after which this parser won't be invoked */
     uint32_t max_depth;
-    /* the probing parser function */
-    ProbingParserFPtr ProbingParser;
+
+    /* the to_server probing parser function */
+    ProbingParserFPtr ProbingParserTs;
+
+    /* the to_client probing parser function */
+    ProbingParserFPtr ProbingParserTc;
 
     struct AppLayerProtoDetectProbingParserElement_ *next;
 } AppLayerProtoDetectProbingParserElement;
@@ -395,7 +399,11 @@
             continue;
         }
 
-        alproto = pe->ProbingParser(buf, buflen, NULL);
+        if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
+            alproto = pe->ProbingParserTs(buf, buflen, NULL);
+        } else if (pe->ProbingParserTc != NULL) {
+            alproto = pe->ProbingParserTc(buf, buflen, NULL);
+        }
         if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED)
             goto end;
         if (alproto == ALPROTO_FAILED ||
@@ -412,7 +420,11 @@
             continue;
         }
 
-        alproto = pe->ProbingParser(buf, buflen, NULL);
+        if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
+            alproto = pe->ProbingParserTs(buf, buflen, NULL);
+        } else if (pe->ProbingParserTc != NULL) {
+            alproto = pe->ProbingParserTc(buf, buflen, NULL);
+        }
         if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED)
             goto end;
         if (alproto == ALPROTO_FAILED ||
@@ -429,8 +441,6 @@
         mask = pp_port_dp->alproto_mask;
     else if (pp_port_sp)
         mask = pp_port_sp->alproto_mask;
-    else
-        mask = 0;
 
     if (alproto_masks[0] == mask) {
         FLOW_SET_PP_DONE(f, direction);
@@ -579,9 +589,7 @@
 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
                                               uint16_t port,
                                               uint16_t min_depth,
-                                              uint16_t max_depth,
-                                              uint16_t (*AppLayerProtoDetectProbingParserFunc)
-                                                       (uint8_t *input, uint32_t input_len, uint32_t *offset))
+                                              uint16_t max_depth)
 {
     AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
 
@@ -590,7 +598,6 @@
     pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
     pe->min_depth = min_depth;
     pe->max_depth = max_depth;
-    pe->ProbingParser = AppLayerProtoDetectProbingParserFunc;
     pe->next = NULL;
 
     if (max_depth != 0 && min_depth >= max_depth) {
@@ -603,11 +610,6 @@
                    "the probing parser.  Invalid alproto - %d", alproto);
         goto error;
     }
-    if (AppLayerProtoDetectProbingParserFunc == NULL) {
-        SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
-                   "register the probing parser.  Probing parser func NULL");
-        goto error;
-    }
 
     SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
  error:
@@ -627,7 +629,8 @@
     new_pe->alproto_mask = pe->alproto_mask;
     new_pe->min_depth = pe->min_depth;
     new_pe->max_depth = pe->max_depth;
-    new_pe->ProbingParser = pe->ProbingParser;
+    new_pe->ProbingParserTs = pe->ProbingParserTs;
+    new_pe->ProbingParserTc = pe->ProbingParserTc;
     new_pe->next = NULL;
 
     SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
@@ -860,7 +863,8 @@
                                                              AppProto alproto,
                                                              uint16_t min_depth, uint16_t max_depth,
                                                              uint8_t direction,
-                                                             ProbingParserFPtr ProbingParser)
+                                                             ProbingParserFPtr ProbingParser1,
+                                                             ProbingParserFPtr ProbingParser2)
 {
     SCEnter();
 
@@ -964,13 +968,14 @@
     AppLayerProtoDetectProbingParserElement *new_pe =
         AppLayerProtoDetectProbingParserElementCreate(alproto,
                                                       curr_port->port,
-                                                      min_depth, max_depth,
-                                                      ProbingParser);
+                                                      min_depth, max_depth);
     if (new_pe == NULL)
         goto error;
     curr_pe = new_pe;
     AppLayerProtoDetectProbingParserElement **head_pe;
     if (direction & STREAM_TOSERVER) {
+        curr_pe->ProbingParserTs = ProbingParser1;
+        curr_pe->ProbingParserTc = ProbingParser2;
         if (curr_port->dp == NULL)
             curr_port->dp_max_depth = new_pe->max_depth;
         if (new_pe->max_depth == 0)
@@ -982,6 +987,8 @@
         curr_port->alproto_mask |= new_pe->alproto_mask;
         head_pe = &curr_port->dp;
     } else {
+        curr_pe->ProbingParserTs = ProbingParser2;
+        curr_pe->ProbingParserTc = ProbingParser1;
         if (curr_port->sp == NULL)
             curr_port->sp_max_depth = new_pe->max_depth;
         if (new_pe->max_depth == 0)
@@ -1390,7 +1397,8 @@
                                    AppProto alproto,
                                    uint16_t min_depth, uint16_t max_depth,
                                    uint8_t direction,
-                                   ProbingParserFPtr ProbingParser)
+                                   ProbingParserFPtr ProbingParser1,
+                                   ProbingParserFPtr ProbingParser2)
 {
     SCEnter();
 
@@ -1408,7 +1416,8 @@
                                                       alproto,
                                                       min_depth, max_depth,
                                                       direction,
-                                                      ProbingParser);
+                                                      ProbingParser1,
+                                                      ProbingParser2);
         }
         temp_dp = temp_dp->next;
     }
@@ -1422,7 +1431,8 @@
                                          const char *alproto_name,
                                          AppProto alproto,
                                          uint16_t min_depth, uint16_t max_depth,
-                                         ProbingParserFPtr ProbingParser)
+                                         ProbingParserFPtr ProbingParserTs,
+                                         ProbingParserFPtr ProbingParserTc)
 {
     SCEnter();
 
@@ -1469,7 +1479,7 @@
                                       alproto,
                                       min_depth, max_depth,
                                       STREAM_TOSERVER, /* to indicate dp */
-                                      ProbingParser);
+                                      ProbingParserTs, ProbingParserTc);
     }
 
     /* detect by source port of flow */
@@ -1483,7 +1493,7 @@
                                       alproto,
                                       min_depth, max_depth,
                                       STREAM_TOCLIENT, /* to indicate sp */
-                                      ProbingParser);
+                                      ProbingParserTc, ProbingParserTs);
 
     }
 
@@ -1540,7 +1550,7 @@
 #ifdef __SC_CUDA_SUPPORT__
     /* CUDA won't work here, so fall back to AC */
     if (mpm_matcher == MPM_AC_CUDA)
-        mpm_matcher = DEFAULT_MPM;
+        mpm_matcher = mpm_default_matcher;
 #endif
 
     alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
@@ -1614,6 +1624,9 @@
     ConfNode *node;
     int r;
 
+#ifdef AFLFUZZ_APPLAYER
+    goto enabled;
+#endif
     if (RunmodeIsUnittests())
         goto enabled;
 
@@ -2980,57 +2993,57 @@
                                   ALPROTO_HTTP,
                                   5, 8,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "80",
                                   ALPROTO_SMB,
                                   5, 6,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "80",
                                   ALPROTO_FTP,
                                   7, 10,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
 
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "81",
                                   ALPROTO_DCERPC,
                                   9, 10,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "81",
                                   ALPROTO_FTP,
                                   7, 15,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "0",
                                   ALPROTO_SMTP,
                                   12, 0,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "0",
                                   ALPROTO_TLS,
                                   12, 18,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
 
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "85",
                                   ALPROTO_DCERPC,
                                   9, 10,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "85",
                                   ALPROTO_FTP,
                                   7, 15,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     result = 1;
 
     AppLayerProtoDetectPPRegister(IPPROTO_UDP,
@@ -3038,7 +3051,7 @@
                                   ALPROTO_IMAP,
                                   12, 23,
                                   STREAM_TOSERVER,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
 
     /* toclient */
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
@@ -3046,74 +3059,74 @@
                                   ALPROTO_JABBER,
                                   12, 23,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "0",
                                   ALPROTO_IRC,
                                   12, 14,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
 
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "85",
                                   ALPROTO_DCERPC,
                                   9, 10,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "81",
                                   ALPROTO_FTP,
                                   7, 15,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "0",
                                   ALPROTO_TLS,
                                   12, 18,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "80",
                                   ALPROTO_HTTP,
                                   5, 8,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "81",
                                   ALPROTO_DCERPC,
                                   9, 10,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "90",
                                   ALPROTO_FTP,
                                   7, 15,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "80",
                                   ALPROTO_SMB,
                                   5, 6,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_UDP,
                                   "85",
                                   ALPROTO_IMAP,
                                   12, 23,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "0",
                                   ALPROTO_SMTP,
                                   12, 17,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
     AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                                   "80",
                                   ALPROTO_FTP,
                                   7, 10,
                                   STREAM_TOCLIENT,
-                                  ProbingParserDummyForTesting);
+                                  ProbingParserDummyForTesting, NULL);
 
     AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
         { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
diff -Nru suricata-3.2/src/app-layer-detect-proto.h suricata-3.2.1/src/app-layer-detect-proto.h
--- suricata-3.2/src/app-layer-detect-proto.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-detect-proto.h	2017-02-15 08:54:12.000000000 +0100
@@ -65,7 +65,8 @@
                                    AppProto alproto,
                                    uint16_t min_depth, uint16_t max_depth,
                                    uint8_t direction,
-                                   ProbingParserFPtr ProbingParser);
+                                   ProbingParserFPtr ProbingParser1,
+                                   ProbingParserFPtr ProbingParser2);
 /**
  *  \retval bool 0 if no config was found, 1 if config was found
  */
@@ -74,7 +75,8 @@
                                          const char *alproto_name,
                                          AppProto alproto,
                                          uint16_t min_depth, uint16_t max_depth,
-                                         ProbingParserFPtr ProbingParser);
+                                         ProbingParserFPtr ProbingParserTs,
+                                         ProbingParserFPtr ProbingParserTc);
 
 /***** PM registration *****/
 
diff -Nru suricata-3.2/src/app-layer-dnp3.c suricata-3.2.1/src/app-layer-dnp3.c
--- suricata-3.2/src/app-layer-dnp3.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-dnp3.c	2017-02-15 08:54:12.000000000 +0100
@@ -1592,13 +1592,15 @@
         if (RunmodeIsUnittests()) {
             AppLayerProtoDetectPPRegister(IPPROTO_TCP, DNP3_DEFAULT_PORT,
                 ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader), STREAM_TOSERVER,
-                DNP3ProbingParser);
+                DNP3ProbingParser, NULL);
         }
         else {
             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                     proto_name, ALPROTO_DNP3, 0, sizeof(DNP3LinkHeader),
-                    DNP3ProbingParser)) {
+                    DNP3ProbingParser, NULL)) {
+#ifndef AFLFUZZ_APPLAYER
                 return;
+#endif
             }
         }
 
diff -Nru suricata-3.2/src/app-layer-dns-common.c suricata-3.2.1/src/app-layer-dns-common.c
--- suricata-3.2/src/app-layer-dns-common.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-dns-common.c	2017-02-15 08:54:12.000000000 +0100
@@ -605,6 +605,7 @@
             return;
         TAILQ_INSERT_TAIL(&dns_state->tx_list, tx, next);
         dns_state->curr = tx;
+        dns_state->transaction_max++;
         tx->tx_num = dns_state->transaction_max;
     }
 
@@ -857,7 +858,7 @@
 
                 DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
                         ntohs(head->type), ntohs(head->class), ntohl(head->ttl),
-                        data, 4, ntohs(dns_header->tx_id));
+                        data, datalen, ntohs(dns_header->tx_id));
             } else {
                 SCLogDebug("invalid length for A response data: %u", ntohs(head->len));
                 goto bad_data;
@@ -875,7 +876,7 @@
 
                 DNSStoreAnswerInState(dns_state, list, fqdn, fqdn_len,
                         ntohs(head->type), ntohs(head->class), ntohl(head->ttl),
-                        data, 16, ntohs(dns_header->tx_id));
+                        data, datalen, ntohs(dns_header->tx_id));
             } else {
                 SCLogDebug("invalid length for AAAA response data: %u", ntohs(head->len));
                 goto bad_data;
diff -Nru suricata-3.2/src/app-layer-dns-tcp.c suricata-3.2.1/src/app-layer-dns-tcp.c
--- suricata-3.2/src/app-layer-dns-tcp.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-dns-tcp.c	2017-02-15 08:54:12.000000000 +0100
@@ -363,7 +363,7 @@
             goto bad_data;
     }
 
-    if (dns_state != NULL && f != NULL) {
+    if (f != NULL) {
         dns_state->last_req = f->lastts;
     }
 
@@ -582,7 +582,7 @@
             goto bad_data;
     }
 
-    if (dns_state != NULL && f != NULL) {
+    if (f != NULL) {
         dns_state->last_req = f->lastts;
     }
 
@@ -627,6 +627,28 @@
     return ALPROTO_DNS;
 }
 
+/**
+ * \brief Probing parser for TCP DNS responses.
+ *
+ * This is a minimal parser that just checks that the input contains enough
+ * data for a TCP DNS response.
+ */
+static uint16_t DNSTcpProbeResponse(uint8_t *input, uint32_t len,
+    uint32_t *offset)
+{
+    if (len == 0 || len < sizeof(DNSTcpHeader)) {
+        return ALPROTO_UNKNOWN;
+    }
+
+    DNSTcpHeader *dns_header = (DNSTcpHeader *)input;
+
+    if (ntohs(dns_header->len) < sizeof(DNSHeader)) {
+        return ALPROTO_FAILED;
+    }
+
+    return ALPROTO_DNS;
+}
+
 void RegisterDNSTCPParsers(void)
 {
     char *proto_name = "dns";
@@ -641,12 +663,13 @@
                                           ALPROTO_DNS,
                                           0, sizeof(DNSTcpHeader),
                                           STREAM_TOSERVER,
-                                          DNSTcpProbingParser);
+                                          DNSTcpProbingParser, NULL);
         } else {
             int have_cfg = AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                                                 proto_name, ALPROTO_DNS,
                                                 0, sizeof(DNSTcpHeader),
-                                                DNSTcpProbingParser);
+                                                DNSTcpProbingParser,
+                                                DNSTcpProbeResponse);
             /* if we have no config, we enable the default port 53 */
             if (!have_cfg) {
                 SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS TCP config found, "
@@ -654,7 +677,8 @@
                                                 "port 53.");
                 AppLayerProtoDetectPPRegister(IPPROTO_TCP, "53",
                                    ALPROTO_DNS, 0, sizeof(DNSTcpHeader),
-                                   STREAM_TOSERVER, DNSTcpProbingParser);
+                                   STREAM_TOSERVER, DNSTcpProbingParser,
+                                   DNSTcpProbeResponse);
             }
         }
     } else {
diff -Nru suricata-3.2/src/app-layer-dns-udp.c suricata-3.2.1/src/app-layer-dns-udp.c
--- suricata-3.2/src/app-layer-dns-udp.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-dns-udp.c	2017-02-15 08:54:12.000000000 +0100
@@ -314,7 +314,7 @@
 
         tx->replied = 1;
     }
-    if (dns_state != NULL && f != NULL) {
+    if (f != NULL) {
         dns_state->last_resp = f->lastts;
     }
     SCReturnInt(1);
@@ -395,20 +395,23 @@
                                           ALPROTO_DNS,
                                           0, sizeof(DNSHeader),
                                           STREAM_TOSERVER,
-                                          DNSUdpProbingParser);
+                                          DNSUdpProbingParser,
+                                          NULL);
         } else {
             int have_cfg = AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
                                                 proto_name, ALPROTO_DNS,
                                                 0, sizeof(DNSHeader),
-                                                DNSUdpProbingParser);
+                                                DNSUdpProbingParser, NULL);
             /* if we have no config, we enable the default port 53 */
             if (!have_cfg) {
+#ifndef AFLFUZZ_APPLAYER
                 SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS UDP config found, "
                                                 "enabling DNS detection on "
                                                 "port 53.");
+#endif
                 AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53",
                                    ALPROTO_DNS, 0, sizeof(DNSHeader),
-                                   STREAM_TOSERVER, DNSUdpProbingParser);
+                                   STREAM_TOSERVER, DNSUdpProbingParser, NULL);
             }
         }
     } else {
diff -Nru suricata-3.2/src/app-layer-enip.c suricata-3.2.1/src/app-layer-enip.c
--- suricata-3.2/src/app-layer-enip.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-enip.c	2017-02-15 08:54:12.000000000 +0100
@@ -383,27 +383,27 @@
         if (RunmodeIsUnittests())
         {
             AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
-                    0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser);
+                    0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
 
             AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818", ALPROTO_ENIP,
-                    0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser);
+                    0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
 
         } else
         {
             if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
                     proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
-                    ENIPProbingParser))
+                    ENIPProbingParser, ENIPProbingParser))
             {
                 SCLogDebug(
                         "no ENIP UDP config found enabling ENIP detection on port 44818.");
 
                 AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
                         ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr), STREAM_TOSERVER,
-                        ENIPProbingParser);
+                        ENIPProbingParser, NULL);
 
                 AppLayerProtoDetectPPRegister(IPPROTO_UDP, "44818",
                         ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT,
-                        ENIPProbingParser);
+                        ENIPProbingParser, NULL);
             }
         }
 
@@ -471,18 +471,20 @@
         if (RunmodeIsUnittests())
         {
             AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
-                    0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser);
+                    0, sizeof(ENIPEncapHdr), STREAM_TOSERVER, ENIPProbingParser, NULL);
 
             AppLayerProtoDetectPPRegister(IPPROTO_TCP, "44818", ALPROTO_ENIP,
-                    0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser);
+                    0, sizeof(ENIPEncapHdr), STREAM_TOCLIENT, ENIPProbingParser, NULL);
 
         } else
         {
             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                     proto_name, ALPROTO_ENIP, 0, sizeof(ENIPEncapHdr),
-                    ENIPProbingParser))
+                    ENIPProbingParser, ENIPProbingParser))
             {
+#ifndef AFLFUZZ_APPLAYER
                 return;
+#endif
             }
         }
 
diff -Nru suricata-3.2/src/app-layer-htp.c suricata-3.2.1/src/app-layer-htp.c
--- suricata-3.2/src/app-layer-htp.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-htp.c	2017-02-15 08:54:12.000000000 +0100
@@ -2737,7 +2737,7 @@
              * 3 is subtracted from the length since the spacing is hex typed as |xx|
              * but the pattern matching should only be one char
             */
-            register_result = AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP,
+            register_result = AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP,
                     ALPROTO_HTTP, method_buffer, strlen(method_buffer)-3, 0, STREAM_TOSERVER);
             if (register_result < 0) {
                 return -1;
@@ -2747,7 +2747,7 @@
 
     /* Loop through all the http verions patterns that are TO_CLIENT */
     for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
-        register_result = AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP,
+        register_result = AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP,
                 ALPROTO_HTTP, versions[versions_pos], strlen(versions[versions_pos]),
                 0, STREAM_TOCLIENT);
         if (register_result < 0) {
diff -Nru suricata-3.2/src/app-layer-htp-file.c suricata-3.2.1/src/app-layer-htp-file.c
--- suricata-3.2/src/app-layer-htp-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-htp-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -633,11 +633,11 @@
     }
 
     if (http_state->files_ts->head == NULL ||
-        FileSize(http_state->files_ts->head) != 11)
+        FileDataSize(http_state->files_ts->head) != 11)
     {
         if (http_state->files_ts->head != NULL)
             printf("filedata len not 11 but %"PRIu64": ",
-                    FileSize(http_state->files_ts->head));
+                    FileDataSize(http_state->files_ts->head));
         goto end;
     }
 
diff -Nru suricata-3.2/src/app-layer-modbus.c suricata-3.2.1/src/app-layer-modbus.c
--- suricata-3.2/src/app-layer-modbus.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-modbus.c	2017-02-15 08:54:12.000000000 +0100
@@ -1455,14 +1455,14 @@
                                           ALPROTO_MODBUS,
                                           0, sizeof(ModbusHeader),
                                           STREAM_TOSERVER,
-                                          ModbusProbingParser);
+                                          ModbusProbingParser, NULL);
         } else {
             /* If there is no app-layer section for Modbus, silently
              * leave it disabled. */
             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                                                 proto_name, ALPROTO_MODBUS,
                                                 0, sizeof(ModbusHeader),
-                                                ModbusProbingParser)) {
+                                                ModbusProbingParser, NULL)) {
 #ifndef AFLFUZZ_APPLAYER
                 return;
 #endif
@@ -1497,11 +1497,7 @@
         return;
 #endif
     }
-#ifndef AFLFUZZ_APPLAYER
     if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
-#else
-    if (1) {
-#endif
         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOSERVER, ModbusParseRequest);
         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_MODBUS, STREAM_TOCLIENT, ModbusParseResponse);
         AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, ModbusStateAlloc, ModbusStateFree);
diff -Nru suricata-3.2/src/app-layer-parser.c suricata-3.2.1/src/app-layer-parser.c
--- suricata-3.2/src/app-layer-parser.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-parser.c	2017-02-15 08:54:12.000000000 +0100
@@ -265,6 +265,10 @@
     SCReturn;
 }
 
+/** \brief check if a parser is enabled in the config
+ *  Returns enabled always if: were running unittests and
+ *                             when compiled with --enable-afl
+ */
 int AppLayerParserConfParserEnabled(const char *ipproto,
                                     const char *alproto_name)
 {
@@ -275,6 +279,9 @@
     ConfNode *node;
     int r;
 
+#ifdef AFLFUZZ_APPLAYER
+    goto enabled;
+#endif
     if (RunmodeIsUnittests())
         goto enabled;
 
@@ -597,12 +604,12 @@
     SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t");
 }
 
-void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate)
+void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id)
 {
     SCEnter();
 
     if (pstate != NULL)
-        pstate->log_id++;
+        pstate->log_id = tx_id;
 
     SCReturn;
 }
@@ -1307,7 +1314,7 @@
 #endif
 
 #ifdef AFLFUZZ_APPLAYER
-int AppLayerParserRequestFromFile(AppProto alproto, char *filename)
+int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename)
 {
     int result = 1;
     Flow *f = NULL;
@@ -1327,7 +1334,8 @@
     f->sp = 10000;
     f->dp = 80;
     f->protoctx = &ssn;
-    f->proto = IPPROTO_TCP;
+    f->proto = ipproto;
+    f->protomap = FlowGetProtoMapping(f->proto);
     f->alproto = alproto;
 
     uint8_t buffer[64];
@@ -1344,8 +1352,8 @@
         int start = 1;
         while (1) {
             int done = 0;
-            size_t result = fread(&buffer, 1, sizeof(buffer), fp);
-            if (result < sizeof(buffer))
+            size_t size = fread(&buffer, 1, sizeof(buffer), fp);
+            if (size < sizeof(buffer))
                 done = 1;
 
             //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
@@ -1361,7 +1369,7 @@
             //PrintRawDataFp(stdout, buffer, result);
 
             (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
-                                      buffer, result);
+                                      buffer, size);
             if (done)
                 break;
         }
@@ -1383,7 +1391,7 @@
     return result;
 }
 
-int AppLayerParserFromFile(AppProto alproto, char *filename)
+int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename)
 {
     int result = 1;
     Flow *f = NULL;
@@ -1403,7 +1411,8 @@
     f->sp = 10000;
     f->dp = 80;
     f->protoctx = &ssn;
-    f->proto = IPPROTO_TCP;
+    f->proto = ipproto;
+    f->protomap = FlowGetProtoMapping(f->proto);
     f->alproto = alproto;
 
     uint8_t buffer[64];
@@ -1421,8 +1430,8 @@
         int flip = 0;
         while (1) {
             int done = 0;
-            size_t result = fread(&buffer, 1, sizeof(buffer), fp);
-            if (result < sizeof(buffer))
+            size_t size = fread(&buffer, 1, sizeof(buffer), fp);
+            if (size < sizeof(buffer))
                 done = 1;
 
             //SCLogInfo("result %u done %d start %d", (uint)result, done, start);
@@ -1445,7 +1454,7 @@
             //PrintRawDataFp(stdout, buffer, result);
 
             (void)AppLayerParserParse(NULL, alp_tctx, f, alproto, flags,
-                                      buffer, result);
+                                      buffer, size);
             if (done)
                 break;
         }
diff -Nru suricata-3.2/src/app-layer-parser.h suricata-3.2.1/src/app-layer-parser.h
--- suricata-3.2/src/app-layer-parser.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-parser.h	2017-02-15 08:54:12.000000000 +0100
@@ -162,7 +162,7 @@
 
 
 uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate);
-void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate);
+void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate, uint64_t tx_id);
 void AppLayerParserSetTxLogged(uint8_t ipproto, AppProto alproto, void *alstate,
                                void *tx, uint32_t logger);
 int AppLayerParserGetTxLogged(uint8_t ipproto, AppProto alproto, void *alstate,
@@ -237,8 +237,8 @@
 #endif
 
 #ifdef AFLFUZZ_APPLAYER
-int AppLayerParserRequestFromFile(AppProto alproto, char *filename);
-int AppLayerParserFromFile(AppProto alproto, char *filename);
+int AppLayerParserRequestFromFile(uint8_t ipproto, AppProto alproto, char *filename);
+int AppLayerParserFromFile(uint8_t ipproto, AppProto alproto, char *filename);
 #endif
 
 /***** Unittests *****/
diff -Nru suricata-3.2/src/app-layer-smb.c suricata-3.2.1/src/app-layer-smb.c
--- suricata-3.2/src/app-layer-smb.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-smb.c	2017-02-15 08:54:12.000000000 +0100
@@ -678,6 +678,7 @@
             sstate->bytesprocessed += parsed;
             sstate->bytecount.bytecountleft -= parsed;
             input_len -= parsed;
+            (void)input_len; /* for scan-build */
         }
     }
     SCReturnInt(parsed);
@@ -833,7 +834,9 @@
             sres = DataParser(sstate, pstate, input + parsed, input_len);
             if (sres != -1 && sres <= (int32_t)input_len) {
                 parsed += (uint32_t)sres;
+                (void)parsed; /* for scan-build */
                 input_len -= (uint32_t)sres;
+                (void)input_len; /* for scan-build */
             } else { /* Did not Validate as DCERPC over SMB */
                 while (sstate->bytecount.bytecountleft-- && input_len--) {
                     SCLogDebug("0x%02x bytecount %"PRIu16"/%"PRIu16" input_len %"PRIu32, *p,
@@ -1497,18 +1500,17 @@
 
 static int SMBRegisterPatternsForProtocolDetection(void)
 {
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB,
-                                               "|ff|SMB", 8, 4, STREAM_TOSERVER) < 0)
-    {
-        return -1;
-    }
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB2,
-                                               "|fe|SMB", 8, 4, STREAM_TOSERVER) < 0)
-    {
-        return -1;
-    }
-
-    return 0;
+    int r = 0;
+    r |= AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB,
+            "|ff|SMB", 8, 4, STREAM_TOSERVER);
+    r |= AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB,
+            "|ff|SMB", 8, 4, STREAM_TOCLIENT);
+
+    r |= AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB2,
+            "|fe|SMB", 8, 4, STREAM_TOSERVER);
+    r |= AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB2,
+            "|fe|SMB", 8, 4, STREAM_TOCLIENT);
+    return r == 0 ? 0 : -1;
 }
 
 void RegisterSMBParsers(void)
@@ -1526,12 +1528,12 @@
                                           ALPROTO_SMB,
                                           SMB_PROBING_PARSER_MIN_DEPTH, 0,
                                           STREAM_TOSERVER,
-                                          SMBProbingParser);
+                                          SMBProbingParser, SMBProbingParser);
         } else {
             AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                                                 proto_name, ALPROTO_SMB,
                                                 SMB_PROBING_PARSER_MIN_DEPTH, 0,
-                                                SMBProbingParser);
+                                                SMBProbingParser, SMBProbingParser);
         }
 
         AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_SMB, STREAM_TOSERVER);
@@ -2217,7 +2219,7 @@
                                   ALPROTO_SMB,
                                   SMB_PROBING_PARSER_MIN_DEPTH, 0,
                                   STREAM_TOSERVER,
-                                  SMBProbingParser);
+                                  SMBProbingParser, NULL);
 
     AppLayerProtoDetectPrepareState();
     alpd_tctx = AppLayerProtoDetectGetCtxThread();
@@ -2301,7 +2303,7 @@
                    ALPROTO_SMB,
                    SMB_PROBING_PARSER_MIN_DEPTH, 0,
                    STREAM_TOSERVER,
-                   SMBProbingParser);
+                   SMBProbingParser, NULL);
 
     AppLayerProtoDetectPrepareState();
     alpd_tctx = AppLayerProtoDetectGetCtxThread();
diff -Nru suricata-3.2/src/app-layer-smtp.c suricata-3.2.1/src/app-layer-smtp.c
--- suricata-3.2/src/app-layer-smtp.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-smtp.c	2017-02-15 08:54:12.000000000 +0100
@@ -157,7 +157,7 @@
     PrefilterRuleStore *pmq;
 } SMTPThreadCtx;
 
-#define SMTP_MPM DEFAULT_MPM
+#define SMTP_MPM mpm_default_matcher
 
 static MpmCtx *smtp_mpm_ctx = NULL;
 
@@ -371,7 +371,7 @@
         if (file->sb->stream_offset == 0)
             window = MAX(window, smtp_config.content_inspect_min_size);
 
-        uint64_t file_size = FileSize(file);
+        uint64_t file_size = FileDataSize(file);
         uint64_t data_size = file_size - file->sb->stream_offset;
 
         SCLogDebug("window %"PRIu32", file_size %"PRIu64", data_size %"PRIu64,
@@ -1490,17 +1490,17 @@
 
 static int SMTPRegisterPatternsForProtocolDetection(void)
 {
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
+    if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_SMTP,
                                                "EHLO", 4, 0, STREAM_TOSERVER) < 0)
     {
         return -1;
     }
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
+    if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_SMTP,
                                                "HELO", 4, 0, STREAM_TOSERVER) < 0)
     {
         return -1;
     }
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP,
+    if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_SMTP,
                                                "QUIT", 4, 0, STREAM_TOSERVER) < 0)
     {
         return -1;
@@ -4840,8 +4840,8 @@
             printf("smtp-mime file name is incorrect");
             goto end;
         }
-        if (FileSize(file) != filesize){
-            printf("smtp-mime file size %"PRIu64" is incorrect", FileSize(file));
+        if (FileTrackedSize(file) != filesize){
+            printf("smtp-mime file size %"PRIu64" is incorrect", FileDataSize(file));
             goto end;
         }
         static uint8_t org_binary[] = {
@@ -5127,7 +5127,7 @@
     FAIL_IF(file == NULL);
     ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state);
     FAIL_IF(ret != 0);
-    FAIL_IF((uint32_t)FileSize(file) != 106);
+    FAIL_IF((uint32_t)FileDataSize(file) != 106);
     SMTPStateFree(smtp_state);
     FLOW_DESTROY(&f);
     PASS;
diff -Nru suricata-3.2/src/app-layer-ssl.c suricata-3.2.1/src/app-layer-ssl.c
--- suricata-3.2/src/app-layer-ssl.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-ssl.c	2017-02-15 08:54:12.000000000 +0100
@@ -67,6 +67,7 @@
     { "MULTIPLE_SNI_EXTENSIONS",     TLS_DECODER_EVENT_MULTIPLE_SNI_EXTENSIONS },
     { "INVALID_SNI_TYPE",            TLS_DECODER_EVENT_INVALID_SNI_TYPE },
     { "INVALID_SNI_LENGTH",          TLS_DECODER_EVENT_INVALID_SNI_LENGTH },
+    { "TOO_MANY_RECORDS_IN_PACKET",  TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET },
     /* certificate decoding messages */
     { "INVALID_CERTIFICATE",         TLS_DECODER_EVENT_INVALID_CERTIFICATE },
     { "CERTIFICATE_MISSING_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT },
@@ -131,6 +132,8 @@
 #define TLS_HB_REQUEST                  1
 #define TLS_HB_RESPONSE                 2
 
+#define SSL_PACKET_MAX_RECORDS        255
+
 #define HAS_SPACE(n) ((uint32_t)((input) + (n) - (initial_input)) > (uint32_t)(input_len)) ?  0 : 1
 
 static void SSLParserReset(SSLState *ssl_state)
@@ -232,6 +235,13 @@
         return TLS_HANDSHAKE_DONE;
     }
 
+    if (direction == STREAM_TOSERVER &&
+        (ssl_state->server_connp.cert0_subject != NULL ||
+         ssl_state->server_connp.cert0_issuerdn != NULL))
+    {
+        return TLS_STATE_CERT_READY;
+    }
+
     return TLS_STATE_IN_PROGRESS;
 }
 
@@ -275,8 +285,9 @@
 
     input += compression_methods_length;
 
+    /* extensions are optional (RFC5246 section 7.4.1.2) */
     if (!(HAS_SPACE(2)))
-        goto invalid_length;
+        goto end;
 
     uint16_t extensions_len = input[0] << 8 | input[1];
     input += 2;
@@ -438,6 +449,7 @@
                 ssl_state->curr_connp->trec_len = 0;
                 /* error, skip packet */
                 parsed += input_len;
+                (void)parsed; /* for scan-build */
                 ssl_state->curr_connp->bytes_processed += input_len;
                 return -1;
             }
@@ -1254,6 +1266,7 @@
 
                 parsed += retval;
                 input_len -= retval;
+                (void)input_len; /* for scan-build */
 
                 if (ssl_state->curr_connp->bytes_processed ==
                         ssl_state->curr_connp->record_length +
@@ -1364,11 +1377,12 @@
 
     /* if we have more than one record */
     while (input_len > 0) {
-        if (counter++ == 30) {
+        if (counter++ == SSL_PACKET_MAX_RECORDS) {
             SCLogDebug("Looks like we have looped quite a bit. Reset state "
                        "and get out of here");
             SSLParserReset(ssl_state);
-            SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
+            SSLSetEvent(ssl_state,
+                        TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET);
             return -1;
         }
 
@@ -1761,12 +1775,12 @@
                                           ALPROTO_TLS,
                                           0, 3,
                                           STREAM_TOSERVER,
-                                          SSLProbingParser);
+                                          SSLProbingParser, NULL);
         } else {
             AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                                                 proto_name, ALPROTO_TLS,
                                                 0, 3,
-                                                SSLProbingParser);
+                                                SSLProbingParser, NULL);
         }
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol",
diff -Nru suricata-3.2/src/app-layer-ssl.h suricata-3.2.1/src/app-layer-ssl.h
--- suricata-3.2/src/app-layer-ssl.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-ssl.h	2017-02-15 08:54:12.000000000 +0100
@@ -46,6 +46,7 @@
     TLS_DECODER_EVENT_MULTIPLE_SNI_EXTENSIONS,
     TLS_DECODER_EVENT_INVALID_SNI_TYPE,
     TLS_DECODER_EVENT_INVALID_SNI_LENGTH,
+    TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET,
     /* Certificates decoding messages */
     TLS_DECODER_EVENT_INVALID_CERTIFICATE,
     TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT,
@@ -58,8 +59,9 @@
 
 enum {
     TLS_STATE_IN_PROGRESS = 0,
-    TLS_HANDSHAKE_DONE = 1,
-    TLS_STATE_FINISHED = 2
+    TLS_STATE_CERT_READY = 1,
+    TLS_HANDSHAKE_DONE = 2,
+    TLS_STATE_FINISHED = 3
 };
 
 /* Flag to indicate that server will now on send encrypted msgs */
diff -Nru suricata-3.2/src/app-layer-template.c suricata-3.2.1/src/app-layer-template.c
--- suricata-3.2/src/app-layer-template.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/app-layer-template.c	2017-02-15 08:54:12.000000000 +0100
@@ -472,21 +472,21 @@
             SCLogNotice("Unittest mode, registeringd default configuration.");
             AppLayerProtoDetectPPRegister(IPPROTO_TCP, TEMPLATE_DEFAULT_PORT,
                 ALPROTO_TEMPLATE, 0, TEMPLATE_MIN_FRAME_LEN, STREAM_TOSERVER,
-                TemplateProbingParser);
+                TemplateProbingParser, NULL);
 
         }
         else {
 
             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                     proto_name, ALPROTO_TEMPLATE, 0, TEMPLATE_MIN_FRAME_LEN,
-                    TemplateProbingParser)) {
+                    TemplateProbingParser, NULL)) {
                 SCLogNotice("No echo app-layer configuration, enabling echo"
                     " detection TCP detection on port %s.",
                     TEMPLATE_DEFAULT_PORT);
                 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                     TEMPLATE_DEFAULT_PORT, ALPROTO_TEMPLATE, 0,
                     TEMPLATE_MIN_FRAME_LEN, STREAM_TOSERVER,
-                    TemplateProbingParser);
+                    TemplateProbingParser, NULL);
             }
 
         }
diff -Nru suricata-3.2/src/decode-afl.c suricata-3.2.1/src/decode-afl.c
--- suricata-3.2/src/decode-afl.c	1970-01-01 01:00:00.000000000 +0100
+++ suricata-3.2.1/src/decode-afl.c	2017-02-15 08:54:12.000000000 +0100
@@ -0,0 +1,167 @@
+/* Copyright (C) 2007-2017 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "suricata-common.h"
+#include "suricata.h"
+#include "conf.h"
+#include "decode.h"
+#include "util-debug.h"
+#include "util-mem.h"
+#include "app-layer-detect-proto.h"
+#include "app-layer.h"
+#include "tm-threads.h"
+#include "util-error.h"
+#include "util-print.h"
+#include "tmqh-packetpool.h"
+#include "util-profiling.h"
+#include "pkt-var.h"
+#include "util-mpm-ac.h"
+
+#include "output.h"
+#include "output-flow.h"
+
+#include "defrag.h"
+#include "flow.h"
+
+#ifdef AFLFUZZ_DECODER
+
+/* stateful processing of data as packets. Because AFL in case of a
+ * crash will only safe the last input, we dump all the inputs to a
+ * directory 'dump' with a unique timestamp for the serie and an
+ * incrementing 'id' so that we can 'replay' it in
+ * DecoderParseDataFromFileSerie().
+ */
+int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder) {
+    uint8_t buffer[65536];
+
+    struct timeval ts;
+    memset(&ts, 0, sizeof(ts));
+    gettimeofday(&ts, NULL);
+
+    uint32_t cnt = 0;
+
+    DefragInit();
+    FlowInitConfig(FLOW_QUIET);
+
+    ThreadVars tv;
+    memset(&tv, 0, sizeof(tv));
+    DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv);
+    DecodeRegisterPerfCounters(dtv, &tv);
+    StatsSetupPrivate(&tv);
+    PacketQueue pq;
+    memset(&pq, 0, sizeof(pq));
+
+#ifdef AFLFUZZ_PERSISTANT_MODE
+    while (__AFL_LOOP(1000)) {
+        /* reset state */
+        memset(buffer, 0, sizeof(buffer));
+#endif /* AFLFUZZ_PERSISTANT_MODE */
+
+
+        FILE *fp = fopen(filename, "r");
+        BUG_ON(fp == NULL);
+
+        size_t size = fread(&buffer, 1, sizeof(buffer), fp);
+        char outfilename[256];
+        snprintf(outfilename, sizeof(outfilename), "dump/%u-%u.%u", (uint)ts.tv_sec, (uint)ts.tv_usec, cnt);
+        FILE *out_fp = fopen(outfilename, "w");
+        BUG_ON(out_fp == NULL);
+        (void)fwrite(buffer, size, 1, out_fp);
+        fclose(out_fp);
+
+        Packet *p = PacketGetFromAlloc();
+        if (p != NULL) {
+            PacketSetData(p, buffer, size);
+            (void) Decoder (&tv, dtv, p, buffer, size, &pq);
+            while (1) {
+                Packet *extra_p = PacketDequeue(&pq);
+                if (unlikely(extra_p == NULL))
+                    break;
+                PacketFree(extra_p);
+            }
+            PacketFree(p);
+        }
+        fclose(fp);
+        cnt++;
+
+#ifdef AFLFUZZ_PERSISTANT_MODE
+    }
+#endif /* AFLFUZZ_PERSISTANT_MODE */
+
+    /* if we get here there was no crash, so we can remove our files */
+    uint32_t x = 0;
+    for (x = 0; x < cnt; x++) {
+        char rmfilename[256];
+        snprintf(rmfilename, sizeof(rmfilename), "dump/%u-%u.%u", (uint)ts.tv_sec, (uint)ts.tv_usec, x);
+        unlink(rmfilename);
+    }
+
+    DecodeThreadVarsFree(&tv, dtv);
+    FlowShutdown();
+    DefragDestroy();
+    return 0;
+}
+
+/* load a serie of files generated by DecoderParseDataFromFile() in
+ * the same order as it was produced. */
+int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder)
+{
+    uint8_t buffer[65536];
+    uint32_t cnt = 0;
+
+    DefragInit();
+    FlowInitConfig(FLOW_QUIET);
+    ThreadVars tv;
+    memset(&tv, 0, sizeof(tv));
+    DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv);
+    DecodeRegisterPerfCounters(dtv, &tv);
+    StatsSetupPrivate(&tv);
+    PacketQueue pq;
+    memset(&pq, 0, sizeof(pq));
+
+    char filename[256];
+    snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
+    FILE *fp;
+    while ((fp = fopen(filename, "r")) != NULL)
+    {
+        memset(buffer, 0, sizeof(buffer));
+
+        size_t size = fread(&buffer, 1, sizeof(buffer), fp);
+
+        Packet *p = PacketGetFromAlloc();
+        if (p != NULL) {
+            PacketSetData(p, buffer, size);
+            (void) Decoder (&tv, dtv, p, buffer, size, &pq);
+            while (1) {
+                Packet *extra_p = PacketDequeue(&pq);
+                if (unlikely(extra_p == NULL))
+                    break;
+                PacketFree(extra_p);
+            }
+            PacketFree(p);
+        }
+        fclose(fp);
+        cnt++;
+        snprintf(filename, sizeof(filename), "dump/%s.%u", fileprefix, cnt);
+    }
+    DecodeThreadVarsFree(&tv, dtv);
+    FlowShutdown();
+    DefragDestroy();
+    return 0;
+}
+#endif /* AFLFUZZ_DECODER */
+
diff -Nru suricata-3.2/src/decode.c suricata-3.2.1/src/decode.c
--- suricata-3.2/src/decode.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/decode.c	2017-02-15 08:54:12.000000000 +0100
@@ -600,55 +600,6 @@
     s->counter_ips_replaced = StatsRegisterCounter("ips.replaced", tv);
 }
 
-#ifdef AFLFUZZ_DECODER
-int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder) {
-    uint8_t buffer[65536];
-    int result = 1;
-
-#ifdef AFLFUZZ_PERSISTANT_MODE
-    while (__AFL_LOOP(1000)) {
-        /* reset state */
-        memset(buffer, 0, sizeof(buffer));
-#endif /* AFLFUZZ_PERSISTANT_MODE */
-
-        FILE *fp = fopen(filename, "r");
-        BUG_ON(fp == NULL);
-
-        ThreadVars tv;
-        memset(&tv, 0, sizeof(tv));
-        DecodeThreadVars *dtv = DecodeThreadVarsAlloc(&tv);
-        DecodeRegisterPerfCounters(dtv, &tv);
-        StatsSetupPrivate(&tv);
-
-        while (1) {
-            int done = 0;
-            size_t result = fread(&buffer, 1, sizeof(buffer), fp);
-            if (result < sizeof(buffer))
-                 done = 1;
-
-            Packet *p = PacketGetFromAlloc();
-            if (p != NULL) {
-                (void) Decoder (&tv, dtv, p, buffer, result, NULL);
-                PacketFree(p);
-            }
-
-            if (done)
-                break;
-        }
-        DecodeThreadVarsFree(&tv, dtv);
-
-        fclose(fp);
-
-#ifdef AFLFUZZ_PERSISTANT_MODE
-    }
-#endif /* AFLFUZZ_PERSISTANT_MODE */
-
-    result = 0;
-    return result;
-
-}
-#endif /* AFLFUZZ_DECODER */
-
 /**
  * @}
  */
diff -Nru suricata-3.2/src/decode.h suricata-3.2.1/src/decode.h
--- suricata-3.2/src/decode.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/decode.h	2017-02-15 08:54:12.000000000 +0100
@@ -594,7 +594,12 @@
 #endif
 Packet;
 
-#define DEFAULT_PACKET_SIZE (1500 + ETHERNET_HEADER_LEN)
+/** highest mtu of the interfaces we monitor */
+extern int g_default_mtu;
+#define DEFAULT_MTU 1500
+#define MINIMUM_MTU 68      /**< ipv4 minimum: rfc791 */
+
+#define DEFAULT_PACKET_SIZE (DEFAULT_MTU + ETHERNET_HEADER_LEN)
 /* storage: maximum ip packet size + link header */
 #define MAX_PAYLOAD_SIZE (IPV6_HEADER_LEN + 65536 + 28)
 uint32_t default_packet_size;
@@ -953,6 +958,7 @@
          uint8_t *pkt, uint16_t len, PacketQueue *pq);
 
 int DecoderParseDataFromFile(char *filename, DecoderFunc Decoder);
+int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder);
 #endif
 
 /** \brief Set the No payload inspection Flag for the packet.
diff -Nru suricata-3.2/src/decode-icmpv6.c suricata-3.2.1/src/decode-icmpv6.c
--- suricata-3.2/src/decode-icmpv6.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/decode-icmpv6.c	2017-02-15 08:54:12.000000000 +0100
@@ -254,7 +254,7 @@
             SCLogDebug("ICMP6_ECHO_REPLY id: %u seq: %u",
                        p->icmpv6h->icmpv6b.icmpv6i.id, p->icmpv6h->icmpv6b.icmpv6i.seq);
 
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             } else {
                 p->icmpv6vars.id = p->icmpv6h->icmpv6b.icmpv6i.id;
@@ -265,37 +265,37 @@
             break;
         case ND_ROUTER_SOLICIT:
             SCLogDebug("ND_ROUTER_SOLICIT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             break;
         case ND_ROUTER_ADVERT:
             SCLogDebug("ND_ROUTER_ADVERT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             break;
         case ND_NEIGHBOR_SOLICIT:
             SCLogDebug("ND_NEIGHBOR_SOLICIT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             break;
         case ND_NEIGHBOR_ADVERT:
             SCLogDebug("ND_NEIGHBOR_ADVERT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             break;
         case ND_REDIRECT:
             SCLogDebug("ND_REDIRECT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             break;
         case MLD_LISTENER_QUERY:
             SCLogDebug("MLD_LISTENER_QUERY");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             if (IPV6_GET_HLIM(p) != 1) {
@@ -304,7 +304,7 @@
             break;
         case MLD_LISTENER_REPORT:
             SCLogDebug("MLD_LISTENER_REPORT");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             if (IPV6_GET_HLIM(p) != 1) {
@@ -313,13 +313,136 @@
             break;
         case MLD_LISTENER_REDUCTION:
             SCLogDebug("MLD_LISTENER_REDUCTION");
-            if (p->icmpv6h->code != 0) {
+            if (ICMPV6_GET_CODE(p) != 0) {
                 ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
             }
             if (IPV6_GET_HLIM(p) != 1) {
                 ENGINE_SET_EVENT(p, ICMPV6_MLD_MESSAGE_WITH_INVALID_HL);
             }
             break;
+        case ICMP6_RR:
+            SCLogDebug("ICMP6_RR");
+            if (ICMPV6_GET_CODE(p) > 2 && ICMPV6_GET_CODE(p) != 255) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case ICMP6_NI_QUERY:
+            SCLogDebug("ICMP6_NI_QUERY");
+            if (ICMPV6_GET_CODE(p) > 2) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case ICMP6_NI_REPLY:
+            SCLogDebug("ICMP6_NI_REPLY");
+            if (ICMPV6_GET_CODE(p) > 2) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case ND_INVERSE_SOLICIT:
+            SCLogDebug("ND_INVERSE_SOLICIT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case ND_INVERSE_ADVERT:
+            SCLogDebug("ND_INVERSE_ADVERT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case MLD_V2_LIST_REPORT:
+            SCLogDebug("MLD_V2_LIST_REPORT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case HOME_AGENT_AD_REQUEST:
+            SCLogDebug("HOME_AGENT_AD_REQUEST");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case HOME_AGENT_AD_REPLY:
+            SCLogDebug("HOME_AGENT_AD_REPLY");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case MOBILE_PREFIX_SOLICIT:
+            SCLogDebug("MOBILE_PREFIX_SOLICIT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case MOBILE_PREFIX_ADVERT:
+            SCLogDebug("MOBILE_PREFIX_ADVERT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case CERT_PATH_SOLICIT:
+            SCLogDebug("CERT_PATH_SOLICIT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case CERT_PATH_ADVERT:
+            SCLogDebug("CERT_PATH_ADVERT");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case ICMP6_MOBILE_EXPERIMENTAL:
+            SCLogDebug("ICMP6_MOBILE_EXPERIMENTAL");
+            break;
+        case MC_ROUTER_ADVERT:
+            SCLogDebug("MC_ROUTER_ADVERT");
+            break;
+        case MC_ROUTER_SOLICIT:
+            SCLogDebug("MC_ROUTER_SOLICIT");
+            break;
+        case MC_ROUTER_TERMINATE:
+            SCLogDebug("MC_ROUTER_TERMINATE");
+            break;
+        case FMIPV6_MSG:
+            SCLogDebug("FMIPV6_MSG");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case RPL_CONTROL_MSG:
+            SCLogDebug("RPL_CONTROL_MSG");
+            if (ICMPV6_GET_CODE(p) > 3 && ICMPV6_GET_CODE(p) < 128) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            if (ICMPV6_GET_CODE(p) > 132) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case LOCATOR_UDATE_MSG:
+            SCLogDebug("LOCATOR_UDATE_MSG");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case DUPL_ADDR_REQUEST:
+            SCLogDebug("DUPL_ADDR_REQUEST");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case DUPL_ADDR_CONFIRM:
+            SCLogDebug("DUPL_ADDR_CONFIRM");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
+        case MPL_CONTROL_MSG:
+            SCLogDebug("MPL_CONTROL_MSG");
+            if (ICMPV6_GET_CODE(p) != 0) {
+                ENGINE_SET_EVENT(p, ICMPV6_UNKNOWN_CODE);
+            }
+            break;
         default:
             /* Various range taken from:
              *   http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-2
diff -Nru suricata-3.2/src/decode-icmpv6.h suricata-3.2.1/src/decode-icmpv6.h
--- suricata-3.2/src/decode-icmpv6.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/decode-icmpv6.h	2017-02-15 08:54:12.000000000 +0100
@@ -53,6 +53,29 @@
 #define ND_NEIGHBOR_ADVERT          136
 #define ND_REDIRECT                 137
 
+#define ICMP6_RR                    138
+#define ICMP6_NI_QUERY              139
+#define ICMP6_NI_REPLY              140
+#define ND_INVERSE_SOLICIT          141
+#define ND_INVERSE_ADVERT           142
+#define MLD_V2_LIST_REPORT          143
+#define HOME_AGENT_AD_REQUEST       144
+#define HOME_AGENT_AD_REPLY         145
+#define MOBILE_PREFIX_SOLICIT       146
+#define MOBILE_PREFIX_ADVERT        147
+#define CERT_PATH_SOLICIT           148
+#define CERT_PATH_ADVERT            149
+#define ICMP6_MOBILE_EXPERIMENTAL   150
+#define MC_ROUTER_ADVERT            151
+#define MC_ROUTER_SOLICIT           152
+#define MC_ROUTER_TERMINATE         153
+#define FMIPV6_MSG                  154
+#define RPL_CONTROL_MSG             155
+#define LOCATOR_UDATE_MSG           156
+#define DUPL_ADDR_REQUEST           157
+#define DUPL_ADDR_CONFIRM           158
+#define MPL_CONTROL_MSG             159
+
 /** Destination Unreachable Message (type=1) Code: */
 
 #define ICMP6_DST_UNREACH_NOROUTE       0 /* no route to destination */
diff -Nru suricata-3.2/src/defrag.c suricata-3.2.1/src/defrag.c
--- suricata-3.2/src/defrag.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/defrag.c	2017-02-15 08:54:12.000000000 +0100
@@ -996,8 +996,8 @@
  * with some payload of no particular protocol.
  */
 static Packet *
-BuildTestPacket(uint16_t id, uint16_t off, int mf, const char content,
-    int content_len)
+BuildTestPacket(uint8_t proto, uint16_t id, uint16_t off, int mf,
+    const char content, int content_len)
 {
     Packet *p = NULL;
     int hlen = 20;
@@ -1023,7 +1023,7 @@
     else
         ip4h.ip_off = htons(off);
     ip4h.ip_ttl = ttl;
-    ip4h.ip_proto = IPPROTO_ICMP;
+    ip4h.ip_proto = proto;
 
     ip4h.s_ip_src.s_addr = 0x01010101; /* 1.1.1.1 */
     ip4h.s_ip_dst.s_addr = 0x02020202; /* 2.2.2.2 */
@@ -1059,7 +1059,7 @@
         goto error;
     if (IPV4_GET_IPTTL(p) != ttl)
         goto error;
-    if (IPV4_GET_IPPROTO(p) != IPPROTO_ICMP)
+    if (IPV4_GET_IPPROTO(p) != proto)
         goto error;
 
     return p;
@@ -1074,8 +1074,8 @@
                           uint16_t prev_hdrextlen);
 
 static Packet *
-IPV6BuildTestPacket(uint32_t id, uint16_t off, int mf, const char content,
-    int content_len)
+IPV6BuildTestPacket(uint8_t proto, uint32_t id, uint16_t off, int mf,
+    const char content, int content_len)
 {
     Packet *p = NULL;
     uint8_t *pcontent;
@@ -1109,7 +1109,7 @@
     IPV6_SET_RAW_VER(p->ip6h, 6);
     /* Fragmentation header. */
     IPV6FragHdr *fh = (IPV6FragHdr *)(GET_PKT_DATA(p) + sizeof(IPV6Hdr));
-    fh->ip6fh_nxt = IPPROTO_ICMP;
+    fh->ip6fh_nxt = proto;
     fh->ip6fh_ident = htonl(id);
     fh->ip6fh_offlg = htons((off << 3) | mf);
 
@@ -1159,13 +1159,13 @@
 
     DefragInit();
 
-    p1 = BuildTestPacket(id, 0, 1, 'A', 8);
+    p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = BuildTestPacket(id, 1, 1, 'B', 8);
+    p2 = BuildTestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
     if (p2 == NULL)
         goto end;
-    p3 = BuildTestPacket(id, 2, 0, 'C', 3);
+    p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
     if (p3 == NULL)
         goto end;
 
@@ -1236,13 +1236,13 @@
 
     DefragInit();
 
-    p1 = BuildTestPacket(id, 0, 1, 'A', 8);
+    p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = BuildTestPacket(id, 1, 1, 'B', 8);
+    p2 = BuildTestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
     if (p2 == NULL)
         goto end;
-    p3 = BuildTestPacket(id, 2, 0, 'C', 3);
+    p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
     if (p3 == NULL)
         goto end;
 
@@ -1308,13 +1308,13 @@
 
     DefragInit();
 
-    p1 = IPV6BuildTestPacket(id, 0, 1, 'A', 8);
+    p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = IPV6BuildTestPacket(id, 1, 1, 'B', 8);
+    p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
     if (p2 == NULL)
         goto end;
-    p3 = IPV6BuildTestPacket(id, 2, 0, 'C', 3);
+    p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
     if (p3 == NULL)
         goto end;
 
@@ -1378,13 +1378,13 @@
     if (dc == NULL)
         goto end;
 
-    p1 = IPV6BuildTestPacket(id, 0, 1, 'A', 8);
+    p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = IPV6BuildTestPacket(id, 1, 1, 'B', 8);
+    p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
     if (p2 == NULL)
         goto end;
-    p3 = IPV6BuildTestPacket(id, 2, 0, 'C', 3);
+    p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
     if (p3 == NULL)
         goto end;
 
@@ -1452,59 +1452,59 @@
      */
 
     /* A*24 at 0. */
-    packets[0] = BuildTestPacket(id, 0, 1, 'A', 24);
+    packets[0] = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
 
     /* B*15 at 32. */
-    packets[1] = BuildTestPacket(id, 32 >> 3, 1, 'B', 16);
+    packets[1] = BuildTestPacket(IPPROTO_ICMP, id, 32 >> 3, 1, 'B', 16);
 
     /* C*24 at 48. */
-    packets[2] = BuildTestPacket(id, 48 >> 3, 1, 'C', 24);
+    packets[2] = BuildTestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'C', 24);
 
     /* D*8 at 80. */
-    packets[3] = BuildTestPacket(id, 80 >> 3, 1, 'D', 8);
+    packets[3] = BuildTestPacket(IPPROTO_ICMP, id, 80 >> 3, 1, 'D', 8);
 
     /* E*16 at 104. */
-    packets[4] = BuildTestPacket(id, 104 >> 3, 1, 'E', 16);
+    packets[4] = BuildTestPacket(IPPROTO_ICMP, id, 104 >> 3, 1, 'E', 16);
 
     /* F*24 at 120. */
-    packets[5] = BuildTestPacket(id, 120 >> 3, 1, 'F', 24);
+    packets[5] = BuildTestPacket(IPPROTO_ICMP, id, 120 >> 3, 1, 'F', 24);
 
     /* G*16 at 144. */
-    packets[6] = BuildTestPacket(id, 144 >> 3, 1, 'G', 16);
+    packets[6] = BuildTestPacket(IPPROTO_ICMP, id, 144 >> 3, 1, 'G', 16);
 
     /* H*16 at 160. */
-    packets[7] = BuildTestPacket(id, 160 >> 3, 1, 'H', 16);
+    packets[7] = BuildTestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'H', 16);
 
     /* I*8 at 176. */
-    packets[8] = BuildTestPacket(id, 176 >> 3, 1, 'I', 8);
+    packets[8] = BuildTestPacket(IPPROTO_ICMP, id, 176 >> 3, 1, 'I', 8);
 
     /*
      * Overlapping subsequent fragments.
      */
 
     /* J*32 at 8. */
-    packets[9] = BuildTestPacket(id, 8 >> 3, 1, 'J', 32);
+    packets[9] = BuildTestPacket(IPPROTO_ICMP, id, 8 >> 3, 1, 'J', 32);
 
     /* K*24 at 48. */
-    packets[10] = BuildTestPacket(id, 48 >> 3, 1, 'K', 24);
+    packets[10] = BuildTestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'K', 24);
 
     /* L*24 at 72. */
-    packets[11] = BuildTestPacket(id, 72 >> 3, 1, 'L', 24);
+    packets[11] = BuildTestPacket(IPPROTO_ICMP, id, 72 >> 3, 1, 'L', 24);
 
     /* M*24 at 96. */
-    packets[12] = BuildTestPacket(id, 96 >> 3, 1, 'M', 24);
+    packets[12] = BuildTestPacket(IPPROTO_ICMP, id, 96 >> 3, 1, 'M', 24);
 
     /* N*8 at 128. */
-    packets[13] = BuildTestPacket(id, 128 >> 3, 1, 'N', 8);
+    packets[13] = BuildTestPacket(IPPROTO_ICMP, id, 128 >> 3, 1, 'N', 8);
 
     /* O*8 at 152. */
-    packets[14] = BuildTestPacket(id, 152 >> 3, 1, 'O', 8);
+    packets[14] = BuildTestPacket(IPPROTO_ICMP, id, 152 >> 3, 1, 'O', 8);
 
     /* P*8 at 160. */
-    packets[15] = BuildTestPacket(id, 160 >> 3, 1, 'P', 8);
+    packets[15] = BuildTestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'P', 8);
 
     /* Q*16 at 176. */
-    packets[16] = BuildTestPacket(id, 176 >> 3, 0, 'Q', 16);
+    packets[16] = BuildTestPacket(IPPROTO_ICMP, id, 176 >> 3, 0, 'Q', 16);
 
     default_policy = policy;
 
@@ -1587,59 +1587,59 @@
      */
 
     /* A*24 at 0. */
-    packets[0] = IPV6BuildTestPacket(id, 0, 1, 'A', 24);
+    packets[0] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 24);
 
     /* B*15 at 32. */
-    packets[1] = IPV6BuildTestPacket(id, 32 >> 3, 1, 'B', 16);
+    packets[1] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 32 >> 3, 1, 'B', 16);
 
     /* C*24 at 48. */
-    packets[2] = IPV6BuildTestPacket(id, 48 >> 3, 1, 'C', 24);
+    packets[2] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'C', 24);
 
     /* D*8 at 80. */
-    packets[3] = IPV6BuildTestPacket(id, 80 >> 3, 1, 'D', 8);
+    packets[3] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 80 >> 3, 1, 'D', 8);
 
     /* E*16 at 104. */
-    packets[4] = IPV6BuildTestPacket(id, 104 >> 3, 1, 'E', 16);
+    packets[4] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 104 >> 3, 1, 'E', 16);
 
     /* F*24 at 120. */
-    packets[5] = IPV6BuildTestPacket(id, 120 >> 3, 1, 'F', 24);
+    packets[5] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 120 >> 3, 1, 'F', 24);
 
     /* G*16 at 144. */
-    packets[6] = IPV6BuildTestPacket(id, 144 >> 3, 1, 'G', 16);
+    packets[6] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 144 >> 3, 1, 'G', 16);
 
     /* H*16 at 160. */
-    packets[7] = IPV6BuildTestPacket(id, 160 >> 3, 1, 'H', 16);
+    packets[7] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'H', 16);
 
     /* I*8 at 176. */
-    packets[8] = IPV6BuildTestPacket(id, 176 >> 3, 1, 'I', 8);
+    packets[8] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 1, 'I', 8);
 
     /*
      * Overlapping subsequent fragments.
      */
 
     /* J*32 at 8. */
-    packets[9] = IPV6BuildTestPacket(id, 8 >> 3, 1, 'J', 32);
+    packets[9] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 8 >> 3, 1, 'J', 32);
 
     /* K*24 at 48. */
-    packets[10] = IPV6BuildTestPacket(id, 48 >> 3, 1, 'K', 24);
+    packets[10] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'K', 24);
 
     /* L*24 at 72. */
-    packets[11] = IPV6BuildTestPacket(id, 72 >> 3, 1, 'L', 24);
+    packets[11] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 72 >> 3, 1, 'L', 24);
 
     /* M*24 at 96. */
-    packets[12] = IPV6BuildTestPacket(id, 96 >> 3, 1, 'M', 24);
+    packets[12] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 96 >> 3, 1, 'M', 24);
 
     /* N*8 at 128. */
-    packets[13] = IPV6BuildTestPacket(id, 128 >> 3, 1, 'N', 8);
+    packets[13] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 128 >> 3, 1, 'N', 8);
 
     /* O*8 at 152. */
-    packets[14] = IPV6BuildTestPacket(id, 152 >> 3, 1, 'O', 8);
+    packets[14] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 152 >> 3, 1, 'O', 8);
 
     /* P*8 at 160. */
-    packets[15] = IPV6BuildTestPacket(id, 160 >> 3, 1, 'P', 8);
+    packets[15] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'P', 8);
 
     /* Q*16 at 176. */
-    packets[16] = IPV6BuildTestPacket(id, 176 >> 3, 0, 'Q', 16);
+    packets[16] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 0, 'Q', 16);
 
     default_policy = policy;
 
@@ -2125,7 +2125,7 @@
 
     /* Load in 16 packets. */
     for (i = 0; i < 16; i++) {
-        Packet *p = BuildTestPacket(i, 0, 1, 'A' + i, 16);
+        Packet *p = BuildTestPacket(IPPROTO_ICMP,i, 0, 1, 'A' + i, 16);
         if (p == NULL)
             goto end;
 
@@ -2141,7 +2141,7 @@
 
     /* Build a new packet but push the timestamp out by our timeout.
      * This should force our previous fragments to be timed out. */
-    Packet *p = BuildTestPacket(99, 0, 1, 'A' + i, 16);
+    Packet *p = BuildTestPacket(IPPROTO_ICMP, 99, 0, 1, 'A' + i, 16);
     if (p == NULL)
         goto end;
 
@@ -2189,7 +2189,7 @@
         goto end;
 
     /* This packet has an offset > 0, more frags set to 0 and no data. */
-    p = BuildTestPacket(id, 1, 0, 'A', 0);
+    p = BuildTestPacket(IPPROTO_ICMP, id, 1, 0, 'A', 0);
     if (p == NULL)
         goto end;
 
@@ -2228,7 +2228,7 @@
 
     /* Create a fragment that would extend past the max allowable size
      * for an IPv4 packet. */
-    p = BuildTestPacket(1, 8183, 0, 'A', 71);
+    p = BuildTestPacket(IPPROTO_ICMP, 1, 8183, 0, 'A', 71);
     if (p == NULL)
         goto end;
 
@@ -2267,10 +2267,10 @@
 
     DefragInit();
 
-    p1 = BuildTestPacket(1, 0, 1, 'A', 8);
+    p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = BuildTestPacket(1, 1, 0, 'B', 8);
+    p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
     if (p2 == NULL)
         goto end;
 
@@ -2313,10 +2313,10 @@
 
     DefragInit();
 
-    p1 = BuildTestPacket(1, 0, 1, 'A', 8);
+    p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
     if (p1 == NULL)
         goto end;
-    p2 = BuildTestPacket(1, 1, 0, 'B', 8);
+    p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
     if (p2 == NULL)
         goto end;
 
@@ -2361,7 +2361,7 @@
 
     /* Build a packet, its not a fragment but shouldn't matter for
      * this test. */
-    p1 = BuildTestPacket(id, 0, 0, 'A', 8);
+    p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 0, 'A', 8);
     if (p1 == NULL) {
         goto end;
     }
@@ -2431,9 +2431,9 @@
 
     DefragInit();
 
-    Packet *p1 = BuildTestPacket(ip_id, 2, 1, 'C', 8);
-    Packet *p2 = BuildTestPacket(ip_id, 0, 1, 'A', 8);
-    Packet *p3 = BuildTestPacket(ip_id, 1, 0, 'B', 8);
+    Packet *p1 = BuildTestPacket(IPPROTO_ICMP, ip_id, 2, 1, 'C', 8);
+    Packet *p2 = BuildTestPacket(IPPROTO_ICMP, ip_id, 0, 1, 'A', 8);
+    Packet *p3 = BuildTestPacket(IPPROTO_ICMP, ip_id, 1, 0, 'B', 8);
     if (p1 == NULL || p2 == NULL || p3 == NULL) {
         goto end;
     }
@@ -2495,9 +2495,9 @@
 
     DefragInit();
 
-    Packet *p1 = IPV6BuildTestPacket(ip_id, 2, 1, 'C', 8);
-    Packet *p2 = IPV6BuildTestPacket(ip_id, 0, 1, 'A', 8);
-    Packet *p3 = IPV6BuildTestPacket(ip_id, 1, 0, 'B', 8);
+    Packet *p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 2, 1, 'C', 8);
+    Packet *p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 0, 1, 'A', 8);
+    Packet *p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 1, 0, 'B', 8);
     if (p1 == NULL || p2 == NULL || p3 == NULL) {
         goto end;
     }
@@ -2542,6 +2542,39 @@
     return retval;
 }
 
+/**
+ * \brief Test that fragments that match other than the proto don't
+ * actually get matched.
+ */
+static int DefragTestBadProto(void)
+{
+    Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
+    int id = 12;
+
+    DefragInit();
+
+    p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
+    FAIL_IF_NULL(p1);
+    p2 = BuildTestPacket(IPPROTO_UDP, id, 1, 1, 'B', 8);
+    FAIL_IF_NULL(p2);
+    p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
+    FAIL_IF_NULL(p3);
+
+    FAIL_IF_NOT_NULL(Defrag(NULL, NULL, p1, NULL));
+    FAIL_IF_NOT_NULL(Defrag(NULL, NULL, p2, NULL));
+    FAIL_IF_NOT_NULL(Defrag(NULL, NULL, p3, NULL));
+
+    if (p1 != NULL)
+        SCFree(p1);
+    if (p2 != NULL)
+        SCFree(p2);
+    if (p3 != NULL)
+        SCFree(p3);
+
+    DefragDestroy();
+    PASS;
+}
+
 #endif /* UNITTESTS */
 
 void
@@ -2583,6 +2616,7 @@
     UtRegisterTest("DefragTimeoutTest", DefragTimeoutTest);
     UtRegisterTest("DefragMfIpv4Test", DefragMfIpv4Test);
     UtRegisterTest("DefragMfIpv6Test", DefragMfIpv6Test);
+    UtRegisterTest("DefragTestBadProto", DefragTestBadProto);
 #endif /* UNITTESTS */
 }
 
diff -Nru suricata-3.2/src/defrag.h suricata-3.2.1/src/defrag.h
--- suricata-3.2/src/defrag.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/defrag.h	2017-02-15 08:54:12.000000000 +0100
@@ -84,6 +84,8 @@
     uint32_t id; /**< IP ID for this tracker.  32 bits for IPv6, 16
                   * for IPv4. */
 
+    uint8_t proto; /**< IP protocol for this tracker. */
+
     uint8_t policy; /**< Reassembly policy this tracker will use. */
 
     uint8_t af; /**< Address family for this tracker, AF_INET or
diff -Nru suricata-3.2/src/defrag-hash.c suricata-3.2.1/src/defrag-hash.c
--- suricata-3.2/src/defrag-hash.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/defrag-hash.c	2017-02-15 08:54:12.000000000 +0100
@@ -92,6 +92,7 @@
         dt->id = (int32_t)IPV6_EXTHDR_GET_FH_ID(p);
         dt->af = AF_INET6;
     }
+    dt->proto = IP_GET_IPPROTO(p);
     dt->vlan_id[0] = p->vlan_id[0];
     dt->vlan_id[1] = p->vlan_id[1];
     dt->policy = DefragGetOsPolicy(p);
@@ -406,6 +407,7 @@
        CMP_ADDR(&(d1)->dst_addr, &(d2)->dst)) || \
       (CMP_ADDR(&(d1)->src_addr, &(d2)->dst) && \
        CMP_ADDR(&(d1)->dst_addr, &(d2)->src))) && \
+     (d1)->proto == IP_GET_IPPROTO(p) &&        \
      (d1)->id == (id) && \
      (d1)->vlan_id[0] == (d2)->vlan_id[0] && \
      (d1)->vlan_id[1] == (d2)->vlan_id[1])
diff -Nru suricata-3.2/src/detect-app-layer-event.c suricata-3.2.1/src/detect-app-layer-event.c
--- suricata-3.2/src/detect-app-layer-event.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-app-layer-event.c	2017-02-15 08:54:12.000000000 +0100
@@ -46,6 +46,8 @@
 #include "util-unittest-helper.h"
 #include "stream-tcp-util.h"
 
+#define MAX_ALPROTO_NAME 50
+
 static int DetectAppLayerEventPktMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                                        Packet *p, Signature *s, const SigMatchCtx *ctx);
 static int DetectAppLayerEventAppMatch(ThreadVars *, DetectEngineThreadCtx *, Flow *,
@@ -193,10 +195,14 @@
     int event_id = 0;
     const char *p_idx;
     uint8_t ipproto;
-    char alproto_name[50];
+    char alproto_name[MAX_ALPROTO_NAME];
     int r = 0;
 
     p_idx = strchr(data->arg, '.');
+    if (strlen(data->arg) > MAX_ALPROTO_NAME) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword is too long or malformed");
+        return -1;
+    }
     strlcpy(alproto_name, data->arg, p_idx - data->arg + 1);
 
     if (ipproto_bitarray[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8)) {
@@ -227,9 +233,13 @@
     DetectAppLayerEventData *aled;
     AppProto alproto;
     const char *p_idx;
-    char alproto_name[50];
+    char alproto_name[MAX_ALPROTO_NAME];
 
     p_idx = strchr(arg, '.');
+    if (strlen(arg) > MAX_ALPROTO_NAME) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword is too long or malformed");
+        return NULL;
+    }
     /* + 1 for trailing \0 */
     strlcpy(alproto_name, arg, p_idx - arg + 1);
 
diff -Nru suricata-3.2/src/detect.c suricata-3.2.1/src/detect.c
--- suricata-3.2/src/detect.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect.c	2017-02-15 08:54:12.000000000 +0100
@@ -588,6 +588,11 @@
      * the decoder events sgh we have. */
     if (p->proto == 0 && p->events.cnt > 0) {
         SCReturnPtr(de_ctx->decoder_event_sgh, "SigGroupHead");
+    } else if (p->proto == 0) {
+        if (!(PKT_IS_IPV4(p) || PKT_IS_IPV6(p))) {
+            /* not IP, so nothing to do */
+            SCReturnPtr(NULL, "SigGroupHead");
+        }
     }
 
     /* select the flow_gh */
@@ -953,7 +958,7 @@
     if (sgh == NULL || sgh->filestore_cnt == 0) {
         FileDisableStoring(pflow, direction);
     }
-
+#ifdef HAVE_MAGIC
     /* see if this sgh requires us to consider file magic */
     if (!FileForceMagic() && (sgh == NULL ||
                 !(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMAGIC)))
@@ -961,7 +966,7 @@
         SCLogDebug("disabling magic for flow");
         FileDisableMagic(pflow, direction);
     }
-
+#endif
     /* see if this sgh requires us to consider file md5 */
     if (!FileForceMd5() && (sgh == NULL ||
                 !(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMD5)))
@@ -1734,9 +1739,7 @@
     }
 
     if (p->flow) {
-        det_ctx->flow_locked = 1;
         DetectFlow(tv, de_ctx, det_ctx, p);
-        det_ctx->flow_locked = 0;
     } else {
         DetectNoFlow(tv, de_ctx, det_ctx, p);
     }
diff -Nru suricata-3.2/src/detect-csum.c suricata-3.2.1/src/detect-csum.c
--- suricata-3.2/src/detect-csum.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-csum.c	2017-02-15 08:54:12.000000000 +0100
@@ -1544,7 +1544,7 @@
         printf("DetectEngineCtxInit failure\n");
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any any "
diff -Nru suricata-3.2/src/detect-dns-query.c suricata-3.2.1/src/detect-dns-query.c
--- suricata-3.2/src/detect-dns-query.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-dns-query.c	2017-02-15 08:54:12.000000000 +0100
@@ -153,7 +153,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -286,7 +286,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -441,7 +441,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -548,7 +548,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -714,7 +714,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -887,7 +887,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
@@ -1034,7 +1034,7 @@
     if (de_ctx == NULL) {
         goto end;
     }
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
diff -Nru suricata-3.2/src/detect-engine-address.c suricata-3.2.1/src/detect-engine-address.c
--- suricata-3.2/src/detect-engine-address.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-address.c	2017-02-15 08:54:12.000000000 +0100
@@ -959,8 +959,11 @@
 
                 if (DetectAddressParse2(de_ctx, gh, ghn, temp_rule_var_address,
                                     (negate + n_set) % 2, var_list) < 0)
+                {
+                    if (temp_rule_var_address != rule_var_address)
+                        SCFree(temp_rule_var_address);
                     goto error;
-
+                }
                 d_set = 0;
                 n_set = 0;
                 if (temp_rule_var_address != rule_var_address)
diff -Nru suricata-3.2/src/detect-engine-alert.c suricata-3.2.1/src/detect-engine-alert.c
--- suricata-3.2/src/detect-engine-alert.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-alert.c	2017-02-15 08:54:12.000000000 +0100
@@ -327,6 +327,12 @@
      * keyword context for sessions and hosts */
     if (!(p->flags & PKT_PSEUDO_STREAM_END))
         TagHandlePacket(de_ctx, det_ctx, p);
+
+    /* Set flag on flow to indicate that it has alerts */
+    if (p->flow != NULL && p->alerts.cnt > 0) {
+        FlowSetHasAlertsFlag(p->flow);
+    }
+
 }
 
 
diff -Nru suricata-3.2/src/detect-engine.c suricata-3.2.1/src/detect-engine.c
--- suricata-3.2/src/detect-engine.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine.c	2017-02-15 08:54:12.000000000 +0100
@@ -2440,7 +2440,7 @@
     } else {
         DetectEngineCtx *list = master->list;
         for ( ; list != NULL; list = list->next) {
-            SCLogInfo("list %p tenant %u", list, list->tenant_id);
+            SCLogDebug("list %p tenant %u", list, list->tenant_id);
 
             if (list->tenant_id == 0) {
                 minimal_de_ctx = list;
diff -Nru suricata-3.2/src/detect-engine-file.c suricata-3.2.1/src/detect-engine-file.c
--- suricata-3.2/src/detect-engine-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -110,7 +110,7 @@
                 break;
             }
 
-            uint64_t file_size = FileSize(file);
+            uint64_t file_size = FileDataSize(file);
             if ((s->file_flags & FILE_SIG_NEED_MAGIC) && file_size == 0) {
                 SCLogDebug("sig needs file content, but we don't have any");
                 r = DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
diff -Nru suricata-3.2/src/detect-engine-filedata-smtp.c suricata-3.2.1/src/detect-engine-filedata-smtp.c
--- suricata-3.2/src/detect-engine-filedata-smtp.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-filedata-smtp.c	2017-02-15 08:54:12.000000000 +0100
@@ -96,7 +96,7 @@
     const uint8_t *buffer = NULL;
     *buffer_len = 0;
     *stream_start_offset = 0;
-    uint64_t file_size = FileSize(curr_file);
+    uint64_t file_size = FileDataSize(curr_file);
 
     if (det_ctx->smtp_buffers_list_len == 0) {
         if (SMTPCreateSpace(det_ctx, 1) < 0)
@@ -160,7 +160,7 @@
     det_ctx->smtp[index].offset = curr_file->content_inspected;
 
     /* updat inspected tracker */
-    curr_file->content_inspected = FileSize(curr_file);
+    curr_file->content_inspected = FileDataSize(curr_file);
 
     SCLogDebug("content_inspected %u, offset %u", (uint)curr_file->content_inspected, (uint)det_ctx->smtp[index].offset);
 
diff -Nru suricata-3.2/src/detect-engine-mpm.c suricata-3.2.1/src/detect-engine-mpm.c
--- suricata-3.2/src/detect-engine-mpm.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-mpm.c	2017-02-15 08:54:12.000000000 +0100
@@ -343,7 +343,7 @@
 uint16_t PatternMatchDefaultMatcher(void)
 {
     char *mpm_algo;
-    uint16_t mpm_algo_val = DEFAULT_MPM;
+    uint16_t mpm_algo_val = mpm_default_matcher;
 
     /* Get the mpm algo defined in config file by the user */
     if ((ConfGet("mpm-algo", &mpm_algo)) == 1) {
diff -Nru suricata-3.2/src/detect-engine-payload.c suricata-3.2.1/src/detect-engine-payload.c
--- suricata-3.2/src/detect-engine-payload.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-payload.c	2017-02-15 08:54:12.000000000 +0100
@@ -214,7 +214,7 @@
     int result = 0;
 
     char sig[] = "alert tcp any any -> any any (content:\"abc\"; content:\"d\"; distance:0; within:1; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -236,7 +236,7 @@
     int result = 0;
 
     char sig[] = "alert tcp any any -> any any (content:\"abc\"; nocase; content:\"d\"; distance:0; within:1; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -258,7 +258,7 @@
     int result = 0;
 
     char sig[] = "alert tcp any any -> any any (content:\"aBc\"; nocase; content:\"abca\"; distance:-10; within:4; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -283,7 +283,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"this\"; content:\"is\"; within:6; content:\"big\"; within:8; "
         "content:\"string\"; within:8; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -308,7 +308,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"this\"; content:\"is\"; within:9; content:\"big\"; within:12; "
         "content:\"string\"; within:8; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -333,7 +333,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"now\"; content:\"this\"; content:\"is\"; within:12; content:\"big\"; within:8; "
         "content:\"string\"; within:8; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -358,7 +358,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"thus\"; offset:8; content:\"is\"; within:6; content:\"big\"; within:8; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -384,7 +384,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"fix\"; content:\"this\"; within:6; content:!\"and\"; distance:0; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) != 1) {
         goto end;
     }
 
@@ -408,7 +408,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "pcre:/super/; content:\"nova\"; within:7; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -433,7 +433,7 @@
     char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
         "byte_test:4,>,2,0,relative; sid:11;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 1) {
         result = 0;
         goto end;
     }
@@ -458,7 +458,7 @@
     char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
         "byte_jump:1,0,relative; sid:11;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 1) {
         result = 0;
         goto end;
     }
@@ -483,7 +483,7 @@
     char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
         "isdataat:10,relative; sid:11;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 1) {
         result = 0;
         goto end;
     }
@@ -523,7 +523,7 @@
     uint16_t buflen = strlen((char *)buf);
     Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
     int result = 0;
-    uint16_t mpm_type = DEFAULT_MPM;
+    uint16_t mpm_type = mpm_default_matcher;
 
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"aa\"; content:\"aa\"; distance:0; content:\"aa\"; distance:0; "
@@ -605,7 +605,7 @@
 
     //char sig[] = "alert tcp any any -> any any (content:\"User-Agent: Mozilla/5.0 (Macintosh; \"; content:\"Firefox/3.\"; distance:0; content:!\"Firefox/3.6.12\"; distance:-10; content:!\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.6 GTB5\"; sid:1; rev:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 1) {
         goto end;
     }
 
@@ -626,7 +626,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"nova\"; isdataat:18,relative; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -649,7 +649,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "content:\"nova\"; isdataat:!20,relative; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -673,7 +673,7 @@
         "content:\"%\"; depth:4; offset:0; "
         "content:\"%\"; within:2; distance:1; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -702,7 +702,7 @@
         "byte_extract:1,2,one,string,dec,relative; "
         "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -731,7 +731,7 @@
         "byte_extract:1,2,one,string,hex,relative; "
         "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -760,7 +760,7 @@
         "byte_extract:1,2,one,string,dec,relative; "
         "content:\"|06 35 07 08|\"; offset:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -789,7 +789,7 @@
         "byte_extract:1,2,one,string,dec,relative; "
         "content:\"|03 04 05 06|\"; depth:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -818,7 +818,7 @@
         "byte_extract:1,2,one,string,dec,relative; "
         "content:\"|09 0A 0B 0C|\"; within:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -848,7 +848,7 @@
         "byte_extract:1,3,two,string,dec,relative; "
         "byte_test:1,=,one,two,string,dec,relative; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -878,7 +878,7 @@
         "byte_jump:1,one,string,dec,relative; "
         "content:\"|0D 0E 0F|\"; distance:0; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -910,7 +910,7 @@
         "byte_extract:1,-4,one,string,dec,relative; "
         "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -942,7 +942,7 @@
         "byte_extract:1,-3000,one,string,dec,relative; "
         "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) != 0) {
         result = 0;
         goto end;
     }
@@ -970,7 +970,7 @@
         "depth:5; sid:1;)";
 
     p->flags |= PKT_STREAM_ADD;
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 1)
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) != 1)
         goto end;
 
     result = 1;
@@ -996,7 +996,7 @@
         "offset:4; depth:12; sid:1;)";
 
     p->flags |= PKT_STREAM_ADD;
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) != 1)
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) != 1)
         goto end;
 
     result = 1;
@@ -1020,7 +1020,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
         "pcre:/^.{4}/; content:\"nova\"; within:4; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 1) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 1) {
         result = 0;
         goto end;
     }
@@ -1041,7 +1041,7 @@
     int result = 0;
 
     char sig[] = "alert tcp any any -> any any (content:\"one\"; pcre:\"/^two/R\"; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -1062,7 +1062,7 @@
     int result = 0;
 
     char sig[] = "alert tcp any any -> any any (content:\"one\"; pcre:\"/(fiv|^two)/R\"; sid:1;)";
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0) {
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0) {
         result = 0;
         goto end;
     }
@@ -1087,7 +1087,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
         "content:\"message\"; byte_jump:2,-14,string,dec,relative; content:\"card\"; within:4; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0)
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0)
         goto end;
 
     result = 1;
@@ -1110,7 +1110,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
         "content:\"message\"; byte_test:1,=,2,-14,string,dec,relative; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0)
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0)
         goto end;
 
     result = 1;
@@ -1133,7 +1133,7 @@
     char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
         "content:\"message\"; byte_extract:1,-14,boom,string,dec,relative; sid:1;)";
 
-    if (UTHPacketMatchSigMpm(p, sig, DEFAULT_MPM) == 0)
+    if (UTHPacketMatchSigMpm(p, sig, mpm_default_matcher) == 0)
         goto end;
 
     result = 1;
diff -Nru suricata-3.2/src/detect-engine-siggroup.c suricata-3.2.1/src/detect-engine-siggroup.c
--- suricata-3.2/src/detect-engine-siggroup.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-siggroup.c	2017-02-15 08:54:12.000000000 +0100
@@ -321,17 +321,6 @@
     return;
 }
 
-static uint16_t SignatureGetMpmPatternLen(const Signature *s, const int list)
-{
-    if (s->sm_lists[list] != NULL && s->mpm_sm != NULL &&
-        SigMatchListSMBelongsTo(s, s->mpm_sm) == list)
-    {
-        DetectContentData *cd = (DetectContentData *)s->mpm_sm->ctx;
-        return cd->content_len;
-    }
-    return 0;
-}
-
 /**
  * \brief Add a Signature to a SigGroupHead.
  *
@@ -533,6 +522,7 @@
  */
 void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
 {
+#ifdef HAVE_MAGIC
     Signature *s = NULL;
     uint32_t sig = 0;
 
@@ -549,47 +539,11 @@
             break;
         }
     }
-
+#endif
     return;
 }
 
 /**
- *  \brief Get size of the shortest mpm pattern.
- *
- *  \param de_ctx detection engine ctx for the signatures
- *  \param sgh sig group head to set the flag in
- *  \param list sm_list to consider
- */
-uint16_t SigGroupHeadGetMinMpmSize(DetectEngineCtx *de_ctx,
-                                   SigGroupHead *sgh, int list)
-{
-    Signature *s = NULL;
-    uint32_t sig = 0;
-    uint16_t min = USHRT_MAX;
-
-    if (sgh == NULL)
-        return 0;
-
-    for (sig = 0; sig < sgh->sig_cnt; sig++) {
-        s = sgh->match_array[sig];
-        if (s == NULL)
-            continue;
-
-        uint16_t mpm_content_minlen = SignatureGetMpmPatternLen(s, DETECT_SM_LIST_PMATCH);
-        if (mpm_content_minlen > 0) {
-            if (mpm_content_minlen < min)
-                min = mpm_content_minlen;
-            SCLogDebug("mpm_content_minlen %u", mpm_content_minlen);
-        }
-    }
-
-    if (min == USHRT_MAX)
-        min = 0;
-    SCLogDebug("min mpm size %u", min);
-    return min;
-}
-
-/**
  *  \brief Set the need size flag in the sgh.
  *
  *  \param de_ctx detection engine ctx for the signatures
diff -Nru suricata-3.2/src/detect-engine-tls.c suricata-3.2.1/src/detect-engine-tls.c
--- suricata-3.2/src/detect-engine-tls.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-engine-tls.c	2017-02-15 08:54:12.000000000 +0100
@@ -156,7 +156,7 @@
     SCEnter();
 
     return PrefilterAppendTxEngine(sgh, PrefilterTxTlsIssuer,
-        ALPROTO_TLS, 0, // TODO a special 'cert ready' state might be good to add
+        ALPROTO_TLS, TLS_STATE_CERT_READY,
         mpm_ctx, NULL, "tls_cert_issuer");
 }
 
@@ -215,7 +215,7 @@
     const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
     SSLState *ssl_state = f->alstate;
 
-    if (ssl_state->server_connp.cert0_issuerdn == NULL)
+    if (ssl_state->server_connp.cert0_subject == NULL)
         return;
 
     const uint8_t *buffer = (const uint8_t *)ssl_state->server_connp.cert0_subject;
@@ -232,7 +232,7 @@
     SCEnter();
 
     return PrefilterAppendTxEngine(sgh, PrefilterTxTlsSubject,
-        ALPROTO_TLS, 0, // TODO a special 'cert ready' state might be good to add
+        ALPROTO_TLS, TLS_STATE_CERT_READY,
         mpm_ctx, NULL, "tls_cert_subject");
 }
 
diff -Nru suricata-3.2/src/detect-filemagic.c suricata-3.2.1/src/detect-filemagic.c
--- suricata-3.2/src/detect-filemagic.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-filemagic.c	2017-02-15 08:54:12.000000000 +0100
@@ -54,6 +54,27 @@
 
 #include "conf.h"
 
+#ifndef HAVE_MAGIC
+
+static int DetectFilemagicSetupNoSupport (DetectEngineCtx *de_ctx, Signature *s, char *str)
+{
+    SCLogError(SC_ERR_NO_MAGIC_SUPPORT, "no libmagic support built in, needed for filemagic keyword");
+    return -1;
+}
+
+/**
+ * \brief Registration function for keyword: filemagic
+ */
+void DetectFilemagicRegister(void)
+{
+    sigmatch_table[DETECT_FILEMAGIC].name = "filemagic";
+    sigmatch_table[DETECT_FILEMAGIC].desc = "match on the information libmagic returns about a file";
+    sigmatch_table[DETECT_FILEMAGIC].url = "https://redmine.openinfosecfoundation.org/projects/suricata/wiki/File-keywords#filemagic";;
+    sigmatch_table[DETECT_FILEMAGIC].Setup = DetectFilemagicSetupNoSupport;
+}
+
+#else /* HAVE_MAGIC */
+
 static int DetectFilemagicMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *,
         uint8_t, File *, Signature *, SigMatch *);
 static int DetectFilemagicSetup (DetectEngineCtx *, Signature *, char *);
@@ -89,7 +110,7 @@
  */
 int FilemagicGlobalLookup(File *file)
 {
-    if (file == NULL || FileSize(file) == 0) {
+    if (file == NULL || FileDataSize(file) == 0) {
         SCReturnInt(-1);
     }
 
@@ -100,7 +121,7 @@
     StreamingBufferGetData(file->sb,
                            &data, &data_len, &offset);
     if (offset == 0) {
-        if (FileSize(file) >= FILEMAGIC_MIN_SIZE) {
+        if (FileDataSize(file) >= FILEMAGIC_MIN_SIZE) {
             file->magic = MagicGlobalLookup(data, data_len);
         } else if (file->state >= FILE_STATE_CLOSED) {
             file->magic = MagicGlobalLookup(data, data_len);
@@ -120,7 +141,7 @@
  */
 int FilemagicThreadLookup(magic_t *ctx, File *file)
 {
-    if (ctx == NULL || file == NULL || FileSize(file) == 0) {
+    if (ctx == NULL || file == NULL || FileDataSize(file) == 0) {
         SCReturnInt(-1);
     }
 
@@ -131,7 +152,7 @@
     StreamingBufferGetData(file->sb,
                            &data, &data_len, &offset);
     if (offset == 0) {
-        if (FileSize(file) >= FILEMAGIC_MIN_SIZE) {
+        if (FileDataSize(file) >= FILEMAGIC_MIN_SIZE) {
             file->magic = MagicThreadLookup(ctx, data, data_len);
         } else if (file->state >= FILE_STATE_CLOSED) {
             file->magic = MagicThreadLookup(ctx, data, data_len);
@@ -453,3 +474,6 @@
     UtRegisterTest("DetectFilemagicTestParse03", DetectFilemagicTestParse03);
 #endif /* UNITTESTS */
 }
+
+#endif /* HAVE_MAGIC */
+
diff -Nru suricata-3.2/src/detect-filemagic.h suricata-3.2.1/src/detect-filemagic.h
--- suricata-3.2/src/detect-filemagic.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-filemagic.h	2017-02-15 08:54:12.000000000 +0100
@@ -24,8 +24,8 @@
 #ifndef __DETECT_FILEMAGIC_H__
 #define __DETECT_FILEMAGIC_H__
 
+#ifdef HAVE_MAGIC
 #include "util-spm-bm.h"
-#include <magic.h>
 
 typedef struct DetectFilemagicThreadData {
     magic_t ctx;
@@ -40,7 +40,8 @@
 } DetectFilemagicData;
 
 /* prototypes */
-void DetectFilemagicRegister (void);
 int FilemagicGlobalLookup(File *file);
+#endif
+void DetectFilemagicRegister (void);
 
 #endif /* __DETECT_FILEMAGIC_H__ */
diff -Nru suricata-3.2/src/detect-filesize.c suricata-3.2.1/src/detect-filesize.c
--- suricata-3.2/src/detect-filesize.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-filesize.c	2017-02-15 08:54:12.000000000 +0100
@@ -93,7 +93,7 @@
 
     DetectFilesizeData *fsd = (DetectFilesizeData *)m->ctx;
     int ret = 0;
-    uint64_t file_size = FileSize(file);
+    uint64_t file_size = FileTrackedSize(file);
 
     SCLogDebug("file size %"PRIu64", check %"PRIu64, file_size, fsd->size1);
 
diff -Nru suricata-3.2/src/detect.h suricata-3.2.1/src/detect.h
--- suricata-3.2/src/detect.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect.h	2017-02-15 08:54:12.000000000 +0100
@@ -838,10 +838,6 @@
     /* counter for the filestore array below -- up here for cache reasons. */
     uint16_t filestore_cnt;
 
-    /* bool to hint the POSTMATCH list members about the lock status of the
-     * flow. If locked this is TRUE, unlocked or no-flow: FALSE */
-    uint8_t flow_locked;
-
     HttpReassembledBody *hsbd;
     uint64_t hsbd_start_tx_id;
     uint16_t hsbd_buffers_size;
@@ -999,7 +995,9 @@
 
 } SigTableElmt;
 
+#ifdef HAVE_MAGIC
 #define SIG_GROUP_HEAD_HAVEFILEMAGIC    (1 << 20)
+#endif
 #define SIG_GROUP_HEAD_HAVEFILEMD5      (1 << 21)
 #define SIG_GROUP_HEAD_HAVEFILESIZE     (1 << 22)
 #define SIG_GROUP_HEAD_HAVEFILESHA1     (1 << 23)
diff -Nru suricata-3.2/src/detect-http-header.c suricata-3.2.1/src/detect-http-header.c
--- suricata-3.2/src/detect-http-header.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-http-header.c	2017-02-15 08:54:12.000000000 +0100
@@ -724,7 +724,7 @@
         goto end;
 
     de_ctx->flags |= DE_QUIET;
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
 
     de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                "(msg:\"http header test\"; "
diff -Nru suricata-3.2/src/detect-ipproto.c suricata-3.2.1/src/detect-ipproto.c
--- suricata-3.2/src/detect-ipproto.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-ipproto.c	2017-02-15 08:54:12.000000000 +0100
@@ -9281,7 +9281,7 @@
         goto end;
     }
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     de_ctx->sig_list = SigInit(de_ctx,
@@ -9366,7 +9366,7 @@
         goto end;
     }
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     de_ctx->sig_list = SigInit(de_ctx,
diff -Nru suricata-3.2/src/detect-parse.c suricata-3.2.1/src/detect-parse.c
--- suricata-3.2/src/detect-parse.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-parse.c	2017-02-15 08:54:12.000000000 +0100
@@ -104,11 +104,7 @@
                            ")"
 
 /* if enclosed in [], spaces are allowed */
-#define CONFIG_PCRE_PORT   "(" \
-                            "[\\:A-z0-9_\\$\\!,]+"\
-                           "|"\
-                            "\\[[\\:A-z0-9_\\$\\!,\\s]+\\]"\
-                           ")"
+#define CONFIG_PCRE_PORT   "([\\[\\]\\:A-z0-9_\\$\\!,\\s]+)"
 
 /* format: action space(s) protocol spaces(s) src space(s) sp spaces(s) dir spaces(s) dst spaces(s) dp spaces(s) options */
 #define CONFIG_PCRE "^([A-z]+)\\s+([A-z0-9\\-]+)\\s+" \
diff -Nru suricata-3.2/src/detect-tls-cert-issuer.c suricata-3.2.1/src/detect-tls-cert-issuer.c
--- suricata-3.2/src/detect-tls-cert-issuer.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-tls-cert-issuer.c	2017-02-15 08:54:12.000000000 +0100
@@ -63,6 +63,7 @@
 {
     sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].name = "tls_cert_issuer";
     sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].desc = "content modifier to match specifically and only on the TLS cert issuer buffer";
+    sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-cert-issuer";
     sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].Match = NULL;
     sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].AppLayerMatch = NULL;
     sigmatch_table[DETECT_AL_TLS_CERT_ISSUER].Setup = DetectTlsIssuerSetup;
@@ -387,7 +388,7 @@
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
diff -Nru suricata-3.2/src/detect-tls-cert-subject.c suricata-3.2.1/src/detect-tls-cert-subject.c
--- suricata-3.2/src/detect-tls-cert-subject.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-tls-cert-subject.c	2017-02-15 08:54:12.000000000 +0100
@@ -63,6 +63,7 @@
 {
     sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].name = "tls_cert_subject";
     sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].desc = "content modifier to match specifically and only on the TLS cert subject buffer";
+    sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-cert-subject";
     sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].Match = NULL;
     sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].AppLayerMatch = NULL;
     sigmatch_table[DETECT_AL_TLS_CERT_SUBJECT].Setup = DetectTlsSubjectSetup;
@@ -387,7 +388,7 @@
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
diff -Nru suricata-3.2/src/detect-tls-sni.c suricata-3.2.1/src/detect-tls-sni.c
--- suricata-3.2/src/detect-tls-sni.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-tls-sni.c	2017-02-15 08:54:12.000000000 +0100
@@ -63,6 +63,7 @@
 {
     sigmatch_table[DETECT_AL_TLS_SNI].name = "tls_sni";
     sigmatch_table[DETECT_AL_TLS_SNI].desc = "content modifier to match specifically and only on the TLS SNI buffer";
+    sigmatch_table[DETECT_AL_TLS_SNI].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-sni";
     sigmatch_table[DETECT_AL_TLS_SNI].Match = NULL;
     sigmatch_table[DETECT_AL_TLS_SNI].AppLayerMatch = NULL;
     sigmatch_table[DETECT_AL_TLS_SNI].Setup = DetectTlsSniSetup;
@@ -156,7 +157,7 @@
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
@@ -248,7 +249,7 @@
     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
-    de_ctx->mpm_matcher = DEFAULT_MPM;
+    de_ctx->mpm_matcher = mpm_default_matcher;
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
diff -Nru suricata-3.2/src/detect-xbits.c suricata-3.2.1/src/detect-xbits.c
--- suricata-3.2/src/detect-xbits.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-xbits.c	2017-02-15 08:54:12.000000000 +0100
@@ -66,7 +66,7 @@
 {
     sigmatch_table[DETECT_XBITS].name = "xbits";
     sigmatch_table[DETECT_XBITS].desc = "operate on bits";
-//    sigmatch_table[DETECT_XBITS].url = DOC_URL DOC_VERSION "/rules/flow-keywords.html#flowbits";
+    sigmatch_table[DETECT_XBITS].url = DOC_URL DOC_VERSION "/rules/xbits.html";
     sigmatch_table[DETECT_XBITS].Match = DetectXbitMatch;
     sigmatch_table[DETECT_XBITS].Setup = DetectXbitSetup;
     sigmatch_table[DETECT_XBITS].Free  = DetectXbitFree;
@@ -180,10 +180,16 @@
     return 0;
 }
 
-int DetectXbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
+/** \internal
+ *  \brief parse xbits rule options
+ *  \retval 0 ok
+ *  \retval -1 bad
+ *  \param[out] cdout return DetectXbitsData structure or NULL if noalert
+ */
+static int DetectXbitParse(DetectEngineCtx *de_ctx,
+        const char *rawstr, DetectXbitsData **cdout)
 {
     DetectXbitsData *cd = NULL;
-    SigMatch *sm = NULL;
     uint8_t fb_cmd = 0;
     uint8_t hb_dir = 0;
 #define MAX_SUBSTRINGS 30
@@ -192,7 +198,7 @@
     char fb_cmd_str[16] = "", fb_name[256] = "";
     char hb_dir_str[16] = "";
     enum VarTypes var_type = VAR_TYPE_NOT_SET;
-    int expire = 30;
+    int expire = DETECT_XBITS_EXPIRE_DEFAULT;
 
     ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
     if (ret != 2 && ret != 3 && ret != 4 && ret != 5) {
@@ -210,13 +216,13 @@
         res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, fb_name, sizeof(fb_name));
         if (res < 0) {
             SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
-            goto error;
+            return -1;
         }
         if (ret >= 4) {
             res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, hb_dir_str, sizeof(hb_dir_str));
             if (res < 0) {
                 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
-                goto error;
+                return -1;
             }
             SCLogDebug("hb_dir_str %s", hb_dir_str);
             if (strlen(hb_dir_str) > 0) {
@@ -231,7 +237,7 @@
                     var_type = VAR_TYPE_IPPAIR_BIT;
                 } else {
                     // TODO
-                    goto error;
+                    return -1;
                 }
             }
 
@@ -240,10 +246,19 @@
                 res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 4, expire_str, sizeof(expire_str));
                 if (res < 0) {
                     SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
-                    goto error;
+                    return -1;
                 }
                 SCLogDebug("expire_str %s", expire_str);
                 expire = atoi(expire_str);
+                if (expire < 0) {
+                    SCLogError(SC_ERR_INVALID_VALUE, "expire must be positive. "
+                            "Got %d (\"%s\")", expire, expire_str);
+                    return -1;
+                }
+                if (expire == 0) {
+                    SCLogError(SC_ERR_INVALID_VALUE, "expire must be bigger than 0");
+                    return -1;
+                }
                 SCLogDebug("expire %d", expire);
             }
         }
@@ -262,16 +277,18 @@
     } else if (strcmp(fb_cmd_str,"toggle") == 0) {
         fb_cmd = DETECT_XBITS_CMD_TOGGLE;
     } else {
-        SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
-        goto error;
+        SCLogError(SC_ERR_UNKNOWN_VALUE, "xbits action \"%s\" is not supported.", fb_cmd_str);
+        return -1;
     }
 
     switch (fb_cmd) {
-        case DETECT_XBITS_CMD_NOALERT:
+        case DETECT_XBITS_CMD_NOALERT: {
             if (strlen(fb_name) != 0)
-                goto error;
-            s->flags |= SIG_FLAG_NOALERT;
+                return -1;
+            /* return ok, cd is NULL. Flag sig. */
+            *cdout = NULL;
             return 0;
+        }
         case DETECT_XBITS_CMD_ISNOTSET:
         case DETECT_XBITS_CMD_ISSET:
         case DETECT_XBITS_CMD_SET:
@@ -279,13 +296,13 @@
         case DETECT_XBITS_CMD_TOGGLE:
         default:
             if (strlen(fb_name) == 0)
-                goto error;
+                return -1;
             break;
     }
 
     cd = SCMalloc(sizeof(DetectXbitsData));
     if (unlikely(cd == NULL))
-        goto error;
+        return -1;
 
     cd->idx = VariableNameGetIdx(de_ctx, fb_name, var_type);
     cd->cmd = fb_cmd;
@@ -296,6 +313,24 @@
     SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
         cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)");
 
+    *cdout = cd;
+    return 0;
+}
+
+int DetectXbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
+{
+    SigMatch *sm = NULL;
+    DetectXbitsData *cd = NULL;
+
+    int result = DetectXbitParse(de_ctx, rawstr, &cd);
+    if (result < 0) {
+        return -1;
+    /* noalert doesn't use a cd/sm struct. It flags the sig. We're done. */
+    } else if (result == 0 && cd == NULL) {
+        s->flags |= SIG_FLAG_NOALERT;
+        return 0;
+    }
+
     /* Okay so far so good, lets get this into a SigMatch
      * and put it in the Signature. */
     sm = SigMatchAlloc();
@@ -305,7 +340,7 @@
     sm->type = DETECT_XBITS;
     sm->ctx = (void *)cd;
 
-    switch (fb_cmd) {
+    switch (cd->cmd) {
         /* case DETECT_XBITS_CMD_NOALERT can't happen here */
 
         case DETECT_XBITS_CMD_ISNOTSET:
@@ -327,8 +362,6 @@
 error:
     if (cd != NULL)
         SCFree(cd);
-    if (sm != NULL)
-        SCFree(sm);
     return -1;
 }
 
@@ -361,11 +394,59 @@
     StorageCleanup();
 }
 
+
+static int XBitsTestParse01(void)
+{
+    DetectEngineCtx *de_ctx = NULL;
+    de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+    de_ctx->flags |= DE_QUIET;
+    DetectXbitsData *cd = NULL;
+
+#define BAD_INPUT(str) \
+    FAIL_IF_NOT(DetectXbitParse(de_ctx, (str), &cd) == -1);
+
+    BAD_INPUT("alert");
+    BAD_INPUT("n0alert");
+    BAD_INPUT("nOalert");
+    BAD_INPUT("set,abc,track nonsense, expire 3600");
+    BAD_INPUT("set,abc,track ip_source, expire 3600");
+    BAD_INPUT("set,abc,track ip_src, expire -1");
+    BAD_INPUT("set,abc,track ip_src, expire 0");
+
+#undef BAD_INPUT
+
+#define GOOD_INPUT(str, command, trk, typ, exp)             \
+    FAIL_IF_NOT(DetectXbitParse(de_ctx, (str), &cd) == 0);  \
+    FAIL_IF_NULL(cd);                                       \
+    FAIL_IF_NOT(cd->cmd == (command));                      \
+    FAIL_IF_NOT(cd->tracker == (trk));                      \
+    FAIL_IF_NOT(cd->type == (typ));                         \
+    FAIL_IF_NOT(cd->expire == (exp));                       \
+    DetectXbitFree(cd);                                     \
+    cd = NULL;
+
+    GOOD_INPUT("set,abc,track ip_pair",
+            DETECT_XBITS_CMD_SET,
+            DETECT_XBITS_TRACK_IPPAIR, VAR_TYPE_IPPAIR_BIT,
+            DETECT_XBITS_EXPIRE_DEFAULT);
+    GOOD_INPUT("set,abc,track ip_pair, expire 3600",
+            DETECT_XBITS_CMD_SET,
+            DETECT_XBITS_TRACK_IPPAIR, VAR_TYPE_IPPAIR_BIT,
+            3600);
+    GOOD_INPUT("set,abc,track ip_src, expire 1234",
+            DETECT_XBITS_CMD_SET,
+            DETECT_XBITS_TRACK_IPSRC, VAR_TYPE_HOST_BIT,
+            1234);
+
+#undef GOOD_INPUT
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
 /**
- * \test HostBitsTestSig01 is a test for a valid noalert flowbits option
- *
- *  \retval 1 on succces
- *  \retval 0 on failure
+ * \test
  */
 
 static int XBitsTestSig01(void)
@@ -376,13 +457,11 @@
                     "\r\n";
     uint16_t buflen = strlen((char *)buf);
     Packet *p = SCMalloc(SIZE_OF_PACKET);
-    if (unlikely(p == NULL))
-        return 0;
+    FAIL_IF_NULL(p);
     Signature *s = NULL;
     ThreadVars th_v;
     DetectEngineThreadCtx *det_ctx = NULL;
     DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
 
     memset(&th_v, 0, sizeof(th_v));
     memset(p, 0, SIZE_OF_PACKET);
@@ -395,46 +474,23 @@
     XBitsTestSetup();
 
     de_ctx = DetectEngineCtxInit();
-
-    if (de_ctx == NULL) {
-        printf("bad de_ctx: ");
-        goto end;
-    }
-
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:set,abc,track ip_pair; content:\"GET \"; sid:1;)");
-    if (s == NULL) {
-        printf("bad sig: ");
-        goto end;
-    }
+    FAIL_IF_NULL(s);
 
     SigGroupBuild(de_ctx);
     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
-
     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
-
-    result = 1;
-
-end:
-    if (de_ctx != NULL) {
-        SigGroupCleanup(de_ctx);
-        SigCleanSignatures(de_ctx);
-    }
-
-    if (det_ctx != NULL) {
-        DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
-    }
-
-    if (de_ctx != NULL) {
-        DetectEngineCtxFree(de_ctx);
-    }
-
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
     XBitsTestShutdown();
-
     SCFree(p);
-    return result;
+    StatsThreadCleanup(&th_v);
+    StatsReleaseResources();
+    PASS;
 }
 
 /**
@@ -447,67 +503,33 @@
 static int XBitsTestSig02(void)
 {
     Signature *s = NULL;
-    ThreadVars th_v;
     DetectEngineCtx *de_ctx = NULL;
-    int result = 0;
-    int error_count = 0;
-
-    memset(&th_v, 0, sizeof(th_v));
-
     de_ctx = DetectEngineCtxInit();
-    if (de_ctx == NULL) {
-        goto end;
-    }
-
+    FAIL_IF_NULL(de_ctx);
     de_ctx->flags |= DE_QUIET;
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:isset,abc,track ip_src; content:\"GET \"; sid:1;)");
-    if (s == NULL) {
-        error_count++;
-    }
+    FAIL_IF_NULL(s);
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:isnotset,abc,track ip_dst; content:\"GET \"; sid:2;)");
-    if (s == NULL) {
-        error_count++;
-    }
+    FAIL_IF_NULL(s);
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:set,abc,track ip_pair; content:\"GET \"; sid:3;)");
-    if (s == NULL) {
-        error_count++;
-    }
+    FAIL_IF_NULL(s);
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:unset,abc,track ip_src; content:\"GET \"; sid:4;)");
-    if (s == NULL) {
-        error_count++;
-    }
+    FAIL_IF_NULL(s);
 
     s = DetectEngineAppendSig(de_ctx,
             "alert ip any any -> any any (xbits:toggle,abc,track ip_dst; content:\"GET \"; sid:5;)");
-    if (s == NULL) {
-        error_count++;
-    }
+    FAIL_IF_NULL(s);
 
-    if (error_count != 0)
-        goto end;
-
-    result = 1;
-
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
     DetectEngineCtxFree(de_ctx);
-    return result;
-end:
-    if (de_ctx != NULL) {
-        SigGroupCleanup(de_ctx);
-        SigCleanSignatures(de_ctx);
-        DetectEngineCtxFree(de_ctx);
-    }
-
-    return result;
+    PASS;
 }
 
 #endif /* UNITTESTS */
@@ -518,6 +540,7 @@
 void XBitsRegisterTests(void)
 {
 #ifdef UNITTESTS
+    UtRegisterTest("XBitsTestParse01", XBitsTestParse01);
     UtRegisterTest("XBitsTestSig01", XBitsTestSig01);
     UtRegisterTest("XBitsTestSig02", XBitsTestSig02);
 #endif /* UNITTESTS */
diff -Nru suricata-3.2/src/detect-xbits.h suricata-3.2.1/src/detect-xbits.h
--- suricata-3.2/src/detect-xbits.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/detect-xbits.h	2017-02-15 08:54:12.000000000 +0100
@@ -37,6 +37,8 @@
 #define DETECT_XBITS_TRACK_IPPAIR 2
 #define DETECT_XBITS_TRACK_FLOW   3
 
+#define DETECT_XBITS_EXPIRE_DEFAULT 30
+
 typedef struct DetectXbitsData_ {
     uint16_t idx;
     uint8_t cmd;
diff -Nru suricata-3.2/src/flow.c suricata-3.2.1/src/flow.c
--- suricata-3.2/src/flow.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/flow.c	2017-02-15 08:54:12.000000000 +0100
@@ -157,6 +157,30 @@
     return;
 }
 
+/** \brief Set flag to indicate that flow has alerts
+ *
+ * \param f flow
+ */
+void FlowSetHasAlertsFlag(Flow *f)
+{
+    f->flags |= FLOW_HAS_ALERTS;
+}
+
+/** \brief Check if flow has alerts
+ *
+ * \param f flow
+ * \retval 1 has alerts
+ * \retval 0 has not alerts
+ */
+int FlowHasAlerts(const Flow *f)
+{
+    if (f->flags & FLOW_HAS_ALERTS) {
+        return 1;
+    }
+
+    return 0;
+}
+
 /**
  *  \brief determine the direction of the packet compared to the flow
  *  \retval 0 to_server
diff -Nru suricata-3.2/src/flow.h suricata-3.2.1/src/flow.h
--- suricata-3.2/src/flow.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/flow.h	2017-02-15 08:54:12.000000000 +0100
@@ -72,7 +72,8 @@
 /** packet to client direction has been logged in drop file (only in IPS mode) */
 #define FLOW_TOCLIENT_DROP_LOGGED       BIT_U32(11)
 
-// vacancy bit 12
+/** flow has alerts */
+#define FLOW_HAS_ALERTS                 BIT_U32(12)
 
 /** Pattern matcher alproto detection done */
 #define FLOW_TS_PM_ALPROTO_DETECT_DONE  BIT_U32(13)
@@ -458,6 +459,8 @@
 void FlowPrintQueueInfo (void);
 void FlowShutdown(void);
 void FlowSetIPOnlyFlag(Flow *, int);
+void FlowSetHasAlertsFlag(Flow *);
+int FlowHasAlerts(const Flow *);
 
 void FlowRegisterTests (void);
 int FlowSetProtoTimeout(uint8_t ,uint32_t ,uint32_t ,uint32_t);
diff -Nru suricata-3.2/src/host-bit.c suricata-3.2.1/src/host-bit.c
--- suricata-3.2/src/host-bit.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/host-bit.c	2017-02-15 08:54:12.000000000 +0100
@@ -123,6 +123,7 @@
     GenericVar *gv = HostGetStorageById(h, host_bit_id);
     if (gv) {
         GenericVarRemove(&gv, (GenericVar *)fb);
+        XBitFree(fb);
         HostSetStorageById(h, host_bit_id, gv);
     }
 }
diff -Nru suricata-3.2/src/log-dnslog.c suricata-3.2.1/src/log-dnslog.c
--- suricata-3.2/src/log-dnslog.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/log-dnslog.c	2017-02-15 08:54:12.000000000 +0100
@@ -138,11 +138,11 @@
                 " [**] %s [**] TTL %u [**] ", record, entry->ttl);
 
         uint8_t *ptr = (uint8_t *)((uint8_t *)entry + sizeof(DNSAnswerEntry) + entry->fqdn_len);
-        if (entry->type == DNS_RECORD_TYPE_A) {
+        if (entry->type == DNS_RECORD_TYPE_A && entry->data_len == 4) {
             char a[16] = "";
             PrintInet(AF_INET, (const void *)ptr, a, sizeof(a));
             MemBufferWriteString(aft->buffer, "%s", a);
-        } else if (entry->type == DNS_RECORD_TYPE_AAAA) {
+        } else if (entry->type == DNS_RECORD_TYPE_AAAA && entry->data_len == 16) {
             char a[46];
             PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a));
             MemBufferWriteString(aft->buffer, "%s", a);
@@ -165,8 +165,8 @@
     SCMutexUnlock(&hlog->file_ctx->fp_mutex);
 }
 
-static int LogDnsLogger(ThreadVars *tv, void *data, const Packet *p, Flow *f,
-    void *state, void *tx, uint64_t tx_id)
+static int LogDnsLogger(ThreadVars *tv, void *data, const Packet *p,
+    Flow *f, void *state, void *tx, uint64_t tx_id, uint8_t direction)
 {
     LogDnsLogThread *aft = (LogDnsLogThread *)data;
     DNSTransaction *dns_tx = (DNSTransaction *)tx;
@@ -214,24 +214,26 @@
         dp = p->sp;
     }
 
-    DNSQueryEntry *query = NULL;
-    TAILQ_FOREACH(query, &dns_tx->query_list, next) {
-        LogQuery(aft, timebuf, dstip, srcip, dp, sp, dns_tx, query);
-    }
-
-    if (dns_tx->rcode)
-        LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, NULL);
-    if (dns_tx->recursion_desired)
-        LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, NULL);
-
-    DNSAnswerEntry *entry = NULL;
-    TAILQ_FOREACH(entry, &dns_tx->answer_list, next) {
-        LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, entry);
-    }
+    if (direction == STREAM_TOSERVER) {
+        DNSQueryEntry *query = NULL;
+        TAILQ_FOREACH(query, &dns_tx->query_list, next) {
+            LogQuery(aft, timebuf, dstip, srcip, dp, sp, dns_tx, query);
+        }
+    } else if (direction == STREAM_TOCLIENT) {
+        if (dns_tx->rcode)
+            LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, NULL);
+        if (dns_tx->recursion_desired)
+            LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, NULL);
+
+        DNSAnswerEntry *entry = NULL;
+        TAILQ_FOREACH(entry, &dns_tx->answer_list, next) {
+            LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, entry);
+        }
 
-    entry = NULL;
-    TAILQ_FOREACH(entry, &dns_tx->authority_list, next) {
-        LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, entry);
+        entry = NULL;
+        TAILQ_FOREACH(entry, &dns_tx->authority_list, next) {
+            LogAnswer(aft, timebuf, srcip, dstip, sp, dp, dns_tx, entry);
+        }
     }
 
     aft->dns_cnt++;
@@ -239,6 +241,18 @@
     return 0;
 }
 
+static int LogDnsRequestLogger(ThreadVars *tv, void *data, const Packet *p,
+    Flow *f, void *state, void *tx, uint64_t tx_id)
+{
+    return LogDnsLogger(tv, data, p, f, state, tx, tx_id, STREAM_TOSERVER);
+}
+
+static int LogDnsResponseLogger(ThreadVars *tv, void *data, const Packet *p,
+    Flow *f, void *state, void *tx, uint64_t tx_id)
+{
+    return LogDnsLogger(tv, data, p, f, state, tx, tx_id, STREAM_TOCLIENT);
+}
+
 static TmEcode LogDnsLogThreadInit(ThreadVars *t, void *initdata, void **data)
 {
     LogDnsLogThread *aft = SCMalloc(sizeof(LogDnsLogThread));
@@ -346,9 +360,15 @@
 
 void LogDnsLogRegister (void)
 {
-    OutputRegisterTxModule(LOGGER_DNS, MODULE_NAME, "dns-log", LogDnsLogInitCtx,
-        ALPROTO_DNS, LogDnsLogger, LogDnsLogThreadInit, LogDnsLogThreadDeinit,
-        LogDnsLogExitPrintStats);
+    /* Request logger. */
+    OutputRegisterTxModuleWithProgress(LOGGER_DNS, MODULE_NAME, "dns-log",
+        LogDnsLogInitCtx, ALPROTO_DNS, LogDnsRequestLogger, 0, 1,
+        LogDnsLogThreadInit, LogDnsLogThreadDeinit, LogDnsLogExitPrintStats);
+
+    /* Response logger. */
+    OutputRegisterTxModuleWithProgress(LOGGER_DNS, MODULE_NAME, "dns-log",
+        LogDnsLogInitCtx, ALPROTO_DNS, LogDnsResponseLogger, 1, 1,
+        LogDnsLogThreadInit, LogDnsLogThreadDeinit, LogDnsLogExitPrintStats);
 
     /* enable the logger for the app layer */
     SCLogDebug("registered %s", MODULE_NAME);
diff -Nru suricata-3.2/src/log-file.c suricata-3.2.1/src/log-file.c
--- suricata-3.2/src/log-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/log-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -269,7 +269,7 @@
     fprintf(fp, "\"filename\": \"");
     PrintRawJsonFp(fp, ff->name, ff->name_len);
     fprintf(fp, "\", ");
-
+#ifdef HAVE_MAGIC
     fprintf(fp, "\"magic\": \"");
     if (ff->magic) {
         PrintRawJsonFp(fp, (uint8_t *)ff->magic, strlen(ff->magic));
@@ -277,7 +277,7 @@
         fprintf(fp, "unknown");
     }
     fprintf(fp, "\", ");
-
+#endif
     switch (ff->state) {
         case FILE_STATE_CLOSED:
             fprintf(fp, "\"state\": \"CLOSED\", ");
@@ -319,7 +319,7 @@
             break;
     }
     fprintf(fp, "\"stored\": %s, ", ff->flags & FILE_STORED ? "true" : "false");
-    fprintf(fp, "\"size\": %"PRIu64" ", FileSize(ff));
+    fprintf(fp, "\"size\": %"PRIu64" ", FileTrackedSize(ff));
     fprintf(fp, "}\n");
     fflush(fp);
     SCMutexUnlock(&aft->file_ctx->fp_mutex);
diff -Nru suricata-3.2/src/log-filestore.c suricata-3.2.1/src/log-filestore.c
--- suricata-3.2/src/log-filestore.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/log-filestore.c	2017-02-15 08:54:12.000000000 +0100
@@ -247,9 +247,10 @@
     snprintf(metafilename, sizeof(metafilename), "%s.meta", filename);
     FILE *fp = fopen(metafilename, "a");
     if (fp != NULL) {
+#ifdef HAVE_MAGIC
         fprintf(fp, "MAGIC:             %s\n",
                 ff->magic ? ff->magic : "<unknown>");
-
+#endif
         switch (ff->state) {
             case FILE_STATE_CLOSED:
                 fprintf(fp, "STATE:             CLOSED\n");
@@ -290,7 +291,7 @@
                 fprintf(fp, "STATE:             UNKNOWN\n");
                 break;
         }
-        fprintf(fp, "SIZE:              %"PRIu64"\n", FileSize(ff));
+        fprintf(fp, "SIZE:              %"PRIu64"\n", FileTrackedSize(ff));
 
         fclose(fp);
     } else {
diff -Nru suricata-3.2/src/log-pcap.c suricata-3.2.1/src/log-pcap.c
--- suricata-3.2/src/log-pcap.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/log-pcap.c	2017-02-15 08:54:12.000000000 +0100
@@ -82,6 +82,8 @@
 #define HONOR_PASS_RULES_DISABLED       0
 #define HONOR_PASS_RULES_ENABLED        1
 
+#define PCAP_SNAPLEN                    262144
+
 SC_ATOMIC_DECLARE(uint32_t, thread_cnt);
 
 typedef struct PcapFileName_ {
@@ -317,7 +319,7 @@
 
     if (pl->pcap_dead_handle == NULL) {
         if ((pl->pcap_dead_handle = pcap_open_dead(p->datalink,
-                        -1)) == NULL) {
+                        PCAP_SNAPLEN)) == NULL) {
             SCLogDebug("Error opening dead pcap handle");
             return TM_ECODE_FAILED;
         }
@@ -669,6 +671,7 @@
                     strerror(errno));
             }
             TAILQ_REMOVE(&pl->pcap_file_list, pf, next);
+            PcapFileNameFree(pf);
             pf = TAILQ_FIRST(&pl->pcap_file_list);
             pl->file_cnt--;
         }
@@ -959,7 +962,7 @@
             timestamp_pattern, pcre_erroffset, pcre_errbuf);
     }
     pcre_timestamp_extra = pcre_study(pcre_timestamp_code, 0, &pcre_errbuf);
-    if (pcre_timestamp_extra == NULL) {
+    if (pcre_errbuf != NULL) {
         FatalError(SC_ERR_PCRE_STUDY, "Fail to study pcre: %s", pcre_errbuf);
     }
 
diff -Nru suricata-3.2/src/log-tlsstore.c suricata-3.2.1/src/log-tlsstore.c
--- suricata-3.2/src/log-tlsstore.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/log-tlsstore.c	2017-02-15 08:54:12.000000000 +0100
@@ -166,7 +166,6 @@
             goto end_fwrite_fp;
     }
     fclose(fp);
-    SCFree(aft->enc_buf);
 
     //Logging certificate informations
     memcpy(filename + (strlen(filename) - 3), "meta", 4);
@@ -223,7 +222,6 @@
 
 end_fwrite_fp:
     fclose(fp);
-    SCFree(aft->enc_buf);
     if (logging_dir_not_writable < LOGGING_WRITE_ISSUE_LIMIT) {
         SCLogWarning(SC_ERR_FWRITE, "Unable to write certificate");
         logging_dir_not_writable++;
@@ -338,6 +336,9 @@
         return TM_ECODE_OK;
     }
 
+    if (aft->enc_buf != NULL)
+        SCFree(aft->enc_buf);
+
     /* clear memory */
     memset(aft, 0, sizeof(LogTlsStoreLogThread));
 
diff -Nru suricata-3.2/src/Makefile.am suricata-3.2.1/src/Makefile.am
--- suricata-3.2/src/Makefile.am	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/Makefile.am	2017-02-15 08:54:12.000000000 +0100
@@ -46,6 +46,7 @@
 counters.c counters.h \
 data-queue.c data-queue.h \
 decode.c decode.h \
+decode-afl.c \
 decode-erspan.c decode-erspan.h \
 decode-ethernet.c decode-ethernet.h \
 decode-events.c decode-events.h \
diff -Nru suricata-3.2/src/Makefile.in suricata-3.2.1/src/Makefile.in
--- suricata-3.2/src/Makefile.in	2016-11-29 18:17:05.000000000 +0100
+++ suricata-3.2.1/src/Makefile.in	2017-02-15 08:54:31.000000000 +0100
@@ -127,20 +127,20 @@
 	app-layer-ssh.$(OBJEXT) app-layer-ssl.$(OBJEXT) \
 	app-layer-tls-handshake.$(OBJEXT) conf.$(OBJEXT) \
 	conf-yaml-loader.$(OBJEXT) counters.$(OBJEXT) \
-	data-queue.$(OBJEXT) decode.$(OBJEXT) decode-erspan.$(OBJEXT) \
-	decode-ethernet.$(OBJEXT) decode-events.$(OBJEXT) \
-	decode-gre.$(OBJEXT) decode-icmpv4.$(OBJEXT) \
-	decode-icmpv6.$(OBJEXT) decode-ipv4.$(OBJEXT) \
-	decode-ipv6.$(OBJEXT) decode-null.$(OBJEXT) \
-	decode-ppp.$(OBJEXT) decode-pppoe.$(OBJEXT) \
-	decode-raw.$(OBJEXT) decode-sctp.$(OBJEXT) \
-	decode-sll.$(OBJEXT) decode-tcp.$(OBJEXT) \
-	decode-teredo.$(OBJEXT) decode-udp.$(OBJEXT) \
-	decode-vlan.$(OBJEXT) decode-mpls.$(OBJEXT) \
-	decode-template.$(OBJEXT) defrag-config.$(OBJEXT) \
-	defrag.$(OBJEXT) defrag-hash.$(OBJEXT) defrag-queue.$(OBJEXT) \
-	defrag-timeout.$(OBJEXT) detect-ack.$(OBJEXT) \
-	detect-app-layer-event.$(OBJEXT) \
+	data-queue.$(OBJEXT) decode.$(OBJEXT) decode-afl.$(OBJEXT) \
+	decode-erspan.$(OBJEXT) decode-ethernet.$(OBJEXT) \
+	decode-events.$(OBJEXT) decode-gre.$(OBJEXT) \
+	decode-icmpv4.$(OBJEXT) decode-icmpv6.$(OBJEXT) \
+	decode-ipv4.$(OBJEXT) decode-ipv6.$(OBJEXT) \
+	decode-null.$(OBJEXT) decode-ppp.$(OBJEXT) \
+	decode-pppoe.$(OBJEXT) decode-raw.$(OBJEXT) \
+	decode-sctp.$(OBJEXT) decode-sll.$(OBJEXT) \
+	decode-tcp.$(OBJEXT) decode-teredo.$(OBJEXT) \
+	decode-udp.$(OBJEXT) decode-vlan.$(OBJEXT) \
+	decode-mpls.$(OBJEXT) decode-template.$(OBJEXT) \
+	defrag-config.$(OBJEXT) defrag.$(OBJEXT) defrag-hash.$(OBJEXT) \
+	defrag-queue.$(OBJEXT) defrag-timeout.$(OBJEXT) \
+	detect-ack.$(OBJEXT) detect-app-layer-event.$(OBJEXT) \
 	detect-app-layer-protocol.$(OBJEXT) detect-asn1.$(OBJEXT) \
 	detect-base64-data.$(OBJEXT) detect-base64-decode.$(OBJEXT) \
 	detect-byte-extract.$(OBJEXT) detect-bytejump.$(OBJEXT) \
@@ -634,6 +634,7 @@
 counters.c counters.h \
 data-queue.c data-queue.h \
 decode.c decode.h \
+decode-afl.c \
 decode-erspan.c decode-erspan.h \
 decode-ethernet.c decode-ethernet.h \
 decode-events.c decode-events.h \
@@ -1197,6 +1198,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/counters.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-queue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-afl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-erspan.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-ethernet.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode-events.Po@am__quote@
diff -Nru suricata-3.2/src/output-file.c suricata-3.2.1/src/output-file.c
--- suricata-3.2/src/output-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -147,11 +147,11 @@
                 ff->state == FILE_STATE_ERROR)
             {
                 int file_logged = 0;
-
+#ifdef HAVE_MAGIC
                 if (FileForceMagic() && ff->magic == NULL) {
                     FilemagicGlobalLookup(ff);
                 }
-
+#endif
                 logger = list;
                 store = op_thread_data->store;
                 while (logger && store) {
diff -Nru suricata-3.2/src/output-filedata.c suricata-3.2.1/src/output-filedata.c
--- suricata-3.2/src/output-filedata.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-filedata.c	2017-02-15 08:54:12.000000000 +0100
@@ -165,10 +165,11 @@
     if (ffc != NULL) {
         File *ff;
         for (ff = ffc->head; ff != NULL; ff = ff->next) {
+#ifdef HAVE_MAGIC
             if (FileForceMagic() && ff->magic == NULL) {
                 FilemagicGlobalLookup(ff);
             }
-
+#endif
             SCLogDebug("ff %p", ff);
             if (ff->flags & FILE_STORED) {
                 SCLogDebug("stored flag set");
@@ -182,7 +183,7 @@
 
             /* if we have no data chunks left to log, we should still
              * close the logger(s) */
-            if (FileSize(ff) == ff->content_stored &&
+            if (FileDataSize(ff) == ff->content_stored &&
                 (file_trunc || file_close)) {
                 CallLoggers(tv, store, p, ff, NULL, 0, OUTPUT_FILEDATA_FLAG_CLOSE);
                 ff->flags |= FILE_STORED;
diff -Nru suricata-3.2/src/output-json-dns.c suricata-3.2.1/src/output-json-dns.c
--- suricata-3.2/src/output-json-dns.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-json-dns.c	2017-02-15 08:54:12.000000000 +0100
@@ -479,11 +479,11 @@
     json_object_set_new(js, "ttl", json_integer(entry->ttl));
 
     uint8_t *ptr = (uint8_t *)((uint8_t *)entry + sizeof(DNSAnswerEntry)+ entry->fqdn_len);
-    if (entry->type == DNS_RECORD_TYPE_A) {
+    if (entry->type == DNS_RECORD_TYPE_A && entry->data_len == 4) {
         char a[16] = "";
         PrintInet(AF_INET, (const void *)ptr, a, sizeof(a));
         json_object_set_new(js, "rdata", json_string(a));
-    } else if (entry->type == DNS_RECORD_TYPE_AAAA) {
+    } else if (entry->type == DNS_RECORD_TYPE_AAAA && entry->data_len == 16) {
         char a[46] = "";
         PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a));
         json_object_set_new(js, "rdata", json_string(a));
diff -Nru suricata-3.2/src/output-json-file.c suricata-3.2.1/src/output-json-file.c
--- suricata-3.2/src/output-json-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-json-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -119,8 +119,10 @@
     json_object_set_new(fjs, "filename", json_string(s));
     if (s != NULL)
         SCFree(s);
+#ifdef HAVE_MAGIC
     if (ff->magic)
         json_object_set_new(fjs, "magic", json_string((char *)ff->magic));
+#endif
     switch (ff->state) {
         case FILE_STATE_CLOSED:
             json_object_set_new(fjs, "state", json_string("CLOSED"));
@@ -169,7 +171,7 @@
     if (ff->flags & FILE_STORED) {
         json_object_set_new(fjs, "file_id", json_integer(ff->file_id));
     }
-    json_object_set_new(fjs, "size", json_integer(FileSize(ff)));
+    json_object_set_new(fjs, "size", json_integer(FileTrackedSize(ff)));
     json_object_set_new(fjs, "tx_id", json_integer(ff->txid));
 
     /* originally just 'file', but due to bug 1127 naming it fileinfo */
diff -Nru suricata-3.2/src/output-json-flow.c suricata-3.2.1/src/output-json-flow.c
--- suricata-3.2/src/output-json-flow.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-json-flow.c	2017-02-15 08:54:12.000000000 +0100
@@ -261,6 +261,8 @@
     json_object_set_new(hjs, "reason",
             json_string(reason));
 
+    json_object_set_new(hjs, "alerted", json_boolean(FlowHasAlerts(f)));
+
     json_object_set_new(js, "flow", hjs);
 
 
diff -Nru suricata-3.2/src/output-json-template.c suricata-3.2.1/src/output-json-template.c
--- suricata-3.2/src/output-json-template.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-json-template.c	2017-02-15 08:54:12.000000000 +0100
@@ -110,9 +110,6 @@
     return TM_ECODE_OK;
     
 error:
-    if (templatejs != NULL) {
-        json_decref(templatejs);
-    }
     json_decref(js);
     return TM_ECODE_FAILED;
 }
diff -Nru suricata-3.2/src/output-tx.c suricata-3.2.1/src/output-tx.c
--- suricata-3.2/src/output-tx.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/output-tx.c	2017-02-15 08:54:12.000000000 +0100
@@ -163,10 +163,17 @@
 
     uint64_t total_txs = AppLayerParserGetTxCnt(p->proto, alproto, alstate);
     uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser);
+    uint64_t max_id = tx_id;
+    int logged = 0;
+    int gap = 0;
 
     for (; tx_id < total_txs; tx_id++)
     {
-        int logger_not_logged = 0;
+        /* Track the number of loggers, of the eligible loggers that
+         * actually logged this transaction. They all must have logged
+         * before the transaction is considered logged. */
+        int number_of_loggers = 0;
+        int loggers_that_logged = 0;
 
         void *tx = AppLayerParserGetTx(p->proto, alproto, alstate, tx_id);
         if (tx == NULL) {
@@ -195,10 +202,12 @@
             if (logger->alproto == alproto) {
                 SCLogDebug("alproto match, logging tx_id %"PRIu64, tx_id);
 
+                number_of_loggers++;
+
                 if (AppLayerParserGetTxLogged(p->proto, alproto, alstate, tx,
                         logger->id)) {
                     SCLogDebug("logger has already logged this transaction");
-
+                    loggers_that_logged++;
                     goto next;
                 }
 
@@ -208,30 +217,30 @@
                         int r = logger->LogCondition(tv, p, alstate, tx, tx_id);
                         if (r == FALSE) {
                             SCLogDebug("conditions not met, not logging");
-                            logger_not_logged = 1;
                             goto next;
                         }
                     } else {
                         if (tx_progress_tc < logger->tc_log_progress) {
                             SCLogDebug("progress not far enough, not logging");
-                            logger_not_logged = 1;
                             goto next;
                         }
 
                         if (tx_progress_ts < logger->ts_log_progress) {
                             SCLogDebug("progress not far enough, not logging");
-                            logger_not_logged = 1;
                             goto next;
                         }
                     }
                 }
 
+                SCLogDebug("Logging tx_id %"PRIu64" to logger %d", tx_id,
+                    logger->logger_id);
                 PACKET_PROFILING_LOGGER_START(p, logger->logger_id);
                 logger->LogFunc(tv, store->thread_data, p, f, alstate, tx, tx_id);
                 PACKET_PROFILING_LOGGER_END(p, logger->logger_id);
 
                 AppLayerParserSetTxLogged(p->proto, alproto, alstate, tx,
                                           logger->id);
+                loggers_that_logged++;
             }
 
 next:
@@ -242,12 +251,27 @@
             BUG_ON(logger != NULL && store == NULL);
         }
 
-        if (!logger_not_logged) {
-            SCLogDebug("updating log tx_id %"PRIu64, tx_id);
-            AppLayerParserSetTransactionLogId(f->alparser);
+        /* If all loggers logged set a flag and update the last tx_id
+         * that was logged.
+         *
+         * If not all loggers were logged we flag that there was a gap
+         * so any subsequent transactions in this loop don't increase
+         * the maximum ID that was logged. */
+        if (!gap && loggers_that_logged == number_of_loggers) {
+            logged = 1;
+            max_id = tx_id;
+        } else {
+            gap = 1;
         }
     }
 
+    /* Update the the last ID that has been logged with all
+     * transactions before it. */
+    if (logged) {
+        SCLogDebug("updating log tx_id %"PRIu64, max_id);
+        AppLayerParserSetTransactionLogId(f->alparser, max_id + 1);
+    }
+
 end:
     return TM_ECODE_OK;
 }
diff -Nru suricata-3.2/src/queue.h suricata-3.2.1/src/queue.h
--- suricata-3.2/src/queue.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/queue.h	2017-02-15 08:54:12.000000000 +0100
@@ -82,12 +82,18 @@
  * For details on the use of these macros, see the queue(3) manual page.
  */
 
-#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
+#if defined(__clang_analyzer__) || defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
 #define _Q_INVALIDATE(a) ((a) = ((void *)-1))
 #else
 #define _Q_INVALIDATE(a)
 #endif
 
+#if defined(__clang_analyzer__)
+#define _Q_ASSERT(a) assert((a))
+#else
+#define _Q_ASSERT(a)
+#endif
+
 /*
  * Singly-linked List definitions.
  */
@@ -377,9 +383,12 @@
 } while (0)
 
 #define TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	_Q_ASSERT((elm));						\
+	_Q_ASSERT((head));						\
 	(elm)->field.tqe_next = NULL;					\
 	(elm)->field.tqe_prev = (head)->tqh_last;			\
 	*(head)->tqh_last = (elm);					\
+	_Q_ASSERT(*(head)->tqh_last);					\
 	(head)->tqh_last = &(elm)->field.tqe_next;			\
 } while (0)
 
@@ -407,6 +416,7 @@
 	else								\
 		(head)->tqh_last = (elm)->field.tqe_prev;		\
 	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+	_Q_ASSERT((head)->tqh_first != (elm));				\
 	_Q_INVALIDATE((elm)->field.tqe_prev);				\
 	_Q_INVALIDATE((elm)->field.tqe_next);				\
 } while (0)
diff -Nru suricata-3.2/src/runmodes.c suricata-3.2.1/src/runmodes.c
--- suricata-3.2/src/runmodes.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/runmodes.c	2017-02-15 08:54:12.000000000 +0100
@@ -50,6 +50,8 @@
 #include "source-pfring.h"
 
 #include "tmqh-flow.h"
+#include "flow-manager.h"
+#include "counters.h"
 
 #ifdef __SC_CUDA_SUPPORT__
 #include "util-cuda-buffer.h"
@@ -392,7 +394,12 @@
     /* Check if the alloted queues have at least 1 reader and writer */
     TmValidateQueueState();
 
-    return;
+    if (runmode != RUNMODE_UNIX_SOCKET) {
+        /* spawn management threads */
+        FlowManagerThreadSpawn();
+        FlowRecyclerThreadSpawn();
+        StatsSpawnThreads();
+    }
 }
 
 /**
diff -Nru suricata-3.2/src/runmode-unittests.c suricata-3.2.1/src/runmode-unittests.c
--- suricata-3.2/src/runmode-unittests.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/runmode-unittests.c	2017-02-15 08:54:12.000000000 +0100
@@ -128,77 +128,9 @@
 void RegisterAllModules();
 void TmqhSetup (void);
 
-/**
- * Run or list unittests
- *
- * \param list_unittests If set to 1, list unittests. Run them if set to 0.
- * \param regex_arg A regular expression to select unittests to run
- *
- * This function is terminal and will call exit after being called.
- */
-
-void RunUnittests(int list_unittests, char *regex_arg)
-{
 #ifdef UNITTESTS
-    /* Initializations for global vars, queues, etc (memsets, mutex init..) */
-    GlobalInits();
-    TimeInit();
-    SupportFastPatternForSigMatchTypes();
-#ifdef HAVE_LUAJIT
-    if (LuajitSetupStatesPool() != 0) {
-        exit(EXIT_FAILURE);
-    }
-#endif
-
-    default_packet_size = DEFAULT_PACKET_SIZE;
-#ifdef __SC_CUDA_SUPPORT__
-    /* Init the CUDA environment */
-    SCCudaInitCudaEnvironment();
-    CudaBufferInit();
-#endif
-    /* load the pattern matchers */
-    MpmTableSetup();
-#ifdef __SC_CUDA_SUPPORT__
-    MpmCudaEnvironmentSetup();
-#endif
-    SpmTableSetup();
-
-    AppLayerSetup();
-
-    /* hardcoded initialization code */
-    SigTableSetup(); /* load the rule keywords */
-    TmqhSetup();
-
-    StorageInit();
-    CIDRInit();
-    SigParsePrepare();
-
-#ifdef DBG_MEM_ALLOC
-    SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
-#endif
-    SCReputationInitCtx();
-    SCProtoNameInit();
-
-    TagInitCtx();
-    SCReferenceConfInit();
-    SCClassConfInit();
-
-    UtInitialize();
-
-    RegisterAllModules();
-
-    HostBitInitCtx();
-
-    StorageFinalize();
-   /* test and initialize the unittesting subsystem */
-    if(regex_arg == NULL){
-        regex_arg = ".*";
-        UtRunSelftest(regex_arg); /* inits and cleans up again */
-    }
-
-    AppLayerHtpEnableRequestBodyCallback();
-    AppLayerHtpNeedFileInspection();
-
+static void RegisterUnittests(void)
+{
     UTHRegisterTests();
     StreamTcpRegisterTests();
     SigRegisterTests();
@@ -290,6 +222,75 @@
     AppLayerUnittestsRegister();
     MimeDecRegisterTests();
     StreamingBufferRegisterTests();
+}
+#endif
+
+/**
+ * Run or list unittests
+ *
+ * \param list_unittests If set to 1, list unittests. Run them if set to 0.
+ * \param regex_arg A regular expression to select unittests to run
+ *
+ * This function is terminal and will call exit after being called.
+ */
+
+void RunUnittests(int list_unittests, char *regex_arg)
+{
+#ifdef UNITTESTS
+    /* Initializations for global vars, queues, etc (memsets, mutex init..) */
+    GlobalsInitPreConfig();
+
+#ifdef HAVE_LUAJIT
+    if (LuajitSetupStatesPool() != 0) {
+        exit(EXIT_FAILURE);
+    }
+#endif
+
+    default_packet_size = DEFAULT_PACKET_SIZE;
+    /* load the pattern matchers */
+    MpmTableSetup();
+#ifdef __SC_CUDA_SUPPORT__
+    MpmCudaEnvironmentSetup();
+#endif
+    SpmTableSetup();
+
+    AppLayerSetup();
+
+    /* hardcoded initialization code */
+    SigTableSetup(); /* load the rule keywords */
+    TmqhSetup();
+
+    StorageInit();
+    CIDRInit();
+    SigParsePrepare();
+
+#ifdef DBG_MEM_ALLOC
+    SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
+#endif
+    SCReputationInitCtx();
+    SCProtoNameInit();
+
+    TagInitCtx();
+    SCReferenceConfInit();
+    SCClassConfInit();
+
+    UtInitialize();
+
+    RegisterAllModules();
+
+    HostBitInitCtx();
+
+    StorageFinalize();
+   /* test and initialize the unittesting subsystem */
+    if(regex_arg == NULL){
+        regex_arg = ".*";
+        UtRunSelftest(regex_arg); /* inits and cleans up again */
+    }
+
+    AppLayerHtpEnableRequestBodyCallback();
+    AppLayerHtpNeedFileInspection();
+
+    RegisterUnittests();
 
     if (list_unittests) {
         UtListTests(regex_arg);
diff -Nru suricata-3.2/src/runmode-unix-socket.c suricata-3.2.1/src/runmode-unix-socket.c
--- suricata-3.2/src/runmode-unix-socket.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/runmode-unix-socket.c	2017-02-15 08:54:12.000000000 +0100
@@ -299,102 +299,57 @@
         }
         this->currentfile = NULL;
 
-        /* needed by FlowForceReassembly */
-        PacketPoolInit();
-
-        /* handle graceful shutdown of the flow engine, it's helper
-         * threads and the packet threads */
-        FlowDisableFlowManagerThread();
-        TmThreadDisableReceiveThreads();
-        FlowForceReassembly();
-        TmThreadDisablePacketThreads();
-        FlowDisableFlowRecyclerThread();
-
-        /* kill the stats threads */
-        TmThreadKillThreadsFamily(TVT_MGMT);
-        TmThreadClearThreadsFamily(TVT_MGMT);
-
-        /* kill packet threads -- already in 'disabled' state */
-        TmThreadKillThreadsFamily(TVT_PPT);
-        TmThreadClearThreadsFamily(TVT_PPT);
-
-        PacketPoolDestroy();
+        PostRunDeinit(RUNMODE_PCAP_FILE, NULL /* no ts */);
+    }
+    if (TAILQ_EMPTY(&this->files)) {
+        // nothing to do
+        return TM_ECODE_OK;
+    }
 
-        /* mgt and ppt threads killed, we can run non thread-safe
-         * shutdown functions */
-        StatsReleaseResources();
-        RunModeShutDown();
-        FlowShutdown();
-        IPPairShutdown();
-        HostCleanup();
-        StreamTcpFreeConfig(STREAM_VERBOSE);
-        DefragDestroy();
-        TmqResetQueues();
-#ifdef PROFILING
-        if (profiling_rules_enabled)
-            SCProfilingDump();
-        SCProfilingDestroy();
-#endif
+    PcapFiles *cfile = TAILQ_FIRST(&this->files);
+    TAILQ_REMOVE(&this->files, cfile, next);
+    SCLogInfo("Starting run for '%s'", cfile->filename);
+    unix_manager_file_task_running = 1;
+    this->running = 1;
+    if (ConfSet("pcap-file.file", cfile->filename) != 1) {
+        SCLogError(SC_ERR_INVALID_ARGUMENTS,
+                "Can not set working file to '%s'", cfile->filename);
+        PcapFilesFree(cfile);
+        return TM_ECODE_FAILED;
     }
-    if (!TAILQ_EMPTY(&this->files)) {
-        PcapFiles *cfile = TAILQ_FIRST(&this->files);
-        TAILQ_REMOVE(&this->files, cfile, next);
-        SCLogInfo("Starting run for '%s'", cfile->filename);
-        unix_manager_file_task_running = 1;
-        this->running = 1;
-        if (ConfSet("pcap-file.file", cfile->filename) != 1) {
+    if (cfile->output_dir) {
+        if (ConfSet("default-log-dir", cfile->output_dir) != 1) {
             SCLogError(SC_ERR_INVALID_ARGUMENTS,
-                       "Can not set working file to '%s'", cfile->filename);
+                    "Can not set output dir to '%s'", cfile->output_dir);
             PcapFilesFree(cfile);
             return TM_ECODE_FAILED;
         }
-        if (cfile->output_dir) {
-            if (ConfSet("default-log-dir", cfile->output_dir) != 1) {
-                SCLogError(SC_ERR_INVALID_ARGUMENTS,
-                           "Can not set output dir to '%s'", cfile->output_dir);
-                PcapFilesFree(cfile);
-                return TM_ECODE_FAILED;
-            }
-        }
-        if (cfile->tenant_id > 0) {
-            char tstr[16];
-            snprintf(tstr, sizeof(tstr), "%d", cfile->tenant_id);
-            if (ConfSet("pcap-file.tenant-id", tstr) != 1) {
-                SCLogError(SC_ERR_INVALID_ARGUMENTS,
-                           "Can not set working tenant-id to '%s'", tstr);
-                PcapFilesFree(cfile);
-                return TM_ECODE_FAILED;
-            }
-        } else {
-            SCLogInfo("pcap-file.tenant-id not set");
-        }
-        this->currentfile = SCStrdup(cfile->filename);
-        if (unlikely(this->currentfile == NULL)) {
-            SCLogError(SC_ERR_MEM_ALLOC, "Failed file name allocation");
+    }
+    if (cfile->tenant_id > 0) {
+        char tstr[16];
+        snprintf(tstr, sizeof(tstr), "%d", cfile->tenant_id);
+        if (ConfSet("pcap-file.tenant-id", tstr) != 1) {
+            SCLogError(SC_ERR_INVALID_ARGUMENTS,
+                    "Can not set working tenant-id to '%s'", tstr);
+            PcapFilesFree(cfile);
             return TM_ECODE_FAILED;
         }
-        PcapFilesFree(cfile);
-        StatsInit();
-#ifdef PROFILING
-        SCProfilingRulesGlobalInit();
-        SCProfilingKeywordsGlobalInit();
-        SCProfilingSghsGlobalInit();
-        SCProfilingInit();
-#endif /* PROFILING */
-        DefragInit();
-        FlowInitConfig(FLOW_QUIET);
-        IPPairInitConfig(FLOW_QUIET);
-        StreamTcpInitConfig(STREAM_VERBOSE);
-        AppLayerRegisterGlobalCounters();
-        RunModeInitializeOutputs();
-        StatsSetupPostConfig();
-        RunModeDispatch(RUNMODE_PCAP_FILE, NULL);
-        FlowManagerThreadSpawn();
-        FlowRecyclerThreadSpawn();
-        StatsSpawnThreads();
-        /* Un-pause all the paused threads */
-        TmThreadContinueThreads();
+    } else {
+        SCLogInfo("pcap-file.tenant-id not set");
+    }
+    this->currentfile = SCStrdup(cfile->filename);
+    if (unlikely(this->currentfile == NULL)) {
+        SCLogError(SC_ERR_MEM_ALLOC, "Failed file name allocation");
+        return TM_ECODE_FAILED;
     }
+    PcapFilesFree(cfile);
+
+    PreRunInit(RUNMODE_PCAP_FILE);
+    PreRunPostPrivsDropInit(RUNMODE_PCAP_FILE);
+    RunModeDispatch(RUNMODE_PCAP_FILE, NULL);
+
+    /* Un-pause all the paused threads */
+    TmThreadContinueThreads();
     return TM_ECODE_OK;
 }
 #endif
diff -Nru suricata-3.2/src/source-af-packet.c suricata-3.2.1/src/source-af-packet.c
--- suricata-3.2/src/source-af-packet.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/source-af-packet.c	2017-02-15 08:54:12.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2016 Open Information Security Foundation
+/* Copyright (C) 2011-2017 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -662,10 +662,23 @@
     SCReturnInt(AFP_READ_OK);
 }
 
-TmEcode AFPWritePacket(Packet *p)
+/**
+ * \brief AF packet write function.
+ *
+ * This function has to be called before the memory
+ * related to Packet in ring buffer is released.
+ *
+ * \param pointer to Packet
+ * \param version of capture: TPACKET_V2 or TPACKET_V3
+ * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
+ *
+ */
+static TmEcode AFPWritePacket(Packet *p, int version)
 {
     struct sockaddr_ll socket_address;
     int socket;
+    uint8_t *pstart;
+    size_t plen;
 
     if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
         if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
@@ -691,7 +704,31 @@
     if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
         SCMutexLock(&p->afp_v.peer->sock_protect);
     socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
-    if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
+
+    if (version == TPACKET_V2) {
+        union thdr h;
+        h.raw = p->afp_v.relptr;
+        /* Copy VLAN header from ring memory. For post june 2011 kernel we test
+         * the flag. It is not defined for older kernel so we go best effort
+         * and test for non zero value of the TCI header. */
+        if (h.h2->tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci) {
+            pstart = GET_PKT_DATA(p) - VLAN_HEADER_LEN;
+            plen = GET_PKT_LEN(p) + VLAN_HEADER_LEN;
+            /* move ethernet addresses */
+            memmove(pstart, GET_PKT_DATA(p), 2 * ETH_ALEN);
+            /* write vlan info */
+            *(uint16_t *)(pstart + 2 * ETH_ALEN) = htons(0x8100);
+            *(uint16_t *)(pstart + 2 * ETH_ALEN + 2) = htons(h.h2->tp_vlan_tci);
+        } else {
+            pstart = GET_PKT_DATA(p);
+            plen = GET_PKT_LEN(p);
+        }
+    } else {
+        pstart = GET_PKT_DATA(p);
+        plen = GET_PKT_LEN(p);
+    }
+
+    if (sendto(socket, pstart, plen, 0,
                (struct sockaddr*) &socket_address,
                sizeof(struct sockaddr_ll)) < 0) {
         SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
@@ -712,7 +749,7 @@
     /* Need to be in copy mode and need to detect early release
        where Ethernet header could not be set (and pseudo packet) */
     if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
-        AFPWritePacket(p);
+        AFPWritePacket(p, TPACKET_V2);
     }
 
     if (AFPDerefSocket(p->afp_v.mpeer) == 0)
@@ -728,15 +765,17 @@
     AFPV_CLEANUP(&p->afp_v);
 }
 
+#ifdef HAVE_TPACKET_V3
 void AFPReleasePacketV3(Packet *p)
 {
     /* Need to be in copy mode and need to detect early release
        where Ethernet header could not be set (and pseudo packet) */
     if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
-        AFPWritePacket(p);
+        AFPWritePacket(p, TPACKET_V3);
     }
     PacketFreeOrRelease(p);
 }
+#endif
 
 void AFPReleasePacket(Packet *p)
 {
@@ -1686,6 +1725,21 @@
     }
 #endif
 
+    /* Let's reserve head room so we can add the VLAN header in IPS
+     * or TAP mode before write the packet */
+    if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
+        /* Only one vlan is extracted from AFP header so
+         * one VLAN header length is enough. */
+        int reserve = VLAN_HEADER_LEN;
+        if (setsockopt(ptv->socket, SOL_PACKET, PACKET_RESERVE, (void *) &reserve,
+                    sizeof(reserve)) < 0) {
+            SCLogError(SC_ERR_AFP_CREATE,
+                    "Can't activate reserve on packet socket: %s",
+                    strerror(errno));
+            return AFP_FATAL_ERROR;
+        }
+    }
+
     /* Allocate RX ring */
 #ifdef HAVE_TPACKET_V3
     if (ptv->flags & AFP_TPACKET_V3) {
diff -Nru suricata-3.2/src/stream-tcp-reassemble.c suricata-3.2.1/src/stream-tcp-reassemble.c
--- suricata-3.2/src/stream-tcp-reassemble.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/stream-tcp-reassemble.c	2017-02-15 08:54:12.000000000 +0100
@@ -344,12 +344,21 @@
             SCLogDebug("segpre->val %s", segpre->val);
 
             uint16_t pktsize = 0;
-            if (ByteExtractStringUint16(&pktsize, 10, strlen(segsize->val),
-                                        segsize->val) == -1)
-            {
-                SCLogError(SC_ERR_INVALID_ARGUMENT, "segment packet size "
-                                                    "of %s is invalid", segsize->val);
-                return -1;
+            if (strcmp("from_mtu", segsize->val) == 0) {
+                int mtu = g_default_mtu ? g_default_mtu : DEFAULT_MTU;
+                if (mtu < MINIMUM_MTU) {
+                    FatalErrorOnInit(SC_ERR_INVALID_ARGUMENT, "invalid mtu %d", mtu);
+                    continue;
+                }
+                pktsize = mtu - 40;
+            } else {
+                if (ByteExtractStringUint16(&pktsize, 10, strlen(segsize->val),
+                            segsize->val) == -1)
+                {
+                    SCLogError(SC_ERR_INVALID_ARGUMENT, "segment packet size "
+                            "of %s is invalid", segsize->val);
+                    return -1;
+                }
             }
             uint32_t prealloc = 0;
             if (ByteExtractStringUint32(&prealloc, 10, strlen(segpre->val),
@@ -379,6 +388,10 @@
             SCLogConfig("appended a segment pool for pktsize 65536");
         }
     } else if (npools == 0) {
+        int mtu = g_default_mtu;
+        if (mtu < MINIMUM_MTU)
+            mtu = DEFAULT_MTU;
+
         /* defaults */
         sizes[0].pktsize = 4;
         sizes[0].prealloc = 256;
@@ -392,7 +405,7 @@
         sizes[4].prealloc = 512;
         sizes[5].pktsize = 768;
         sizes[5].prealloc = 1024;
-        sizes[6].pktsize = 1448;
+        sizes[6].pktsize = mtu - 40; // min size of ipv4+tcp hdrs
         sizes[6].prealloc = 1024;
         sizes[7].pktsize = 0xffff;
         sizes[7].prealloc = 128;
diff -Nru suricata-3.2/src/suricata.c suricata-3.2.1/src/suricata.c
--- suricata-3.2/src/suricata.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/suricata.c	2017-02-15 08:54:12.000000000 +0100
@@ -116,6 +116,7 @@
 #include "app-layer-htp.h"
 #include "app-layer-ssl.h"
 #include "app-layer-dns-tcp.h"
+#include "app-layer-dns-udp.h"
 #include "app-layer-ssh.h"
 #include "app-layer-ftp.h"
 #include "app-layer-smtp.h"
@@ -211,7 +212,10 @@
 int g_detect_disabled = 0;
 
 /** set caps or not */
-int sc_set_caps;
+int sc_set_caps = FALSE;
+
+/** highest mtu of the interfaces we monitor */
+int g_default_mtu = 0;
 
 int EngineModeIsIPS(void)
 {
@@ -312,8 +316,14 @@
     }
 }
 
-void GlobalInits()
+void GlobalsInitPreConfig()
 {
+#ifdef __SC_CUDA_SUPPORT__
+    /* Init the CUDA environment */
+    SCCudaInitCudaEnvironment();
+    CudaBufferInit();
+#endif
+
     memset(trans_q, 0, sizeof(trans_q));
     memset(data_queues, 0, sizeof(data_queues));
 
@@ -334,6 +344,80 @@
     }
 
     CreateLowercaseTable();
+
+    TimeInit();
+    SupportFastPatternForSigMatchTypes();
+}
+
+void GlobalsDestroy(SCInstance *suri)
+{
+    HostShutdown();
+    HTPFreeConfig();
+    HTPAtExitPrintStats();
+
+#ifdef DBG_MEM_ALLOC
+    SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem);
+#ifdef DBG_MEM_ALLOC_SKIP_STARTUP
+    print_mem_flag = 0;
+#endif
+#endif
+
+    AppLayerHtpPrintStats();
+
+    /* TODO this can do into it's own func */
+    DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
+    if (de_ctx) {
+        DetectEngineMoveToFreeList(de_ctx);
+        DetectEngineDeReference(&de_ctx);
+    }
+    DetectEnginePruneFreeList();
+
+    AppLayerDeSetup();
+
+    TagDestroyCtx();
+
+    LiveDeviceListClean();
+    OutputDeregisterAll();
+    TimeDeinit();
+    SCProtoNameDeInit();
+    if (!suri->disabled_detect) {
+        SCReferenceConfDeinit();
+        SCClassConfDeinit();
+    }
+#ifdef HAVE_MAGIC
+    MagicDeinit();
+#endif
+    TmqhCleanup();
+    TmModuleRunDeInit();
+    ParseSizeDeinit();
+#ifdef HAVE_NSS
+    NSS_Shutdown();
+    PR_Cleanup();
+#endif
+
+#ifdef HAVE_AF_PACKET
+    AFPPeersListClean();
+#endif
+
+    SC_ATOMIC_DESTROY(engine_stage);
+
+#ifdef BUILD_HYPERSCAN
+    MpmHSGlobalCleanup();
+#endif
+
+#ifdef __SC_CUDA_SUPPORT__
+    if (PatternMatchDefaultMatcher() == MPM_AC_CUDA)
+        MpmCudaBufferDeSetup();
+    CudaHandlerFreeProfiles();
+#endif
+    ConfDeInit();
+#ifdef HAVE_LUAJIT
+    LuajitFreeStatesPool();
+#endif
+    SCLogDeInitLogModule();
+    DetectParseFreeRegexes();
+
+    SCPidfileRemove(suri->pid_filename);
 }
 
 /** \brief make sure threads can stop the engine by calling this
@@ -680,6 +764,9 @@
 #ifdef TLS
     strlcat(features, "TLS ", sizeof(features));
 #endif
+#ifdef HAVE_MAGIC
+    strlcat(features, "MAGIC ", sizeof(features));
+#endif
     if (strlen(features) == 0) {
         strlcat(features, "none", sizeof(features));
     }
@@ -954,10 +1041,11 @@
     SCReturnInt(TM_ECODE_OK);
 }
 
-static void SCInstanceInit(SCInstance *suri)
+static void SCInstanceInit(SCInstance *suri, const char *progname)
 {
     memset(suri, 0x00, sizeof(*suri));
 
+    suri->progname = progname;
     suri->run_mode = RUNMODE_UNKNOWN;
 
     memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
@@ -1019,13 +1107,15 @@
     gettimeofday(&suri->start_time, NULL);
 }
 
-static void SCPrintElapsedTime(SCInstance *suri)
+static void SCPrintElapsedTime(struct timeval *start_time)
 {
+    if (start_time == NULL)
+        return;
     struct timeval end_time;
     memset(&end_time, 0, sizeof(end_time));
     gettimeofday(&end_time, NULL);
-    uint64_t milliseconds = ((end_time.tv_sec - suri->start_time.tv_sec) * 1000) +
-        (((1000000 + end_time.tv_usec - suri->start_time.tv_usec) / 1000) - 1000);
+    uint64_t milliseconds = ((end_time.tv_sec - start_time->tv_sec) * 1000) +
+        (((1000000 + end_time.tv_usec - start_time->tv_usec) / 1000) - 1000);
     SCLogInfo("time elapsed %.3fs", (float)milliseconds/(float)1000);
 }
 
@@ -1108,6 +1198,231 @@
     return TM_ECODE_OK;
 }
 
+static void ParseCommandLineAFL(const char *opt_name, char *opt_arg)
+{
+#ifdef AFLFUZZ_RULES
+    if(strcmp(opt_name, "afl-rules") == 0) {
+        MpmTableSetup();
+        SpmTableSetup();
+        exit(RuleParseDataFromFile(opt_arg));
+    } else
+#endif
+#ifdef AFLFUZZ_APPLAYER
+    if(strcmp(opt_name, "afl-http-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterHTPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_HTTP, opt_arg));
+    } else if(strcmp(opt_name, "afl-http") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterHTPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_HTTP, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-tls-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSSLParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_TLS, opt_arg));
+    } else if(strcmp(opt_name, "afl-tls") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSSLParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_TLS, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-dns-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        RegisterDNSUDPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_UDP, ALPROTO_DNS, opt_arg));
+    } else if(strcmp(opt_name, "afl-dns") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterDNSUDPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_UDP, ALPROTO_DNS, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-dnstcp-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        RegisterDNSTCPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_DNS, opt_arg));
+    } else if(strcmp(opt_name, "afl-dnstcp") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterDNSTCPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_DNS, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-ssh-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        RegisterSSHParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_SSH, opt_arg));
+    } else if(strcmp(opt_name, "afl-ssh") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSSHParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_SSH, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-ftp-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterFTPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_FTP, opt_arg));
+    } else if(strcmp(opt_name, "afl-ftp") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterFTPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_FTP, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-smtp-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSMTPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_SMTP, opt_arg));
+    } else if(strcmp(opt_name, "afl-smtp") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSMTPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_SMTP, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-smb-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        RegisterSMBParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_SMB, opt_arg));
+    } else if(strcmp(opt_name, "afl-smb") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        AppLayerParserSetup();
+        RegisterSMBParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_SMB, opt_arg));
+
+    } else if(strcmp(opt_name, "afl-modbus-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterModbusParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_MODBUS, opt_arg));
+    } else if(strcmp(opt_name, "afl-modbus") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterModbusParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_MODBUS, opt_arg));
+    } else if(strcmp(opt_name, "afl-enip-request") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterENIPTCPParsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_ENIP, opt_arg));
+    } else if(strcmp(opt_name, "afl-enip") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        AppLayerParserSetup();
+        RegisterENIPTCPParsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_ENIP, opt_arg));
+    } else if(strcmp(opt_name, "afl-dnp3-request") == 0) {
+        AppLayerParserSetup();
+        RegisterDNP3Parsers();
+        exit(AppLayerParserRequestFromFile(IPPROTO_TCP, ALPROTO_DNP3, opt_arg));
+    } else if(strcmp(opt_name, "afl-dnp3") == 0) {
+        AppLayerParserSetup();
+        RegisterDNP3Parsers();
+        exit(AppLayerParserFromFile(IPPROTO_TCP, ALPROTO_DNP3, opt_arg));
+    } else
+#endif
+#ifdef AFLFUZZ_MIME
+    if(strcmp(opt_name, "afl-mime") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        exit(MimeParserDataFromFile(opt_arg));
+    } else
+#endif
+#ifdef AFLFUZZ_DECODER
+    if(strstr(opt_name, "afl-decoder-ppp") != NULL) {
+        StatsInit();
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        if (strcmp(opt_name, "afl-decoder-ppp") == 0)
+            exit(DecoderParseDataFromFile(opt_arg, DecodePPP));
+        else
+            exit(DecoderParseDataFromFileSerie(opt_arg, DecodePPP));
+    } else if(strstr(opt_name, "afl-decoder-ipv4") != NULL) {
+        StatsInit();
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        if (strcmp(opt_name, "afl-decoder-ipv4") == 0)
+            exit(DecoderParseDataFromFile(opt_arg, DecodeIPV4));
+        else
+            exit(DecoderParseDataFromFileSerie(opt_arg, DecodeIPV4));
+    } else if(strstr(opt_name, "afl-decoder-ipv6") != NULL) {
+        StatsInit();
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        if (strcmp(opt_name, "afl-decoder-ipv6") == 0)
+            exit(DecoderParseDataFromFile(opt_arg, DecodeIPV6));
+        else
+            exit(DecoderParseDataFromFileSerie(opt_arg, DecodeIPV6));
+    } else if(strstr(opt_name, "afl-decoder-ethernet") != NULL) {
+        StatsInit();
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        if (strcmp(opt_name, "afl-decoder-ethernet") == 0)
+            exit(DecoderParseDataFromFile(opt_arg, DecodeEthernet));
+        else
+            exit(DecoderParseDataFromFileSerie(opt_arg, DecodeEthernet));
+    } else if(strstr(opt_name, "afl-decoder-erspan") != NULL) {
+        StatsInit();
+        MpmTableSetup();
+        SpmTableSetup();
+        AppLayerProtoDetectSetup();
+        if (strcmp(opt_name, "afl-decoder-erspan") == 0)
+            exit(DecoderParseDataFromFile(opt_arg, DecodeERSPAN));
+        else
+            exit(DecoderParseDataFromFileSerie(opt_arg, DecodeERSPAN));
+    } else
+#endif
+#ifdef AFLFUZZ_DER
+    if(strcmp(opt_name, "afl-der") == 0) {
+        //printf("arg: //%s\n", opt_arg);
+        exit(DerParseDataFromFile(opt_arg));
+    } else
+#endif
+    {
+        abort();
+    }
+}
+
 static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
 {
     int opt;
@@ -1171,6 +1486,15 @@
         {"afl-rules", required_argument, 0 , 0},
         {"afl-mime", required_argument, 0 , 0},
         {"afl-decoder-ppp", required_argument, 0 , 0},
+        {"afl-decoder-ppp-serie", required_argument, 0 , 0},
+        {"afl-decoder-ethernet", required_argument, 0 , 0},
+        {"afl-decoder-ethernet-serie", required_argument, 0 , 0},
+        {"afl-decoder-erspan", required_argument, 0 , 0},
+        {"afl-decoder-erspan-serie", required_argument, 0 , 0},
+        {"afl-decoder-ipv4", required_argument, 0 , 0},
+        {"afl-decoder-ipv4-serie", required_argument, 0 , 0},
+        {"afl-decoder-ipv6", required_argument, 0 , 0},
+        {"afl-decoder-ipv6-serie", required_argument, 0 , 0},
         {"afl-der", required_argument, 0, 0},
 
 #ifdef BUILD_UNIX_SOCKET
@@ -1312,173 +1636,8 @@
                 if (ParseCommandLinePcapLive(suri, optarg) != TM_ECODE_OK) {
                     return TM_ECODE_FAILED;
                 }
-#ifdef AFLFUZZ_RULES
-            } else if(strcmp((long_opts[option_index]).name, "afl-rules") == 0) {
-                MpmTableSetup();
-                SpmTableSetup();
-                exit(RuleParseDataFromFile(optarg));
-#endif
-#ifdef AFLFUZZ_APPLAYER
-            } else if(strcmp((long_opts[option_index]).name, "afl-http-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterHTPParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_HTTP, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-http") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterHTPParsers();
-                exit(AppLayerParserFromFile(ALPROTO_HTTP, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-tls-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSSLParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_TLS, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-tls") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSSLParsers();
-                exit(AppLayerParserFromFile(ALPROTO_TLS, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-dns-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                RegisterDNSTCPParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_DNS, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-dns") == 0) {
-                //printf("arg: //%s\n", optarg);
-                AppLayerParserSetup();
-                RegisterDNSTCPParsers();
-                exit(AppLayerParserFromFile(ALPROTO_DNS, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-ssh-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                RegisterSSHParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_SSH, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-ssh") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSSHParsers();
-                exit(AppLayerParserFromFile(ALPROTO_SSH, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-ftp-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterFTPParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_FTP, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-ftp") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterFTPParsers();
-                exit(AppLayerParserFromFile(ALPROTO_FTP, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-smtp-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSMTPParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_SMTP, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-smtp") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSMTPParsers();
-                exit(AppLayerParserFromFile(ALPROTO_SMTP, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-smb-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                RegisterSMBParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_SMB, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-smb") == 0) {
-                //printf("arg: //%s\n", optarg);
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                AppLayerParserSetup();
-                RegisterSMBParsers();
-                exit(AppLayerParserFromFile(ALPROTO_SMB, optarg));
-
-            } else if(strcmp((long_opts[option_index]).name, "afl-modbus-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                AppLayerParserSetup();
-                RegisterModbusParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_MODBUS, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-modbus") == 0) {
-                //printf("arg: //%s\n", optarg);
-                AppLayerParserSetup();
-                RegisterModbusParsers();
-                exit(AppLayerParserFromFile(ALPROTO_MODBUS, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-enip-request") == 0) {
-                //printf("arg: //%s\n", optarg);
-                AppLayerParserSetup();
-                RegisterENIPTCPParsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_ENIP, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-enip") == 0) {
-                //printf("arg: //%s\n", optarg);
-                AppLayerParserSetup();
-                RegisterENIPTCPParsers();
-                exit(AppLayerParserFromFile(ALPROTO_ENIP, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-dnp3-request") == 0) {
-                AppLayerParserSetup();
-                RegisterDNP3Parsers();
-                exit(AppLayerParserRequestFromFile(ALPROTO_DNP3, optarg));
-            } else if(strcmp((long_opts[option_index]).name, "afl-dnp3") == 0) {
-                AppLayerParserSetup();
-                RegisterDNP3Parsers();
-                exit(AppLayerParserFromFile(ALPROTO_DNP3, optarg));
-#endif
-#ifdef AFLFUZZ_MIME
-            } else if(strcmp((long_opts[option_index]).name, "afl-mime") == 0) {
-                //printf("arg: //%s\n", optarg);
-                exit(MimeParserDataFromFile(optarg));
-#endif
-#ifdef AFLFUZZ_DECODER
-            } else if(strcmp((long_opts[option_index]).name, "afl-decoder-ppp") == 0) {
-                StatsInit();
-                MpmTableSetup();
-                SpmTableSetup();
-                AppLayerProtoDetectSetup();
-                DefragInit();
-                FlowInitConfig(FLOW_QUIET);
-                //printf("arg: //%s\n", optarg);
-                exit(DecoderParseDataFromFile(optarg, DecodePPP));
-#endif
-#ifdef AFLFUZZ_DER
-            } else if(strcmp((long_opts[option_index]).name, "afl-der") == 0) {
-                //printf("arg: //%s\n", optarg);
-                exit(DerParseDataFromFile(optarg));
-#endif
+            } else if(strncmp((long_opts[option_index]).name, "afl-", 4) == 0) {
+                ParseCommandLineAFL((long_opts[option_index]).name, optarg);
             } else if(strcmp((long_opts[option_index]).name, "simulate-ips") == 0) {
                 SCLogInfo("Setting IPS mode");
                 EngineModeSetIPS();
@@ -2029,6 +2188,89 @@
     return TM_ECODE_OK;
 }
 
+/* initialization code for both the main modes and for
+ * unix socket mode.
+ *
+ * Will be run once per pcap in unix-socket mode */
+void PreRunInit(const int runmode)
+{
+    if (runmode == RUNMODE_UNIX_SOCKET)
+        return;
+
+    StatsInit();
+#ifdef PROFILING
+    SCProfilingRulesGlobalInit();
+    SCProfilingKeywordsGlobalInit();
+    SCProfilingSghsGlobalInit();
+    SCProfilingInit();
+#endif /* PROFILING */
+    DefragInit();
+    FlowInitConfig(FLOW_QUIET);
+    IPPairInitConfig(FLOW_QUIET);
+    StreamTcpInitConfig(STREAM_VERBOSE);
+    AppLayerRegisterGlobalCounters();
+}
+
+/* tasks we need to run before packets start flowing,
+ * but after we dropped privs */
+void PreRunPostPrivsDropInit(const int runmode)
+{
+    if (runmode == RUNMODE_UNIX_SOCKET)
+        return;
+
+    RunModeInitializeOutputs();
+    StatsSetupPostConfig();
+}
+
+/* clean up / shutdown code for both the main modes and for
+ * unix socket mode.
+ *
+ * Will be run once per pcap in unix-socket mode */
+void PostRunDeinit(const int runmode, struct timeval *start_time)
+{
+    if (runmode == RUNMODE_UNIX_SOCKET)
+        return;
+
+    /* needed by FlowForceReassembly */
+    PacketPoolInit();
+
+    /* handle graceful shutdown of the flow engine, it's helper
+     * threads and the packet threads */
+    FlowDisableFlowManagerThread();
+    TmThreadDisableReceiveThreads();
+    FlowForceReassembly();
+    TmThreadDisablePacketThreads();
+    SCPrintElapsedTime(start_time);
+    FlowDisableFlowRecyclerThread();
+
+    /* kill the stats threads */
+    TmThreadKillThreadsFamily(TVT_MGMT);
+    TmThreadClearThreadsFamily(TVT_MGMT);
+
+    /* kill packet threads -- already in 'disabled' state */
+    TmThreadKillThreadsFamily(TVT_PPT);
+    TmThreadClearThreadsFamily(TVT_PPT);
+
+    PacketPoolDestroy();
+
+    /* mgt and ppt threads killed, we can run non thread-safe
+     * shutdown functions */
+    StatsReleaseResources();
+    RunModeShutDown();
+    FlowShutdown();
+    IPPairShutdown();
+    HostCleanup();
+    StreamTcpFreeConfig(STREAM_VERBOSE);
+    DefragDestroy();
+    TmqResetQueues();
+#ifdef PROFILING
+    if (profiling_rules_enabled)
+        SCProfilingDump();
+    SCProfilingDestroy();
+#endif
+}
+
+
 int StartInternalRunMode(SCInstance *suri, int argc, char **argv)
 {
     /* Treat internal running mode */
@@ -2191,6 +2433,8 @@
                             dev[len-1] = '\0';
                         }
                     }
+                    int mtu = GetIfaceMTU(dev);
+                    g_default_mtu = MAX(mtu, g_default_mtu);
 
                     unsigned int iface_max_packet_size = GetIfaceMaxPacketSize(dev);
                     if (iface_max_packet_size > default_packet_size)
@@ -2200,6 +2444,7 @@
                     break;
                 /* fall through */
             default:
+                g_default_mtu = DEFAULT_MTU;
                 default_packet_size = DEFAULT_PACKET_SIZE;
         }
     } else {
@@ -2215,6 +2460,72 @@
 
     return TM_ECODE_OK;
 }
+
+static void PostRunStartedDetectSetup(SCInstance *suri)
+{
+    /* registering signal handlers we use.  We register usr2 here, so that one
+     * can't call it during the first sig load phase or while threads are still
+     * starting up. */
+    if (DetectEngineEnabled() && suri->sig_file == NULL &&
+            suri->delayed_detect == 0)
+        UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
+
+    if (suri->delayed_detect) {
+        /* force 'reload', this will load the rules and swap engines */
+        DetectEngineReload(suri);
+        SCLogNotice("Signature(s) loaded, Detect thread(s) activated.");
+    }
+}
+
+static void PostConfLoadedDetectSetup(SCInstance *suri)
+{
+    DetectEngineCtx *de_ctx = NULL;
+    if (!suri->disabled_detect) {
+        SCClassConfInit();
+        SCReferenceConfInit();
+        SetupDelayedDetect(suri);
+        int mt_enabled = 0;
+        (void)ConfGetBool("multi-detect.enabled", &mt_enabled);
+        int default_tenant = 0;
+        if (mt_enabled)
+            (void)ConfGetBool("multi-detect.default", &default_tenant);
+        if (DetectEngineMultiTenantSetup() == -1) {
+            SCLogError(SC_ERR_INITIALIZATION, "initializing multi-detect "
+                    "detection engine contexts failed.");
+            exit(EXIT_FAILURE);
+        }
+        if ((suri->delayed_detect || (mt_enabled && !default_tenant)) &&
+            (suri->run_mode != RUNMODE_CONF_TEST)) {
+            de_ctx = DetectEngineCtxInitMinimal();
+        } else {
+            de_ctx = DetectEngineCtxInit();
+        }
+        if (de_ctx == NULL) {
+            SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
+                    "context failed.");
+            exit(EXIT_FAILURE);
+        }
+
+#ifdef __SC_CUDA_SUPPORT__
+        if (PatternMatchDefaultMatcher() == MPM_AC_CUDA)
+            CudaVarsSetDeCtx(de_ctx);
+#endif /* __SC_CUDA_SUPPORT__ */
+
+        if (!de_ctx->minimal) {
+            if (LoadSignatures(de_ctx, suri) != TM_ECODE_OK)
+                exit(EXIT_FAILURE);
+            if (suri->run_mode == RUNMODE_ENGINE_ANALYSIS) {
+                exit(EXIT_SUCCESS);
+            }
+        }
+
+        DetectEngineAddToMaster(de_ctx);
+    } else {
+        /* tell the app layer to consider only the log id */
+        RegisterAppLayerGetActiveTxIdFunc(AppLayerTransactionGetActiveLogOnly);
+    }
+}
+
 /**
  * This function is meant to contain code that needs
  * to be run once the configuration has been loaded.
@@ -2316,9 +2627,6 @@
 
     /* Load the Host-OS lookup. */
     SCHInfoLoadFromConfig();
-    if (suri->run_mode != RUNMODE_UNIX_SOCKET) {
-        DefragInit();
-    }
 
     if (suri->run_mode == RUNMODE_ENGINE_ANALYSIS) {
         SCLogInfo("== Carrying out Engine Analysis ==");
@@ -2338,14 +2646,6 @@
     StorageInit();
     CIDRInit();
     SigParsePrepare();
-#ifdef PROFILING
-    if (suri->run_mode != RUNMODE_UNIX_SOCKET) {
-        SCProfilingRulesGlobalInit();
-        SCProfilingKeywordsGlobalInit();
-        SCProfilingSghsGlobalInit();
-        SCProfilingInit();
-    }
-#endif /* PROFILING */
     SCReputationInitCtx();
     SCProtoNameInit();
 
@@ -2397,43 +2697,82 @@
     }
 
     HostInitConfig(HOST_VERBOSE);
-
+#ifdef HAVE_MAGIC
     if (MagicInit() != 0)
         SCReturnInt(TM_ECODE_FAILED);
-
+#endif
     SCAsn1LoadConfig();
 
     CoredumpLoadConfig();
 
+    PreRunInit(suri->run_mode);
+
     SCReturnInt(TM_ECODE_OK);
 }
 
-int main(int argc, char **argv)
+static void SuricataMainLoop(SCInstance *suri)
 {
-    SCInstance suri;
+    while(1) {
+        if (sigterm_count || sigint_count) {
+            suricata_ctl_flags |= SURICATA_STOP;
+        }
+
+        if (suricata_ctl_flags & SURICATA_STOP) {
+            SCLogNotice("Signal Received.  Stopping engine.");
+            break;
+        }
+
+        TmThreadCheckThreadState();
 
-    SCInstanceInit(&suri);
-    suri.progname = argv[0];
+        if (sighup_count > 0) {
+            OutputNotifyFileRotation();
+            sighup_count--;
+        }
 
-    sc_set_caps = FALSE;
+        if (sigusr2_count > 0) {
+            if (suri->sig_file != NULL) {
+                SCLogWarning(SC_ERR_LIVE_RULE_SWAP, "Live rule reload not "
+                        "possible if -s or -S option used at runtime.");
+                sigusr2_count--;
+            } else {
+                if (!(DetectEngineReloadIsStart())) {
+                    DetectEngineReloadStart();
+                    DetectEngineReload(suri);
+                    DetectEngineReloadSetDone();
+                    sigusr2_count--;
+                }
+            }
+
+        } else if (DetectEngineReloadIsStart()) {
+            if (suri->sig_file != NULL) {
+                SCLogWarning(SC_ERR_LIVE_RULE_SWAP, "Live rule reload not "
+                        "possible if -s or -S option used at runtime.");
+                DetectEngineReloadSetDone();
+            } else {
+                DetectEngineReload(suri);
+                DetectEngineReloadSetDone();
+            }
+        }
+
+        usleep(10* 1000);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    SCInstance suri;
+    SCInstanceInit(&suri, argv[0]);
 
     SC_ATOMIC_INIT(engine_stage);
 
     /* initialize the logging subsys */
     SCLogInitLogModule(NULL);
 
-    if (SCSetThreadName("Suricata-Main") < 0) {
-        SCLogWarning(SC_ERR_THREAD_INIT, "Unable to set thread name");
-    }
+    (void)SCSetThreadName("Suricata-Main");
 
     ParseSizeInit();
-
     RunModeRegisterRunModes();
 
-    /* By default use IDS mode, but if nfq or ipfw
-     * are specified, IPS mode will overwrite this */
-    EngineModeSetIDS();
-
 #ifdef OS_WIN32
     /* service initialization */
     if (WindowsInit(argc, argv) != 0) {
@@ -2459,19 +2798,8 @@
             exit(EXIT_FAILURE);
     }
 
-#ifdef __SC_CUDA_SUPPORT__
-    /* Init the CUDA environment */
-    SCCudaInitCudaEnvironment();
-    CudaBufferInit();
-#endif
-
     /* Initializations for global vars, queues, etc (memsets, mutex init..) */
-    GlobalInits();
-    TimeInit();
-    SupportFastPatternForSigMatchTypes();
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        StatsInit();
-    }
+    GlobalsInitPreConfig();
 
     /* Load yaml configuration file if provided. */
     if (LoadYamlConfig(&suri) != TM_ECODE_OK) {
@@ -2488,7 +2816,6 @@
     SCLogLoadConfig(suri.daemon, suri.verbose);
 
     SCPrintVersion();
-
     UtilCpuPrintSummary();
 
     if (ParseInterfacesList(suri.run_mode, suri.pcap_dev) != TM_ECODE_OK) {
@@ -2498,93 +2825,23 @@
     if (PostConfLoadedSetup(&suri) != TM_ECODE_OK) {
         exit(EXIT_FAILURE);
     }
-
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        FlowInitConfig(FLOW_VERBOSE);
-        StreamTcpInitConfig(STREAM_VERBOSE);
-        IPPairInitConfig(IPPAIR_VERBOSE);
-        AppLayerRegisterGlobalCounters();
-    }
-
-    DetectEngineCtx *de_ctx = NULL;
-    if (!suri.disabled_detect) {
-        SCClassConfInit();
-        SCReferenceConfInit();
-        SetupDelayedDetect(&suri);
-        int mt_enabled = 0;
-        (void)ConfGetBool("multi-detect.enabled", &mt_enabled);
-        int default_tenant = 0;
-        if (mt_enabled)
-            (void)ConfGetBool("multi-detect.default", &default_tenant);
-        if (DetectEngineMultiTenantSetup() == -1) {
-            SCLogError(SC_ERR_INITIALIZATION, "initializing multi-detect "
-                    "detection engine contexts failed.");
-            exit(EXIT_FAILURE);
-        }
-        if ((suri.delayed_detect || (mt_enabled && !default_tenant)) &&
-            (suri.run_mode != RUNMODE_CONF_TEST)) {
-            de_ctx = DetectEngineCtxInitMinimal();
-        } else {
-            de_ctx = DetectEngineCtxInit();
-        }
-        if (de_ctx == NULL) {
-            SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
-                    "context failed.");
-            exit(EXIT_FAILURE);
-        }
-
-#ifdef __SC_CUDA_SUPPORT__
-        if (PatternMatchDefaultMatcher() == MPM_AC_CUDA)
-            CudaVarsSetDeCtx(de_ctx);
-#endif /* __SC_CUDA_SUPPORT__ */
-
-        if (!de_ctx->minimal) {
-            if (LoadSignatures(de_ctx, &suri) != TM_ECODE_OK)
-                exit(EXIT_FAILURE);
-            if (suri.run_mode == RUNMODE_ENGINE_ANALYSIS) {
-                exit(EXIT_SUCCESS);
-            }
-        }
-
-        DetectEngineAddToMaster(de_ctx);
-    } else {
-        /* tell the app layer to consider only the log id */
-        RegisterAppLayerGetActiveTxIdFunc(AppLayerTransactionGetActiveLogOnly);
-    }
-
-    SCSetStartTime(&suri);
+    PostConfLoadedDetectSetup(&suri);
 
     SCDropMainThreadCaps(suri.userid, suri.groupid);
-
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        RunModeInitializeOutputs();
-        StatsSetupPostConfig();
-    }
+    PreRunPostPrivsDropInit(suri.run_mode);
 
     if (suri.run_mode == RUNMODE_CONF_TEST){
         SCLogNotice("Configuration provided was successfully loaded. Exiting.");
+#ifdef HAVE_MAGIC
         MagicDeinit();
+#endif
         exit(EXIT_SUCCESS);
     }
 
+    SCSetStartTime(&suri);
     RunModeDispatch(suri.run_mode, suri.runmode_custom_mode);
-
-    /* In Unix socket runmode, Flow manager is started on demand */
     if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        /* Spawn the unix socket manager thread */
-        int unix_socket = ConfUnixSocketIsEnable();
-        if (unix_socket == 1) {
-            UnixManagerThreadSpawn(0);
-#ifdef BUILD_UNIX_SOCKET
-            UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
-                                       UNIX_CMD_TAKE_ARGS);
-            UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
-#endif
-        }
-        /* Spawn the flow manager thread */
-        FlowManagerThreadSpawn();
-        FlowRecyclerThreadSpawn();
-        StatsSpawnThreads();
+        UnixManagerThreadSpawnNonRunmode();
     }
 
     /* Wait till all the threads have been initialized */
@@ -2599,19 +2856,8 @@
 
     /* Un-pause all the paused threads */
     TmThreadContinueThreads();
-    /* registering singal handlers we use.  We register usr2 here, so that one
-     * can't call it during the first sig load phase or while threads are still
-     * starting up. */
-    if (DetectEngineEnabled() && suri.sig_file == NULL &&
-            suri.delayed_detect == 0)
-        UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
-
-    if (suri.delayed_detect) {
-        /* force 'reload', this will load the rules and swap engines */
-        DetectEngineReload(&suri);
-        SCLogNotice("Signature(s) loaded, Detect thread(s) activated.");
-    }
 
+    PostRunStartedDetectSetup(&suri);
 
 #ifdef DBG_MEM_ALLOC
     SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
@@ -2620,181 +2866,17 @@
 #endif
 #endif
 
-    int engine_retval = EXIT_SUCCESS;
-    while(1) {
-        if (sigterm_count || sigint_count) {
-            suricata_ctl_flags |= SURICATA_STOP;
-        }
-
-        if (suricata_ctl_flags & SURICATA_STOP) {
-            SCLogNotice("Signal Received.  Stopping engine.");
-            break;
-        }
-
-        TmThreadCheckThreadState();
-
-        if (sighup_count > 0) {
-            OutputNotifyFileRotation();
-            sighup_count--;
-        }
-
-        if (sigusr2_count > 0) {
-            if (suri.sig_file != NULL) {
-                SCLogWarning(SC_ERR_LIVE_RULE_SWAP, "Live rule reload not "
-                        "possible if -s or -S option used at runtime.");
-                sigusr2_count--;
-            } else {
-                if (!(DetectEngineReloadIsStart())) {
-                    DetectEngineReloadStart();
-                    DetectEngineReload(&suri);
-                    DetectEngineReloadSetDone();
-                    sigusr2_count--;
-                }
-            }
-
-        } else if (DetectEngineReloadIsStart()) {
-            if (suri.sig_file != NULL) {
-                SCLogWarning(SC_ERR_LIVE_RULE_SWAP, "Live rule reload not "
-                        "possible if -s or -S option used at runtime.");
-                DetectEngineReloadSetDone();
-            } else {
-                DetectEngineReload(&suri);
-                DetectEngineReloadSetDone();
-            }
-        }
-
-        usleep(10* 1000);
-    }
+    SuricataMainLoop(&suri);
 
     /* Update the engine stage/status flag */
     (void) SC_ATOMIC_CAS(&engine_stage, SURICATA_RUNTIME, SURICATA_DEINIT);
 
     UnixSocketKillSocketThread();
-
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        /* First we need to disable the flow manager thread */
-        FlowDisableFlowManagerThread();
-    }
-
-
-    /* Disable packet acquisition first */
-    TmThreadDisableReceiveThreads();
-
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        /* we need a packet pool for FlowForceReassembly */
-        PacketPoolInit();
-
-        FlowForceReassembly();
-        /* kill receive threads when they have processed all
-         * flow timeout packets */
-        TmThreadDisablePacketThreads();
-    }
-
-    SCPrintElapsedTime(&suri);
-
-    /* before TmThreadKillThreads, as otherwise that kills it
-     * but more slowly */
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        FlowDisableFlowRecyclerThread();
-    }
-
+    PostRunDeinit(suri.run_mode, &suri.start_time);
     /* kill remaining threads */
     TmThreadKillThreads();
 
+    GlobalsDestroy(&suri);
 
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        /* destroy the packet pool for flow reassembly after all
-         * the other threads are gone. */
-        PacketPoolDestroy();
-
-        StatsReleaseResources();
-        IPPairShutdown();
-        FlowShutdown();
-        StreamTcpFreeConfig(STREAM_VERBOSE);
-    }
-    HostShutdown();
-
-    HTPFreeConfig();
-    HTPAtExitPrintStats();
-
-#ifdef DBG_MEM_ALLOC
-    SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem);
-#ifdef DBG_MEM_ALLOC_SKIP_STARTUP
-    print_mem_flag = 0;
-#endif
-#endif
-
-    SCPidfileRemove(suri.pid_filename);
-
-    AppLayerHtpPrintStats();
-
-    /** TODO this can do into it's own func */
-    de_ctx = DetectEngineGetCurrent();
-    if (de_ctx) {
-        DetectEngineMoveToFreeList(de_ctx);
-        DetectEngineDeReference(&de_ctx);
-    }
-    DetectEnginePruneFreeList();
-
-    AppLayerDeSetup();
-
-    TagDestroyCtx();
-
-    LiveDeviceListClean();
-    RunModeShutDown();
-    OutputDeregisterAll();
-    TimeDeinit();
-    SCProtoNameDeInit();
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        DefragDestroy();
-    }
-    if (!suri.disabled_detect) {
-        SCReferenceConfDeinit();
-        SCClassConfDeinit();
-    }
-    MagicDeinit();
-    TmqhCleanup();
-    TmModuleRunDeInit();
-    ParseSizeDeinit();
-#ifdef HAVE_NSS
-    NSS_Shutdown();
-    PR_Cleanup();
-#endif
-
-#ifdef HAVE_AF_PACKET
-    AFPPeersListClean();
-#endif
-
-#ifdef PROFILING
-    if (suri.run_mode != RUNMODE_UNIX_SOCKET) {
-        if (profiling_rules_enabled)
-            SCProfilingDump();
-        SCProfilingDestroy();
-    }
-#endif
-
-#ifdef OS_WIN32
-	if (daemon) {
-		return 0;
-	}
-#endif /* OS_WIN32 */
-
-    SC_ATOMIC_DESTROY(engine_stage);
-
-#ifdef BUILD_HYPERSCAN
-    MpmHSGlobalCleanup();
-#endif
-
-#ifdef __SC_CUDA_SUPPORT__
-    if (PatternMatchDefaultMatcher() == MPM_AC_CUDA)
-        MpmCudaBufferDeSetup();
-    CudaHandlerFreeProfiles();
-#endif
-    ConfDeInit();
-#ifdef HAVE_LUAJIT
-    LuajitFreeStatesPool();
-#endif
-    SCLogDeInitLogModule();
-    DetectParseFreeRegexes();
-    exit(engine_retval);
+    exit(EXIT_SUCCESS);
 }
diff -Nru suricata-3.2/src/suricata-common.h suricata-3.2.1/src/suricata-common.h
--- suricata-3.2/src/suricata-common.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/suricata-common.h	2017-02-15 08:54:12.000000000 +0100
@@ -225,15 +225,8 @@
 #endif
 #endif
 
-#if CPPCHECK==1
-#define BUG_ON(x) if (((x))) exit(1)
-#else
-#ifdef HAVE_ASSERT_H
-#include <assert.h>
-#define BUG_ON(x) assert(!(x))
-#else
-#define BUG_ON(x)
-#endif
+#ifdef HAVE_MAGIC
+#include <magic.h>
 #endif
 
 /* we need this to stringify the defines which are supplied at compiletime see:
@@ -241,6 +234,23 @@
 #define xstr(s) str(s)
 #define str(s) #s
 
+#if CPPCHECK==1
+    #define BUG_ON(x) if (((x))) exit(1)
+#else
+    #if defined HAVE_ASSERT_H && !defined NDEBUG
+    #include <assert.h>
+        #define BUG_ON(x) assert(!(x))
+    #else
+        #define BUG_ON(x) do {      \
+            if (((x))) {            \
+                fprintf(stderr, "BUG at %s:%d(%s)\n", __FILE__, __LINE__, __func__);    \
+                fprintf(stderr, "Code: '%s'\n", xstr((x)));                             \
+                exit(EXIT_FAILURE); \
+            }                       \
+        } while(0)
+    #endif
+#endif
+
 /** type for the internal signature id. Since it's used in the matching engine
  *  extensively keeping this as small as possible reduces the overall memory
  *  footprint of the engine. Set to uint32_t if the engine needs to support
@@ -309,10 +319,13 @@
 #define MAX(x, y) (((x)<(y))?(y):(x))
 #endif
 
+#define BIT_U8(n)  ((uint8_t)(1 << (n)))
 #define BIT_U16(n) ((uint16_t)(1 << (n)))
 #define BIT_U32(n) (1UL  << (n))
 #define BIT_U64(n) (1ULL << (n))
 
+#define WARN_UNUSED __attribute__((warn_unused_result))
+
 typedef enum PacketProfileDetectId_ {
     PROF_DETECT_IPONLY,
     PROF_DETECT_RULES,
diff -Nru suricata-3.2/src/suricata.h suricata-3.2.1/src/suricata.h
--- suricata-3.2/src/suricata.h	2016-11-29 18:16:48.000000000 +0100
+++ suricata-3.2.1/src/suricata.h	2017-02-15 08:54:17.000000000 +0100
@@ -71,7 +71,7 @@
 
 /* the name of our binary */
 #define PROG_NAME "Suricata"
-#define PROG_VER "3.2"
+#define PROG_VER "3.2.1"
 
 /* workaround SPlint error (don't know __gnuc_va_list) */
 #ifdef S_SPLINT_S
@@ -169,7 +169,7 @@
 
 
 /* memset to zeros, and mutex init! */
-void GlobalInits();
+void GlobalsInitPreConfig();
 
 extern volatile uint8_t suricata_ctl_flags;
 
@@ -195,5 +195,9 @@
 
 extern int run_mode;
 
+void PreRunInit(const int runmode);
+void PreRunPostPrivsDropInit(const int runmode);
+void PostRunDeinit(const int runmode, struct timeval *start_time);
+
 #endif /* __SURICATA_H__ */
 
diff -Nru suricata-3.2/src/tm-threads.c suricata-3.2.1/src/tm-threads.c
--- suricata-3.2/src/tm-threads.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/tm-threads.c	2017-02-15 08:54:12.000000000 +0100
@@ -1521,6 +1521,64 @@
     return;
 }
 
+/** \internal
+ *
+ *  \brief make sure that all packet threads are done processing their
+ *         in-flight packets
+ */
+static void TmThreadDrainPacketThreads(void)
+{
+    /* value in seconds */
+#define THREAD_KILL_MAX_WAIT_TIME 60
+    /* value in microseconds */
+#define WAIT_TIME 1000
+
+    uint64_t total_wait_time = 0;
+
+    ThreadVars *tv = NULL;
+
+again:
+    if (total_wait_time > (THREAD_KILL_MAX_WAIT_TIME * 1000000)) {
+        SCLogWarning(SC_ERR_SHUTDOWN, "unable to get all packet threads "
+                "to process their packets in time");
+        return;
+    }
+
+    SCMutexLock(&tv_root_lock);
+
+    /* all receive threads are part of packet processing threads */
+    tv = tv_root[TVT_PPT];
+
+    while (tv) {
+        if (tv->inq != NULL) {
+            /* we wait till we dry out all the inq packets, before we
+             * kill this thread.  Do note that you should have disabled
+             * packet acquire by now using TmThreadDisableReceiveThreads()*/
+            if (!(strlen(tv->inq->name) == strlen("packetpool") &&
+                        strcasecmp(tv->inq->name, "packetpool") == 0)) {
+                PacketQueue *q = &trans_q[tv->inq->id];
+                if (q->len != 0) {
+                    SCMutexUnlock(&tv_root_lock);
+
+                    total_wait_time += WAIT_TIME;
+
+                    /* don't sleep while holding a lock */
+                    usleep(WAIT_TIME);
+                    goto again;
+                }
+            }
+        }
+
+        tv = tv->next;
+    }
+
+    SCMutexUnlock(&tv_root_lock);
+    return;
+
+#undef THREAD_KILL_MAX_WAIT_TIME
+#undef WAIT_TIME
+}
+
 /**
  *  \brief Disable all threads having the specified TMs.
  *
@@ -1618,6 +1676,11 @@
 
     SCMutexUnlock(&tv_root_lock);
 
+    /* finally wait for all packet threads to have
+     * processed all of their 'live' packets so we
+     * don't process the last live packets together
+     * with FFR packets */
+    TmThreadDrainPacketThreads();
     return;
 }
 
@@ -1635,6 +1698,8 @@
 
     ThreadVars *tv = NULL;
 
+    /* first drain all packet threads of their packets */
+    TmThreadDrainPacketThreads();
 again:
     SCMutexLock(&tv_root_lock);
 
diff -Nru suricata-3.2/src/unix-manager.c suricata-3.2.1/src/unix-manager.c
--- suricata-3.2/src/unix-manager.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/unix-manager.c	2017-02-15 08:54:12.000000000 +0100
@@ -31,8 +31,8 @@
 
 #include "util-privs.h"
 #include "util-debug.h"
+#include "util-device.h"
 #include "util-signal.h"
-
 #include "util-buffer.h"
 
 #include <sys/un.h>
@@ -97,7 +97,7 @@
     int len;
     int ret;
     int on = 1;
-    char *sockettarget = NULL;
+    char sockettarget[PATH_MAX];
     char *socketname;
 
     this->start_timestamp = time(NULL);
@@ -108,42 +108,39 @@
     TAILQ_INIT(&this->tasks);
     TAILQ_INIT(&this->clients);
 
+    int check_dir = 0;
     if (ConfGet("unix-command.filename", &socketname) == 1) {
         if (PathIsAbsolute(socketname)) {
-            sockettarget = SCStrdup(socketname);
-            if (unlikely(sockettarget == NULL)) {
-                SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate socket name");
-                return 0;
-            }
+            strlcpy(sockettarget, socketname, sizeof(sockettarget));
         } else {
-            int socketlen = strlen(SOCKET_PATH) + strlen(socketname) + 2;
-            sockettarget = SCMalloc(socketlen);
-            if (unlikely(sockettarget == NULL)) {
-                SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate socket name");
-                return 0;
-            }
-            snprintf(sockettarget, socketlen, "%s/%s", SOCKET_PATH, socketname);
+            snprintf(sockettarget, sizeof(sockettarget), "%s/%s",
+                    SOCKET_PATH, socketname);
+            check_dir = 1;
+        }
+    } else {
+        strlcpy(sockettarget, SOCKET_TARGET, sizeof(sockettarget));
+        check_dir = 1;
+    }
+    SCLogInfo("Using unix socket file '%s'", sockettarget);
 
-            /* Create socket dir */
+    if (check_dir) {
+        struct stat stat_buf;
+        /* coverity[toctou] */
+        if (stat(SOCKET_PATH, &stat_buf) != 0) {
+            /* coverity[toctou] */
             ret = mkdir(SOCKET_PATH, S_IRWXU|S_IXGRP|S_IRGRP);
-            if ( ret != 0 ) {
+            if (ret != 0) {
                 int err = errno;
                 if (err != EEXIST) {
-                    SCFree(sockettarget);
-                    SCLogError(SC_ERR_OPENING_FILE,
-                            "Cannot create socket directory %s: %s", SOCKET_PATH, strerror(err));
+                    SCLogError(SC_ERR_INITIALIZATION,
+                            "Cannot create socket directory %s: %s",
+                            SOCKET_PATH, strerror(err));
                     return 0;
                 }
+            } else {
+                SCLogInfo("Created socket directory %s",
+                        SOCKET_PATH);
             }
-
-        }
-        SCLogInfo("Using unix socket file '%s'", sockettarget);
-    }
-    if (sockettarget == NULL) {
-        sockettarget = SCStrdup(SOCKET_TARGET);
-        if (unlikely(sockettarget == NULL)) {
-            SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate socket name");
-            return 0;
         }
     }
 
@@ -162,7 +159,6 @@
         SCLogWarning(SC_ERR_OPENING_FILE,
                      "Unix Socket: unable to create UNIX socket %s: %s",
                      addr.sun_path, strerror(errno));
-        SCFree(sockettarget);
         return 0;
     }
     this->select_max = this->socket + 1;
@@ -194,7 +190,6 @@
         SCLogWarning(SC_ERR_INITIALIZATION,
                      "Unix socket: UNIX socket bind(%s) error: %s",
                      sockettarget, strerror(errno));
-        SCFree(sockettarget);
         return 0;
     }
 
@@ -203,10 +198,8 @@
         SCLogWarning(SC_ERR_INITIALIZATION,
                      "Command server: UNIX socket listen() error: %s",
                      strerror(errno));
-        SCFree(sockettarget);
         return 0;
     }
-    SCFree(sockettarget);
     return 1;
 }
 
@@ -908,16 +901,18 @@
 
     if (UnixNew(&command) == 0) {
         int failure_fatal = 0;
-        SCLogError(SC_ERR_INITIALIZATION,
-                   "Unable to create unix command socket");
         if (ConfGetBool("engine.init-failure-fatal", &failure_fatal) != 1) {
             SCLogDebug("ConfGetBool could not load the value.");
         }
         SCFree(utd);
         if (failure_fatal) {
+            SCLogError(SC_ERR_INITIALIZATION,
+                    "Unable to create unix command socket");
             exit(EXIT_FAILURE);
         } else {
-            return TM_ECODE_FAILED;
+            SCLogWarning(SC_ERR_INITIALIZATION,
+                    "Unable to create unix command socket");
+            return TM_ECODE_OK;
         }
     }
 
@@ -1016,6 +1011,19 @@
     return;
 }
 
+// TODO can't think of a good name
+void UnixManagerThreadSpawnNonRunmode(void)
+{
+    /* Spawn the unix socket manager thread */
+    int unix_socket = ConfUnixSocketIsEnable();
+    if (unix_socket == 1) {
+        UnixManagerThreadSpawn(0);
+        UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
+                UNIX_CMD_TAKE_ARGS);
+        UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
+    }
+}
+
 /**
  * \brief Used to kill unix manager thread(s).
  *
@@ -1069,6 +1077,11 @@
 {
     return;
 }
+
+void UnixManagerThreadSpawnNonRunmode(void)
+{
+    return;
+}
 
 #endif /* BUILD_UNIX_SOCKET */
 
diff -Nru suricata-3.2/src/unix-manager.h suricata-3.2.1/src/unix-manager.h
--- suricata-3.2/src/unix-manager.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/unix-manager.h	2017-02-15 08:54:12.000000000 +0100
@@ -36,7 +36,6 @@
 void UnixManagerThreadSpawn(int mode);
 void UnixSocketKillSocketThread(void);
 
-
 #ifdef BUILD_UNIX_SOCKET
 TmEcode UnixManagerRegisterCommand(const char * keyword,
         TmEcode (*Func)(json_t *, json_t *, void *),
@@ -47,5 +46,6 @@
 #endif
 
 void TmModuleUnixManagerRegister(void);
+void UnixManagerThreadSpawnNonRunmode(void);
 
 #endif /* UNIX_MANAGER_H */
diff -Nru suricata-3.2/src/util-debug.c suricata-3.2.1/src/util-debug.c
--- suricata-3.2/src/util-debug.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-debug.c	2017-02-15 08:54:12.000000000 +0100
@@ -300,29 +300,19 @@
         blue = "\x1b[34m";
         reset = "\x1b[0m";
     }
-
     /* no of characters_written(cw) by snprintf */
     int cw = 0;
 
-    if (sc_log_module_initialized != 1) {
-#ifdef DEBUG
-        printf("Logging module not initialized.  Call SCLogInitLogModule(), "
-               "before using the logging API\n");
-#endif
-        return SC_ERR_LOG_MODULE_NOT_INIT;
-    }
+    BUG_ON(sc_log_module_initialized != 1);
 
-    char *temp_fmt = strdup(log_format);
-    if (unlikely(temp_fmt == NULL)) {
-        return SC_ERR_MEM_ALLOC;
-    }
-    char *temp_fmt_h = temp_fmt;
+    /* make a copy of the format string as it will be modified below */
+    char local_format[strlen(log_format) + 1];
+    strlcpy(local_format, log_format, sizeof(local_format));
+    char *temp_fmt = local_format;
     char *substr = temp_fmt;
 
 	while ( (temp_fmt = index(temp_fmt, SC_LOG_FMT_PREFIX)) ) {
         if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
-            if (temp_fmt_h != NULL)
-                SCFree(temp_fmt_h);
             return SC_OK;
         }
         switch(temp_fmt[1]) {
@@ -338,7 +328,7 @@
                               tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
                               tms->tm_sec, reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -350,7 +340,7 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s%u%s", substr, yellow, getpid(), reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -362,12 +352,13 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s%lu%s", substr, yellow, SCGetThreadIdLong(), reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
                 substr++;
                 break;
+
             case SC_LOG_FMT_TM:
                 temp_fmt[0] = '\0';
 /* disabled to prevent dead lock:
@@ -382,12 +373,13 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s", substr, "N/A");
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
                 substr++;
                 break;
+
             case SC_LOG_FMT_LOG_LEVEL:
                 temp_fmt[0] = '\0';
                 s = SCMapEnumValueToName(log_level, sc_log_level_map);
@@ -409,7 +401,7 @@
                                   "%s%s", substr, "INVALID");
                 }
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -421,7 +413,7 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s%s%s", substr, blue, file, reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -433,7 +425,7 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s%u%s", substr, green, line, reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -445,7 +437,7 @@
                 cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                               "%s%s%s%s", substr, green, function, reset);
                 if (cw < 0)
-                    goto error;
+                    return SC_ERR_SPRINTF;
                 temp += cw;
                 temp_fmt++;
                 substr = temp_fmt;
@@ -456,29 +448,25 @@
         temp_fmt++;
 	}
     if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
-        if (temp_fmt_h != NULL)
-            SCFree(temp_fmt_h);
         return SC_OK;
     }
     cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s", substr);
-    if (cw < 0)
-        goto error;
+    if (cw < 0) {
+        return SC_ERR_SPRINTF;
+    }
     temp += cw;
     if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
-        if (temp_fmt_h != NULL)
-            SCFree(temp_fmt_h);
         return SC_OK;
     }
 
     if (error_code != SC_OK) {
         cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
                 "[%sERRCODE%s: %s%s%s(%s%d%s)] - ", yellow, reset, red, SCErrorToString(error_code), reset, yellow, error_code, reset);
-        if (cw < 0)
-            goto error;
+        if (cw < 0) {
+            return SC_ERR_SPRINTF;
+        }
         temp += cw;
         if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
-            if (temp_fmt_h != NULL)
-                SCFree(temp_fmt_h);
             return SC_OK;
         }
     }
@@ -489,17 +477,14 @@
     else if (log_level <= SC_LOG_NOTICE)
         hi = yellow;
     cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s", hi, message, reset);
-    if (cw < 0)
-        goto error;
+    if (cw < 0) {
+        return SC_ERR_SPRINTF;
+    }
     temp += cw;
     if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
-        if (temp_fmt_h != NULL)
-            SCFree(temp_fmt_h);
         return SC_OK;
     }
 
-    SCFree(temp_fmt_h);
-
     if (sc_log_config->op_filter_regex != NULL) {
 #define MAX_SUBSTRINGS 30
         int ov[MAX_SUBSTRINGS];
@@ -514,11 +499,6 @@
     }
 
     return SC_OK;
-
- error:
-    if (temp_fmt_h != NULL)
-        SCFree(temp_fmt_h);
-    return SC_ERR_SPRINTF;
 }
 
 static void SCLogReopen(SCLogOPIfaceCtx *op_iface_ctx)
diff -Nru suricata-3.2/src/util-decode-mime.c suricata-3.2.1/src/util-decode-mime.c
--- suricata-3.2/src/util-decode-mime.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-decode-mime.c	2017-02-15 08:54:12.000000000 +0100
@@ -2645,11 +2645,11 @@
 
         while (1) {
             int done = 0;
-            size_t result = fread(&buffer, 1, sizeof(buffer), fp);
-            if (result < sizeof(buffer))
+            size_t size = fread(&buffer, 1, sizeof(buffer), fp);
+            if (size < sizeof(buffer))
                 done = 1;
 
-            (void) MimeDecParseLine(buffer, result, 1, state);
+            (void) MimeDecParseLine(buffer, size, 1, state);
 
             if (done)
                 break;
diff -Nru suricata-3.2/src/util-error.c suricata-3.2.1/src/util-error.c
--- suricata-3.2/src/util-error.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-error.c	2017-02-15 08:54:12.000000000 +0100
@@ -333,6 +333,8 @@
         CASE_CODE (SC_ERR_DNP3_CONFIG);
         CASE_CODE (SC_ERR_DIR_OPEN);
         CASE_CODE(SC_WARN_REMOVE_FILE);
+        CASE_CODE (SC_ERR_NO_MAGIC_SUPPORT);
+        CASE_CODE (SC_ERR_REDIS);
     }
 
     return "UNKNOWN_ERROR";
diff -Nru suricata-3.2/src/util-error.h suricata-3.2.1/src/util-error.h
--- suricata-3.2/src/util-error.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-error.h	2017-02-15 08:54:12.000000000 +0100
@@ -323,6 +323,8 @@
     SC_ERR_DNP3_CONFIG,
     SC_ERR_DIR_OPEN,
     SC_WARN_REMOVE_FILE,
+    SC_ERR_NO_MAGIC_SUPPORT,
+    SC_ERR_REDIS,
 } SCError;
 
 const char *SCErrorToString(SCError);
diff -Nru suricata-3.2/src/util-file.c suricata-3.2.1/src/util-file.c
--- suricata-3.2/src/util-file.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-file.c	2017-02-15 08:54:12.000000000 +0100
@@ -267,12 +267,12 @@
 }
 
 /**
- *  \brief get the size of the file
+ *  \brief get the size of the file data
  *
  *  This doesn't reflect how much of the file we have in memory, just the
- *  total size tracked so far.
+ *  total size of filedata so far.
  */
-uint64_t FileSize(const File *file)
+uint64_t FileDataSize(const File *file)
 {
     if (file != NULL && file->sb != NULL) {
         SCLogDebug("returning %"PRIu64,
@@ -283,10 +283,24 @@
     return 0;
 }
 
+/**
+ *  \brief get the size of the file
+ *
+ *  This doesn't reflect how much of the file we have in memory, just the
+ *  total size of file so far.
+ */
+uint64_t FileTrackedSize(const File *file)
+{
+    if (file != NULL) {
+        return file->size;
+    }
+    return 0;
+}
+
 static int FilePruneFile(File *file)
 {
     SCEnter();
-
+#ifdef HAVE_MAGIC
     if (!(file->flags & FILE_NOMAGIC)) {
         /* need magic but haven't set it yet, bail out */
         if (file->magic == NULL)
@@ -296,10 +310,10 @@
     } else {
         SCLogDebug("file->flags & FILE_NOMAGIC == true");
     }
-
+#endif
     uint64_t left_edge = file->content_stored;
     if (file->flags & FILE_NOSTORE) {
-        left_edge = FileSize(file);
+        left_edge = FileDataSize(file);
     }
     if (file->flags & FILE_USE_DETECT) {
         left_edge = MIN(left_edge, file->content_inspected);
@@ -309,7 +323,7 @@
         StreamingBufferSlideToOffset(file->sb, left_edge);
     }
 
-    if (left_edge != FileSize(file)) {
+    if (left_edge != FileDataSize(file)) {
         SCReturnInt(0);
     }
 
@@ -443,11 +457,11 @@
 
     if (ff->name != NULL)
         SCFree(ff->name);
-
+#ifdef HAVE_MAGIC
     /* magic returned by libmagic is strdup'd by MagicLookup. */
     if (ff->magic != NULL)
         SCFree(ff->magic);
-
+#endif
     if (ff->sb != NULL) {
         StreamingBufferFree(ff->sb);
     }
@@ -516,7 +530,7 @@
 
     if (ff->flags & FILE_NOSTORE) {
         if (ff->state == FILE_STATE_OPENED &&
-            FileSize(ff) >= (uint64_t)FileMagicSize())
+            FileDataSize(ff) >= (uint64_t)FileMagicSize())
         {
             SCReturnInt(1);
         }
@@ -565,6 +579,8 @@
         SCReturnInt(-1);
     }
 
+    ffc->tail->size += data_len;
+
     if (ffc->tail->state != FILE_STATE_OPENED) {
         if (ffc->tail->flags & FILE_NOSTORE) {
             SCReturnInt(-2);
@@ -574,19 +590,23 @@
 
     if (FileStoreNoStoreCheck(ffc->tail) == 1) {
 #ifdef HAVE_NSS
+        int hash_done = 0;
         /* no storage but forced hashing */
         if (ffc->tail->md5_ctx) {
             HASH_Update(ffc->tail->md5_ctx, data, data_len);
-            SCReturnInt(0);
+            hash_done = 1;
         }
         if (ffc->tail->sha1_ctx) {
             HASH_Update(ffc->tail->sha1_ctx, data, data_len);
-            SCReturnInt(0);
+            hash_done = 1;
         }
         if (ffc->tail->sha256_ctx) {
             HASH_Update(ffc->tail->sha256_ctx, data, data_len);
-            SCReturnInt(0);
+            hash_done = 1;
         }
+
+        if (hash_done)
+            SCReturnInt(0);
 #endif
         if (g_file_force_tracking || (!(ffc->tail->flags & FILE_NOTRACK)))
             SCReturnInt(0);
@@ -695,11 +715,12 @@
     FileContainerAdd(ffc, ff);
 
     if (data != NULL) {
+        ff->size += data_len;
         if (AppendData(ff, data, data_len) != 0) {
             ff->state = FILE_STATE_ERROR;
             SCReturnPtr(NULL, "File");
         }
-        SCLogDebug("file size is now %"PRIu64, FileSize(ff));
+        SCLogDebug("file size is now %"PRIu64, FileTrackedSize(ff));
     }
 
     SCReturnPtr(ff, "File");
@@ -719,6 +740,7 @@
     }
 
     if (data != NULL) {
+        ff->size += data_len;
         if (ff->flags & FILE_NOSTORE) {
 #ifdef HAVE_NSS
             /* no storage but hashing */
@@ -1026,7 +1048,7 @@
     SCLogDebug("not storing this file");
     ff->flags |= FILE_NOSTORE;
 
-    if (ff->state == FILE_STATE_OPENED && FileSize(ff) >= (uint64_t)FileMagicSize()) {
+    if (ff->state == FILE_STATE_OPENED && FileDataSize(ff) >= (uint64_t)FileMagicSize()) {
         if (g_file_force_md5 == 0 && g_file_force_sha1 == 0 && g_file_force_sha256 == 0
                 && g_file_force_tracking == 0) {
             (void)FileCloseFilePtr(ff, NULL, 0,
diff -Nru suricata-3.2/src/util-file.h suricata-3.2.1/src/util-file.h
--- suricata-3.2/src/util-file.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-file.h	2017-02-15 08:54:12.000000000 +0100
@@ -67,7 +67,9 @@
     uint64_t txid;                  /**< tx this file is part of */
     uint32_t file_id;
     uint8_t *name;
+#ifdef HAVE_MAGIC
     char *magic;
+#endif
     struct File_ *next;
 #ifdef HAVE_NSS
     HASHContext *md5_ctx;
@@ -80,6 +82,7 @@
     uint64_t content_inspected;     /**< used in pruning if FILE_USE_DETECT
                                      *   flag is set */
     uint64_t content_stored;
+    uint64_t size;
 } File;
 
 typedef struct FileContainer_ {
@@ -211,7 +214,8 @@
 
 void FileTruncateAllOpenFiles(FileContainer *);
 
-uint64_t FileSize(const File *file);
+uint64_t FileDataSize(const File *file);
+uint64_t FileTrackedSize(const File *file);
 
 uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction);
 
diff -Nru suricata-3.2/src/util-logopenfile.c suricata-3.2.1/src/util-logopenfile.c
--- suricata-3.2/src/util-logopenfile.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-logopenfile.c	2017-02-15 08:54:12.000000000 +0100
@@ -280,6 +280,15 @@
         log_ctx->pcie_fp = SCLogOpenPcieFp(log_ctx, log_path, append);
         if (log_ctx->pcie_fp == NULL)
             return -1; // Error already logged by Open...Fp routine
+#ifdef HAVE_LIBHIREDIS
+    } else if (strcasecmp(filetype, "redis") == 0) {
+        ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
+        if (SCConfLogOpenRedis(redis_node, log_ctx) < 0) {
+            SCLogError(SC_ERR_REDIS, "failed to open redis output");
+            return -1;
+        }
+        log_ctx->type = LOGFILE_TYPE_REDIS;
+#endif
     } else {
         SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid entry for "
                    "%s.filetype.  Expected \"regular\" (default), \"unix_stream\", "
@@ -592,10 +601,10 @@
             file_ctx->redis_setup.batch_count++;
         }
     } else {
-        redisReply *reply = redisCommand(file_ctx->redis, "%s %s %s",
+        redisReply *reply = redisCommand(file_ctx->redis, "%s %s %b",
                 file_ctx->redis_setup.command,
                 file_ctx->redis_setup.key,
-                string);
+                string, string_len);
 
         /*  We may lose the reply if disconnection happens! */
         if (reply) {
diff -Nru suricata-3.2/src/util-lua-common.c suricata-3.2.1/src/util-lua-common.c
--- suricata-3.2/src/util-lua-common.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-lua-common.c	2017-02-15 08:54:12.000000000 +0100
@@ -248,6 +248,37 @@
 }
 
 /** \internal
+ *  \brief fill lua stack with flow has alerts
+ *  \param luastate the lua state
+ *  \param flow flow
+ *  \retval cnt number of data items placed on the stack
+ *
+ *  Places alerts (bool)
+ */
+static int LuaCallbackHasAlertsPushToStackFromFlow(lua_State *luastate, const Flow *flow)
+{
+    lua_pushboolean(luastate, FlowHasAlerts(flow));
+
+    return 1;
+}
+
+/** \internal
+ *  \brief Wrapper for getting flow has alerts info into a lua script
+ *  \retval cnt number of items placed on the stack
+ */
+static int LuaCallbackFlowHasAlerts(lua_State *luastate)
+{
+    int r = 0;
+    Flow *flow = LuaStateGetFlow(luastate);
+    if (flow == NULL)
+        return LuaCallbackError(luastate, "internal error: no flow");
+
+    r = LuaCallbackHasAlertsPushToStackFromFlow(luastate, flow);
+
+    return r;
+}
+
+/** \internal
  *  \brief fill lua stack with header info
  *  \param luastate the lua state
  *  \param p packet
@@ -650,8 +681,14 @@
     lua_pushnumber(luastate, file->file_id);
     lua_pushnumber(luastate, file->txid);
     lua_pushlstring(luastate, (char *)file->name, file->name_len);
-    lua_pushnumber(luastate, FileSize(file));
-    lua_pushstring (luastate, file->magic);
+    lua_pushnumber(luastate, FileTrackedSize(file));
+    lua_pushstring (luastate,
+#ifdef HAVE_MAGIC
+                    file->magic
+#else
+                    "nomagic"
+#endif
+                    );
     lua_pushstring(luastate, md5ptr);
     lua_pushstring(luastate, sha1ptr);
     lua_pushstring(luastate, sha256ptr);
@@ -762,6 +799,8 @@
     lua_setglobal(luastate, "SCFlowAppLayerProto");
     lua_pushcfunction(luastate, LuaCallbackStatsFlow);
     lua_setglobal(luastate, "SCFlowStats");
+    lua_pushcfunction(luastate, LuaCallbackFlowHasAlerts);
+    lua_setglobal(luastate, "SCFlowHasAlerts");
 
     lua_pushcfunction(luastate, LuaCallbackStreamingBuffer);
     lua_setglobal(luastate, "SCStreamingBuffer");
diff -Nru suricata-3.2/src/util-lua-dns.c suricata-3.2.1/src/util-lua-dns.c
--- suricata-3.2/src/util-lua-dns.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-lua-dns.c	2017-02-15 08:54:12.000000000 +0100
@@ -214,13 +214,17 @@
             ptr = (uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry) + answer->fqdn_len);
             if (answer->type == DNS_RECORD_TYPE_A) {
                 char a[16] = "";
-                PrintInet(AF_INET, (const void *)ptr, a, sizeof(a));
+                if (answer->data_len == 4) {
+                    PrintInet(AF_INET, (const void *)ptr, a, sizeof(a));
+                }
                 lua_pushstring(luastate, "addr");
                 LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a));
                 lua_settable(luastate, -3);
             } else if (answer->type == DNS_RECORD_TYPE_AAAA) {
-                char a[46];
-                PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a));
+                char a[46] = "";
+                if (answer->data_len == 16) {
+                    PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a));
+                }
                 lua_pushstring(luastate, "addr");
                 LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a));
                 lua_settable(luastate, -3);
diff -Nru suricata-3.2/src/util-magic.c suricata-3.2.1/src/util-magic.c
--- suricata-3.2/src/util-magic.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-magic.c	2017-02-15 08:54:12.000000000 +0100
@@ -28,10 +28,11 @@
  */
 
 #include "suricata-common.h"
+
+#ifdef HAVE_MAGIC
 #include "conf.h"
 
 #include "util-unittest.h"
-#include <magic.h>
 
 static magic_t g_magic_ctx = NULL;
 static SCMutex g_magic_lock;
@@ -654,10 +655,11 @@
 }
 
 #endif /* UNITTESTS */
-
+#endif
 
 void MagicRegisterTests(void)
 {
+#ifdef HAVE_MAGIC
 #ifdef UNITTESTS
     UtRegisterTest("MagicInitTest01", MagicInitTest01);
     UtRegisterTest("MagicInitTest02", MagicInitTest02);
@@ -675,4 +677,6 @@
     UtRegisterTest("MagicDetectTest10ValgrindError",
                    MagicDetectTest10ValgrindError);
 #endif /* UNITTESTS */
+#endif /* HAVE_MAGIC */
 }
+
diff -Nru suricata-3.2/src/util-magic.h suricata-3.2.1/src/util-magic.h
--- suricata-3.2/src/util-magic.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-magic.h	2017-02-15 08:54:12.000000000 +0100
@@ -24,12 +24,12 @@
 #ifndef __UTIL_MAGIC_H__
 #define __UTIL_MAGIC_H__
 
-#include <magic.h>
-
+#ifdef HAVE_MAGIC
 int MagicInit(void);
 void MagicDeinit(void);
 char *MagicGlobalLookup(const uint8_t *, uint32_t);
 char *MagicThreadLookup(magic_t *, const uint8_t *, uint32_t);
+#endif
 void MagicRegisterTests(void);
 
 #endif /* __UTIL_MAGIC_H__ */
diff -Nru suricata-3.2/src/util-mpm-ac-bs.c suricata-3.2.1/src/util-mpm-ac-bs.c
--- suricata-3.2/src/util-mpm-ac-bs.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-mpm-ac-bs.c	2017-02-15 08:54:12.000000000 +0100
@@ -719,7 +719,6 @@
         uint16_t *curr_loc = (uint16_t *)ctx->state_table_mod;
         uint16_t *no_of_entries = NULL;
         uint16_t *ascii_codes = NULL;
-        state = 0;
         uint16_t ascii_code = 0;
         uint16_t k = 0;
         for (state = 0; state < ctx->state_count; state++) {
@@ -794,7 +793,6 @@
         uint32_t *curr_loc = (uint32_t *)ctx->state_table_mod;
         uint32_t *no_of_entries = NULL;
         uint32_t *ascii_codes = NULL;
-        state = 0;
         uint32_t ascii_code = 0;
         uint32_t k = 0;
         for (state = 0; state < ctx->state_count; state++) {
@@ -1192,7 +1190,6 @@
                     int low = 0;
                     int high = no_of_entries;
                     int mid;
-                    state = 0;
                     while (low <= high) {
                         mid = (low + high) / 2;
                         if (ascii_codes[mid] == buf_local) {
@@ -1276,7 +1273,6 @@
                     int low = 0;
                     int high = no_of_entries;
                     int mid;
-                    state = 0;
                     while (low <= high) {
                         mid = (low + high) / 2;
                         if (ascii_codes[mid] == buf_local) {
diff -Nru suricata-3.2/src/util-mpm-ac.c suricata-3.2.1/src/util-mpm-ac.c
--- suricata-3.2/src/util-mpm-ac.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-mpm-ac.c	2017-02-15 08:54:12.000000000 +0100
@@ -122,6 +122,28 @@
 
 /**
  * \internal
+ * \brief Check if size_t multiplication would overflow and perform operation
+ *        if safe. In case of an overflow we exit().
+ *
+ * \param a First size_t value to multiplicate.
+ * \param b Second size_t value to multiplicate.
+ *
+ * \retval The product of a and b, guaranteed to not overflow.
+ */
+static inline size_t SCACCheckSafeSizetMult(size_t a, size_t b)
+{
+    /* check for safety of multiplication operation */
+    if (b > 0 && a > SIZE_MAX / b) {
+        SCLogError(SC_ERR_MEM_ALLOC, "%"PRIuMAX" * %"PRIuMAX" > %"
+                   PRIuMAX" would overflow size_t calculating buffer size",
+                   (uintmax_t) a, (uintmax_t) b, (uintmax_t) SIZE_MAX);
+        exit(EXIT_FAILURE);
+    }
+    return a * b;
+}
+
+/**
+ * \internal
  * \brief Initialize a new state in the goto and output tables.
  *
  * \param mpm_ctx Pointer to the mpm context.
@@ -130,12 +152,13 @@
  */
 static inline int SCACReallocState(SCACCtx *ctx, uint32_t cnt)
 {
-    void *ptmp;
-    int size = 0;
+    void *ptmp = NULL;
+    size_t size = 0;
 
     /* reallocate space in the goto table to include a new state */
-    size = cnt * ctx->single_state_size;
-    ptmp = SCRealloc(ctx->goto_table, size);
+    size = SCACCheckSafeSizetMult((size_t) cnt, (size_t) ctx->single_state_size);
+    if (size > 0)
+        ptmp = SCRealloc(ctx->goto_table, size);
     if (ptmp == NULL) {
         SCFree(ctx->goto_table);
         ctx->goto_table = NULL;
@@ -145,12 +168,15 @@
     ctx->goto_table = ptmp;
 
     /* reallocate space in the output table for the new state */
-    int oldsize = ctx->state_count * sizeof(SCACOutputTable);
-    size = cnt * sizeof(SCACOutputTable);
-    SCLogDebug("oldsize %d size %d cnt %u ctx->state_count %u",
-            oldsize, size, cnt, ctx->state_count);
+    size_t oldsize = SCACCheckSafeSizetMult((size_t) ctx->state_count,
+        sizeof(SCACOutputTable));
+    size = SCACCheckSafeSizetMult((size_t) cnt, sizeof(SCACOutputTable));
+    SCLogDebug("oldsize %"PRIuMAX" size  %"PRIuMAX" cnt %d ctx->state_count %u",
+            (uintmax_t) oldsize, (uintmax_t) size, cnt, ctx->state_count);
 
-    ptmp = SCRealloc(ctx->output_table, size);
+    ptmp = NULL;
+    if (size > 0)
+        ptmp = SCRealloc(ctx->output_table, size);
     if (ptmp == NULL) {
         SCFree(ctx->output_table);
         ctx->output_table = NULL;
diff -Nru suricata-3.2/src/util-mpm.c suricata-3.2.1/src/util-mpm.c
--- suricata-3.2/src/util-mpm.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-mpm.c	2017-02-15 08:54:12.000000000 +0100
@@ -46,6 +46,9 @@
 #include "detect-engine-mpm.h"
 #endif
 #include "util-memcpy.h"
+#ifdef BUILD_HYPERSCAN
+#include "hs.h"
+#endif
 
 /**
  * \brief Register a new Mpm Context.
@@ -402,15 +405,46 @@
     mpm_table[matcher].InitCtx(mpm_ctx);
 }
 
+/* MPM matcher to use by default, i.e. when "mpm-algo" is set to "auto".
+ * If Hyperscan is available, use it. Otherwise, use AC. */
+#ifdef BUILD_HYPERSCAN
+# define DEFAULT_MPM     MPM_HS
+# ifdef __tile__
+#  define DEFAULT_MPM_AC MPM_AC_TILE
+# else
+#  define DEFAULT_MPM_AC MPM_AC
+# endif
+#else
+# ifdef __tile__
+#  define DEFAULT_MPM    MPM_AC_TILE
+# else
+#  define DEFAULT_MPM    MPM_AC
+# endif
+#endif
+
 void MpmTableSetup(void)
 {
     memset(mpm_table, 0, sizeof(mpm_table));
+    mpm_default_matcher = DEFAULT_MPM;
 
     MpmACRegister();
     MpmACBSRegister();
     MpmACTileRegister();
 #ifdef BUILD_HYPERSCAN
-    MpmHSRegister();
+    #ifdef HAVE_HS_VALID_PLATFORM
+    /* Enable runtime check for SSSE3. Do not use Hyperscan MPM matcher if
+     * check is not successful. */
+        if (hs_valid_platform() != HS_SUCCESS) {
+            SCLogInfo("SSSE3 support not detected, disabling Hyperscan for "
+                      "MPM");
+            /* Fall back to best Aho-Corasick variant. */
+            mpm_default_matcher = DEFAULT_MPM_AC;
+        } else {
+            MpmHSRegister();
+        }
+    #else
+        MpmHSRegister();
+    #endif /* HAVE_HS_VALID_PLATFORM */
 #endif /* BUILD_HYPERSCAN */
 #ifdef __SC_CUDA_SUPPORT__
     MpmACCudaRegister();
diff -Nru suricata-3.2/src/util-mpm.h suricata-3.2.1/src/util-mpm.h
--- suricata-3.2/src/util-mpm.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-mpm.h	2017-02-15 08:54:12.000000000 +0100
@@ -43,18 +43,6 @@
     MPM_TABLE_SIZE,
 };
 
-/* MPM matcher to use by default, i.e. when "mpm-algo" is set to "auto".
- * If Hyperscan is available, use it. Otherwise, use AC. */
-#ifdef BUILD_HYPERSCAN
-# define DEFAULT_MPM    MPM_HS
-#else
-# ifdef __tile__
-#  define DEFAULT_MPM   MPM_AC_TILE
-# else
-#  define DEFAULT_MPM   MPM_AC
-# endif
-#endif
-
 /* Internal Pattern Index: 0 to pattern_cnt-1 */
 typedef uint32_t MpmPatternIndex;
 
@@ -171,6 +159,7 @@
 } MpmTableElmt;
 
 MpmTableElmt mpm_table[MPM_TABLE_SIZE];
+int mpm_default_matcher;
 
 /* macros decides if cuda is enabled for the platform or not */
 #ifdef __SC_CUDA_SUPPORT__
diff -Nru suricata-3.2/src/util-mpm-hs.c suricata-3.2.1/src/util-mpm-hs.c
--- suricata-3.2/src/util-mpm-hs.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-mpm-hs.c	2017-02-15 08:54:12.000000000 +0100
@@ -657,6 +657,7 @@
         if (p->flags & (MPM_PATTERN_FLAG_OFFSET | MPM_PATTERN_FLAG_DEPTH)) {
             cd->ext[i] = SCMalloc(sizeof(hs_expr_ext_t));
             if (cd->ext[i] == NULL) {
+                SCMutexUnlock(&g_db_table_mutex);
                 goto error;
             }
             memset(cd->ext[i], 0, sizeof(hs_expr_ext_t));
@@ -685,6 +686,7 @@
             SCLogError(SC_ERR_FATAL, "compile error: %s", compile_err->message);
         }
         hs_free_compile_error(compile_err);
+        SCMutexUnlock(&g_db_table_mutex);
         goto error;
     }
 
@@ -695,12 +697,14 @@
     SCMutexUnlock(&g_scratch_proto_mutex);
     if (err != HS_SUCCESS) {
         SCLogError(SC_ERR_FATAL, "failed to allocate scratch");
+        SCMutexUnlock(&g_db_table_mutex);
         goto error;
     }
 
     err = hs_database_size(pd->hs_db, &ctx->hs_db_size);
     if (err != HS_SUCCESS) {
         SCLogError(SC_ERR_FATAL, "failed to query database size");
+        SCMutexUnlock(&g_db_table_mutex);
         goto error;
     }
 
@@ -719,7 +723,6 @@
     return 0;
 
 error:
-    SCMutexUnlock(&g_db_table_mutex);
     if (pd) {
         PatternDatabaseFree(pd);
     }
diff -Nru suricata-3.2/src/util-privs.c suricata-3.2.1/src/util-privs.c
--- suricata-3.2/src/util-privs.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-privs.c	2017-02-15 08:54:12.000000000 +0100
@@ -77,6 +77,7 @@
             capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
                     CAP_NET_RAW,            /* needed for pcap live mode */
                     CAP_SYS_NICE,
+                    CAP_NET_ADMIN,
                     -1);
             break;
         case RUNMODE_PFRING:
diff -Nru suricata-3.2/src/util-profiling.c suricata-3.2.1/src/util-profiling.c
--- suricata-3.2/src/util-profiling.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-profiling.c	2017-02-15 08:54:12.000000000 +0100
@@ -102,14 +102,14 @@
 struct ProfileProtoRecords packet_profile_flowworker_data[PROFILE_FLOWWORKER_SIZE];
 
 int profiling_packets_enabled = 0;
-int profiling_packets_csv_enabled = 0;
-
 int profiling_output_to_file = 0;
-int profiling_packets_output_to_file = 0;
-char *profiling_file_name;
-char *profiling_packets_file_name;
-char *profiling_csv_file_name;
-const char *profiling_packets_file_mode = "a";
+
+static int profiling_packets_csv_enabled = 0;
+static int profiling_packets_output_to_file = 0;
+static char *profiling_file_name;
+static char profiling_packets_file_name[PATH_MAX];
+static char *profiling_csv_file_name;
+static const char *profiling_packets_file_mode = "a";
 
 static int rate = 1;
 static SC_ATOMIC_DECLARE(uint64_t, samples);
@@ -187,13 +187,8 @@
                 char *log_dir;
                 log_dir = ConfigGetLogDirectory();
 
-                profiling_packets_file_name = SCMalloc(PATH_MAX);
-                if (unlikely(profiling_packets_file_name == NULL)) {
-                    SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name");
-                    exit(EXIT_FAILURE);
-                }
-
-                snprintf(profiling_packets_file_name, PATH_MAX, "%s/%s", log_dir, filename);
+                snprintf(profiling_packets_file_name, sizeof(profiling_packets_file_name),
+                        "%s/%s", log_dir, filename);
 
                 const char *v = ConfNodeLookupChildValue(conf, "append");
                 if (v == NULL || ConfValIsTrue(v)) {
@@ -1117,7 +1112,7 @@
 }
 
 static void SCProfilingUpdatePacketGenericRecords(Packet *p, PktProfilingData *pd,
-        struct ProfileProtoRecords *store, int size)
+        struct ProfileProtoRecords *records, int size)
 {
     int i;
     for (i = 0; i < size; i++) {
@@ -1127,7 +1122,7 @@
             continue;
         }
 
-        struct ProfileProtoRecords *r = &store[i];
+        struct ProfileProtoRecords *r = &records[i];
         SCProfilePacketData *store = NULL;
 
         if (PKT_IS_IPV4(p)) {
diff -Nru suricata-3.2/src/util-profiling-keywords.c suricata-3.2.1/src/util-profiling-keywords.c
--- suricata-3.2/src/util-profiling-keywords.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-profiling-keywords.c	2017-02-15 08:54:12.000000000 +0100
@@ -63,7 +63,7 @@
 static int profiling_keywords_output_to_file = 0;
 int profiling_keyword_enabled = 0;
 __thread int profiling_keyword_entered = 0;
-static char *profiling_file_name = "";
+static char profiling_file_name[PATH_MAX];
 static const char *profiling_file_mode = "a";
 
 void SCProfilingKeywordsGlobalInit(void)
@@ -80,12 +80,8 @@
                 char *log_dir;
                 log_dir = ConfigGetLogDirectory();
 
-                profiling_file_name = SCMalloc(PATH_MAX);
-                if (unlikely(profiling_file_name == NULL)) {
-                    SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name");
-                    exit(EXIT_FAILURE);
-                }
-                snprintf(profiling_file_name, PATH_MAX, "%s/%s", log_dir, filename);
+                snprintf(profiling_file_name, sizeof(profiling_file_name), "%s/%s",
+                        log_dir, filename);
 
                 const char *v = ConfNodeLookupChildValue(conf, "append");
                 if (v == NULL || ConfValIsTrue(v)) {
diff -Nru suricata-3.2/src/util-profiling-rulegroups.c suricata-3.2.1/src/util-profiling-rulegroups.c
--- suricata-3.2/src/util-profiling-rulegroups.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-profiling-rulegroups.c	2017-02-15 08:54:12.000000000 +0100
@@ -64,7 +64,7 @@
 
 static int profiling_sghs_output_to_file = 0;
 int profiling_sghs_enabled = 0;
-static char *profiling_file_name = "";
+static char profiling_file_name[PATH_MAX];
 static const char *profiling_file_mode = "a";
 #ifdef HAVE_LIBJANSSON
 static int profiling_rulegroup_json = 0;
@@ -84,12 +84,8 @@
                 char *log_dir;
                 log_dir = ConfigGetLogDirectory();
 
-                profiling_file_name = SCMalloc(PATH_MAX);
-                if (unlikely(profiling_file_name == NULL)) {
-                    SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name");
-                    exit(EXIT_FAILURE);
-                }
-                snprintf(profiling_file_name, PATH_MAX, "%s/%s", log_dir, filename);
+                snprintf(profiling_file_name, sizeof(profiling_file_name),
+                        "%s/%s", log_dir, filename);
 
                 const char *v = ConfNodeLookupChildValue(conf, "append");
                 if (v == NULL || ConfValIsTrue(v)) {
diff -Nru suricata-3.2/src/util-profiling-rules.c suricata-3.2.1/src/util-profiling-rules.c
--- suricata-3.2/src/util-profiling-rules.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-profiling-rules.c	2017-02-15 08:54:12.000000000 +0100
@@ -79,7 +79,7 @@
 
 extern int profiling_output_to_file;
 int profiling_rules_enabled = 0;
-static char *profiling_file_name = "";
+static char profiling_file_name[PATH_MAX] = "";
 static const char *profiling_file_mode = "a";
 #ifdef HAVE_LIBJANSSON
 static int profiling_rule_json = 0;
@@ -165,12 +165,8 @@
                 char *log_dir;
                 log_dir = ConfigGetLogDirectory();
 
-                profiling_file_name = SCMalloc(PATH_MAX);
-                if (unlikely(profiling_file_name == NULL)) {
-                    SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name");
-                    exit(EXIT_FAILURE);
-                }
-                snprintf(profiling_file_name, PATH_MAX, "%s/%s", log_dir, filename);
+                snprintf(profiling_file_name, sizeof(profiling_file_name),
+                        "%s/%s", log_dir, filename);
 
                 const char *v = ConfNodeLookupChildValue(conf, "append");
                 if (v == NULL || ConfValIsTrue(v)) {
diff -Nru suricata-3.2/src/util-spm.c suricata-3.2.1/src/util-spm.c
--- suricata-3.2/src/util-spm.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-spm.c	2017-02-15 08:54:12.000000000 +0100
@@ -55,6 +55,9 @@
 #include "util-spm-bm.h"
 #include "util-spm-hs.h"
 #include "util-clock.h"
+#ifdef BUILD_HYPERSCAN
+#include "hs.h"
+#endif
 
 /**
  * \brief Returns the single pattern matcher algorithm to be used, based on the
@@ -89,7 +92,20 @@
     /* When Suricata is built with Hyperscan support, default to using it for
      * SPM. */
 #ifdef BUILD_HYPERSCAN
-    return SPM_HS;
+    #ifdef HAVE_HS_VALID_PLATFORM
+    /* Enable runtime check for SSSE3. Do not use Hyperscan SPM matcher if
+     * check is not successful. */
+        if (hs_valid_platform() != HS_SUCCESS) {
+            SCLogInfo("SSSE3 support not detected, disabling Hyperscan for "
+                      "SPM");
+            /* Use Boyer-Moore as fallback. */
+            return SPM_BM;
+        } else {
+            return SPM_HS;
+        }
+    #else
+        return SPM_HS;
+    #endif
 #else
     /* Otherwise, default to Boyer-Moore */
     return SPM_BM;
@@ -102,7 +118,13 @@
 
     SpmBMRegister();
 #ifdef BUILD_HYPERSCAN
-    SpmHSRegister();
+    #ifdef HAVE_HS_VALID_PLATFORM
+        if (hs_valid_platform() == HS_SUCCESS) {
+            SpmHSRegister();
+        }
+    #else
+        SpmHSRegister();
+    #endif
 #endif
 }
 
diff -Nru suricata-3.2/src/util-var.c suricata-3.2.1/src/util-var.c
--- suricata-3.2/src/util-var.c	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-var.c	2017-02-15 08:54:12.000000000 +0100
@@ -36,7 +36,7 @@
 
 #include "util-debug.h"
 
-static void XBitFree(XBit *fb)
+void XBitFree(XBit *fb)
 {
     if (fb == NULL)
         return;
diff -Nru suricata-3.2/src/util-var.h suricata-3.2.1/src/util-var.h
--- suricata-3.2/src/util-var.h	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/src/util-var.h	2017-02-15 08:54:12.000000000 +0100
@@ -57,6 +57,8 @@
     uint32_t expire;
 } XBit;
 
+void XBitFree(XBit *);
+
 // A list of variables we try to resolve while parsing configuration file.
 // Helps to detect recursive declarations.
 typedef struct ResolvedVariable_ {
diff -Nru suricata-3.2/suricata.yaml.in suricata-3.2.1/suricata.yaml.in
--- suricata-3.2/suricata.yaml.in	2016-11-29 18:16:41.000000000 +0100
+++ suricata-3.2.1/suricata.yaml.in	2017-02-15 08:54:12.000000000 +0100
@@ -50,6 +50,7 @@
 default-rule-path: @e_sysconfdir@rules
 rule-files:
  - botcc.rules
+ # - botcc.portgrouped.rules
  - ciarmy.rules
  - compromised.rules
  - drop.rules
@@ -67,6 +68,7 @@
 # - emerging-icmp.rules
  - emerging-imap.rules
 # - emerging-inappropriate.rules
+# - emerging-info.rules
  - emerging-malware.rules
  - emerging-misc.rules
  - emerging-mobile_malware.rules
@@ -75,7 +77,8 @@
  - emerging-policy.rules
  - emerging-pop3.rules
  - emerging-rpc.rules
- - emerging-scada.rules
+# - emerging-scada.rules
+# - emerging-scada_special.rules
  - emerging-scan.rules
 # - emerging-shellcode.rules
  - emerging-smtp.rules
@@ -703,7 +706,7 @@
     smb:
       enabled: yes
       detection-ports:
-        dp: 139
+        dp: 139, 445
     # smb2 detection is disabled internally inside the engine.
     #smb2:
     #  enabled: yes
@@ -1217,7 +1220,9 @@
     #    prealloc: 512
     #  - size: 768
     #    prealloc: 1024
-    #  - size: 1448
+    # 'from_mtu' means that the size is mtu - 40,
+    # or 1460 if mtu couldn't be determined.
+    #  - size: from_mtu
     #    prealloc: 1024
     #  - size: 65535
     #    prealloc: 128

Reply to: