# limitations under the License.
##### Settings #####
-VERSION=1.0.6
+VERSION=1.0.7
AUTHOR="Ashlee Young"
-MODIFIED="November 17, 2015"
+MODIFIED="November 23, 2015"
GERRITURL="git clone ssh://im2bz2pee@gerrit.opnfv.org:29418/onosfw"
ONOSURL="https://github.com/opennetworkinglab/onos"
SURICATAURL="https://github.com/inliniac/suricata"
export ONOS_CELL=sdnds-tw
export RPMBUILDPATH=~/rpmbuild
export PATCHES=$GERRITROOT/framework/patches
+export SURICATAROOT=$BUILDROOT/suricata
+export SURICATASRC=$GERRITROOT/framework/src/suricata
##### End Set build environment #####
##### Ask Function #####
clear
printf "You are running installer script Version: %s \n" "$VERSION"
printf "Last modified on %s, by %s. \n\n" "$MODIFIED" "$AUTHOR"
- sleep 2
+ sleep 1
}
##### End Version #####
updateONOS()
{
if [ "$MODE" != "auto" ]; then
- printf "NOTE: Updating upstream src is a PTL function. Please use this function locally, only. \n"
- printf "If you need the main repo updated to pick up ONOS upstream features, please email \n"
- printf "me at ashlee AT onosfw.com. \n\n"
- printf "Thanks! \n\n"
- if ask "Do you still wish to update your local ONOS source tree?"; then
- freshONOS
- printf "\n"
- cd $BUILDROOT
- git clone $ONOSURL onosproject
- rsync -arvP --delete --exclude=.git --exclude=.gitignore --exclude=.gitreview onosproject/ ../src/onos/
- cd onosproject
- git log > ../onos_update.$(date +%s)
- cd ../
- rm -rf onosproject
- cd $GERRITROOT
- # End applying patches
+ MODE=manual
+ if ask "Would you like to refresh your ONOS src tree with the ONOS tip?"; then
+ printf "NOTE: Updating upstream src is a PTL function. Please use this function locally, only. \n"
+ printf "If you need the main repo updated to pick up ONOS upstream features, please email \n"
+ printf "me at ashlee AT onosfw.com. \n\n"
+ printf "Thanks! \n\n"
+ if ask "Do you still wish to update your local ONOS source tree?"; then
+ freshONOS
+ printf "\n"
+ cd $BUILDROOT
+ git clone $ONOSURL onosproject
+ rsync -arvP --delete --exclude=.git --exclude=.gitignore --exclude=.gitreview onosproject/ ../src/onos/
+ cd onosproject
+ git log > ../onos_update.$(date +%s)
+ cd ../
+ rm -rf onosproject
+ cd $GERRITROOT
+ # End applying patches
+ fi
fi
+ else
+ MODE=auto
fi
printf "\n"
printf "Build Mode is set to $MODE\n\n"
if [ "$JAVA_NUM" '<' "$JAVA_VERSION" ]; then
echo -e "Java version $INSTALLED_JAVA is lower than the required version of $JAVA_VERSION. \n"
if [ "$OS" = "centos" ]; then
- printf "It is recommended that you run \"sudo yum install java-$JAVA_VERSION.0-openjdk-devel\".\n"
+ printf "It is recommended that you run \"sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel\".\n"
if ask "May we perform this task for you?"; then
- sudo yum install java-$JAVA_VERSION.0-openjdk-devel
+ sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel
fi
elif [[ "$OS" = "ubuntu" ]]; then
- printf "It is recommended that you run \"sudo apt-get install openjdk-8-jdk\".\n"
+ printf "It is recommended that you run \"sudo apt-get -y install openjdk-8-jdk\".\n"
if ask "May we perform this task for you?"; then
- sudo add-apt-repository ppa:openjdk-r/ppa
- sudo apt-get update
- sudo apt-get install openjdk-8-jdk
+ sudo add-apt-repository -y ppa:openjdk-r/ppa
+ sudo apt-get -y update
+ sudo apt-get -y install openjdk-8-jdk
fi
elif [[ "$OS" = "suse" ]]; then
if [ "OS" = "centos" ]; then
printf "It doesn't look there's a valid JDK installed.\n"
if ask "May we install one?"; then
- sudo yum install java-$JAVA_VERSION.0-openjdk-devel
+ sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel
else
- printf "You should run \"sudo yum install java-$JAVA_VERSION.0-openjdk-devel\". \n\n"
+ printf "You should run \"sudo yum -y install java-$JAVA_VERSION.0-openjdk-devel\". \n\n"
fi
elif [[ "$OS" = "ubuntu" ]]; then
printf "It doesn't look there's a valid JDK installed.\n"
if ask "May we install one?"; then
- sudo add-apt-repository ppa:openjdk-r/ppa
- sudo apt-get update
- sudo apt-get install openjdk-8-jdk
+ sudo add-apt-repository -y ppa:openjdk-r/ppa
+ sudo apt-get -y update
+ sudo apt-get -y install openjdk-8-jdk
else
- printf "You should run \"sudo apt-get install openjdk-8-jdk\". \n\n"
+ printf "You should run \"sudo apt-get -y install openjdk-8-jdk\". \n\n"
fi
elif [[ "$OS" = "suse" ]]; then
printf "It doesn't look there's a valid JDK installed.\n"
##### Build ONOS #####
buildONOS()
{
- if [ ! -d $ONOSROOT ]; then
- if ask "May we proceed to build ONOS?"; then
- clear
- mkdir -p $ONOSROOT
- cp -rv $ONOSRC/* $ONOSROOT/
- if ask "Would you like to apply ONOSFW unique patches?"; then
- cd $PATCHES
- files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
- if [ $"files" > 0 ]; then
- for file in $files; do
- FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
- if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
- mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ if ask "Would you like to build ONOS?"; then
+ updateONOS
+ checkJRE
+ checkJDK
+ installAnt
+ installMaven
+ installKaraf
+ freshONOS
+ if [ ! -d $ONOSROOT ]; then
+ clear
+ mkdir -p $ONOSROOT
+ cp -rv $ONOSRC/* $ONOSROOT/
+ if [ -d $PATCHES/onos ]; then
+ if ask "Would you like to apply ONOSFW unique patches?"; then
+ cd $PATCHES
+ files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
+ if [ $"files" > 0 ]; then
+ for file in $files; do
+ FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
+ if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
+ mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ fi
+ cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
+ done
fi
- cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
- done
+ cd $GERRITROOT
+ fi
fi
- cd $GERRITROOT
- fi
- cd $ONOSROOT
- ln -sf $KARAF_ROOT/apache-karaf-$KARAF_VERSION apache-karaf-$KARAF_VERSION
- mvn clean install
- if [ -f "$ONOSROOT/tools/build/envDefaults" ]; then
- export ONOSVERSION="`cat $ONOSROOT/tools/build/envDefaults | grep "export ONOS_POM_VERSION" \
- | awk -F "=" {'print $2'} | sed -e 's/^"//' -e 's/"$//' | awk -F "-" {'print $1'}`-onosfw-$(date +%s)"
- printf "ONOSFW ONOS version is $ONOSVERSION. \n\n"
- fi
- fi
- else
- if ask "Would you like us to re-run building ONOS?"; then
- if ask "Would you like to apply ONOSFW unique patches?"; then
- cd $PATCHES
- files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
- if [ $"files" > 0 ]; then
- for file in $files; do
- FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
- if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
- mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ cd $ONOSROOT
+ ln -sf $KARAF_ROOT/apache-karaf-$KARAF_VERSION apache-karaf-$KARAF_VERSION
+ mvn clean install
+ if [ -f "$ONOSROOT/tools/build/envDefaults" ]; then
+ export ONOSVERSION="`cat $ONOSROOT/tools/build/envDefaults | grep "export ONOS_POM_VERSION" \
+ | awk -F "=" {'print $2'} | sed -e 's/^"//' -e 's/"$//' | awk -F "-" {'print $1'}`-onosfw-$(date +%s)"
+ printf "ONOSFW ONOS version is $ONOSVERSION. \n\n"
+ fi
+ else
+ if ask "There looks to be a previous build. Would you like us to re-build ONOS?"; then
+ if [ -d $PATCHES/onos ]; then
+ if ask "Would you like to apply ONOSFW unique patches?"; then
+ cd $PATCHES
+ files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
+ if [ $"files" > 0 ]; then
+ for file in $files; do
+ FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
+ if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
+ mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ fi
+ cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
+ done
fi
- cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
- done
+ cd $GERRITROOT
+ fi
fi
- cd $GERRITROOT
fi
cd $ONOSROOT
ln -sf $KARAF_ROOT/apache-karaf-$KARAF_VERSION apache-karaf-$KARAF_VERSION
| awk -F "=" {'print $2'} | sed -e 's/^"//' -e 's/"$//' | awk -F "-" {'print $1'}`-onosfw-$(date +%s)"
printf "ONOSFW ONOS version is $ONOSVERSION. \n\n"
fi
- fi
- fi
+ fi
+ fi
}
##### End Build ONOS #####
printf "RPM Development support is not installed. We need it to build the RPM packages. \n"
if ask "May we install it?"; then
if [ "$OS" = "centos" ]; then
- sudo yum install rpm-build
- sudo yum install rpm-devel
+ sudo yum -y install rpm-build
+ sudo yum -y install rpm-devel
elif [ "$OS" = "suse" ]; then
- sudo zypper install rpm-build
- sudo zypper install rpm-devel
+ sudo zypper --non-interactive install rpm-build
+ sudo zypper --non-interactive install rpm-devel
elif [ "$OS" = "ubuntu" ]; then
- sudo apt-get install rpm
+ sudo apt-get -y install rpm
fi
fi
fi
}
##### End Check for RPMBUILD tools #####
+##### Update Suricata #####
+# This function will pull the Suricata upstream project and then update the
+# repository in this project with just the diffs.
+updateSuricata()
+{
+ if [ "$MODE" != "auto" ]; then
+ printf "NOTE: Updating upstream src is a PTL function. Please use this function locally, only. \n"
+ printf "If you need the main repo updated to pick up ONOS upstream features, please email \n"
+ printf "me at ashlee AT onosfw.com. \n\n"
+ printf "Thanks! \n\n"
+ if ask "Do you still wish to update your local Suricata source tree?"; then
+ freshSuricata
+ printf "\n"
+ cd $BUILDROOT
+ git clone $SURICATAURL suricataproject
+ rsync -arvP --delete --exclude=.git --exclude=.gitignore --exclude=.gitreview suricataproject/ ../src/suricata/
+ cd suricataproject
+ git log > ../suricata_update.$(date +%s)
+ cd ../
+ rm -rf suricataproject
+ cd $GERRITROOT
+ # End applying patches
+ fi
+ fi
+ printf "\n"
+ printf "Build Mode is set to $MODE\n\n"
+}
+##### End Update Suricata #####
+
+##### Delete Suricata Build #####
+freshSuricata()
+{
+ if [ -d $SURICATAROOT ]; then
+ printf "Suricata has previously been built.\n"
+ if ask "Would you like to build fresh? This involves deleting the old build."; then
+ rm -rf $SURICATAROOT
+ fi
+ fi
+}
+##### End Delete Suricata Build #####
+
+##### Check for libnet #####
+checkforlibNet() # Checks whether RPMBUILD is installed
+{
+ if [ -n "$(rpm -qa | grep libnet-devel)" ]; then
+ if [ "$OS" = "centos" ]; then
+ sudo yum -y install libnet-devel
+ elif [ "$OS" = "suse" ]; then
+ sudo zypper --non-interactive install libnet-devel
+ elif [ "$OS" = "ubuntu" ]; then
+ sudo apt-get -y install libnet-devel
+ fi
+ fi
+}
+##### End Check for libnet #####
+
+##### Check for libpcap #####
+checkforlibpcap() # Checks whether RPMBUILD is installed
+{
+ if [ -n "$(rpm -qa | grep libpcap-devel)" ]; then
+ if [ "$OS" = "centos" ]; then
+ sudo yum -y install libpcap-devel
+ elif [ "$OS" = "suse" ]; then
+ sudo zypper --non-interactive install libpcap-devel
+ elif [ "$OS" = "ubuntu" ]; then
+ sudo apt-get -y install libpcap-devel
+ fi
+ fi
+}
+##### End Check for libpcap #####
+
+##### Build Suricata #####
+buildSuricata()
+{
+ if ask "Would you like to build Suricata for DPI capabilities?"; then
+ updateSuricata
+ freshSuricata
+ checkforlibNet
+ checkforlibpcap
+ if [ ! -d $SURICATAROOT ]; then
+ if ask "May we proceed to build Suricata?"; then
+ clear
+ mkdir -p $SURICATAROOT
+ cp -rv $SURICATASRC/* $SURICATAROOT/
+ if [ -d $PATCHES/suricata ]; then
+ if ask "Would you like to apply ONOSFW unique patches?"; then
+ cd $PATCHES
+ files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
+ if [ $"files" > 0 ]; then
+ for file in $files; do
+ FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
+ if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
+ mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ fi
+ cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
+ done
+ fi
+ cd $GERRITROOT
+ fi
+ fi
+ cd $SURICATAROOT
+ ./autogen.sh
+ ./configure
+ make
+ cd $GERRITROOT
+ fi
+ else
+ if ask "Would you like us to re-run building Suricata?"; then
+ if [ -d $PATCHES/suricata ]; then
+ if ask "Would you like to apply ONOSFW unique patches?"; then
+ cd $PATCHES
+ files=$(find . ! -path . -type f | grep -v 0) # Checks for any files in patches directory
+ if [ $"files" > 0 ]; then
+ for file in $files; do
+ FILEPATH=$(dirname $file) #isolate just the relative path so we can re-create it
+ if [ ! -d "$BUILDROOT/$FILEPATH" ]; then
+ mkdir -p $BUILDROOT/$FILEPATH #recreate the relative path
+ fi
+ cp -v $file $BUILDROOT/$FILEPATH/. #copy all files to proper location(s)
+ done
+ fi
+ cd $GERRITROOT
+ fi
+ fi
+ cd $SURICATAROOT
+ ./autogen.sh
+ ./configure
+ make
+ cd $GERRITROOT
+ fi
+ fi
+ fi
+}
+##### End Build Suricata #####
+
##### Execution order #####
main()
{
displayVersion
detectOS
- updateONOS
- checkJRE
- checkJDK
- installAnt
- installMaven
- installKaraf
- freshONOS
buildONOS
+ buildSuricata
checkforRPMBUILD
}
##### End Execution order #####
-Other than this README file, all contents of this folder will be deleted upon each build. While this can be disabled on local systems, it will be overwritten upon a git pull. We will pull source code from ../src and patches from ../patches. These patches will be applied here and the artifacts built up.
+This is where to place any files to patch upstream projects. The patches are whole files and must be added with their full relative path. For example, if you're making applying a patch to onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc, then you'll need that entire directory path here. Use copy and paste of the location after running "pwd". You can then use "mkdir -p" to create the full path.
import org.onosproject.bgpio.types.Med;
import org.onosproject.bgpio.types.NextHop;
import org.onosproject.bgpio.types.Origin;
+import org.onosproject.bgpio.types.MpReachNlri;
+import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
case LocalPref.LOCAL_PREF_TYPE:
pathAttribute = LocalPref.read(cb);
break;
- case MPREACHNLRI_TYPE:
- //TODO: To be merged later
+ case MpReachNlri.MPREACHNLRI_TYPE:
+ pathAttribute = MpReachNlri.read(cb);
+ isMpReach = ((MpReachNlri) pathAttribute).isMpReachNlriSet();
break;
- case MPUNREACHNLRI_TYPE:
- //TODO: To be merged later
+ case MpUnReachNlri.MPUNREACHNLRI_TYPE:
+ pathAttribute = MpUnReachNlri.read(cb);
+ isMpUnReach = ((MpUnReachNlri) pathAttribute)
+ .isMpUnReachNlriSet();
break;
case LINK_STATE_ATTRIBUTE_TYPE:
//TODO: To be merged later
long tunnelId = match.get(MatchField.TUNNEL_ID).getValue();
builder.matchTunnelId(tunnelId);
break;
+ case ARP_SHA:
+ mac = MacAddress.valueOf(match.get(MatchField.ARP_SHA).getLong());
+ builder.matchArpSha(mac);
+ break;
case ARP_THA:
mac = MacAddress.valueOf(match.get(MatchField.ARP_THA).getLong());
builder.matchArpTha(mac);
break;
case ARP_OP:
- case ARP_SHA:
case ARP_SPA:
case ARP_TPA:
case MPLS_TC:
mplsBos.mplsBos() ? OFBooleanValue.TRUE
: OFBooleanValue.FALSE);
break;
+ case ARP_SHA:
+ arpHaCriterion = (ArpHaCriterion) c;
+ mBuilder.setExact(MatchField.ARP_SHA,
+ MacAddress.of(arpHaCriterion.mac().toLong()));
+ break;
case ARP_THA:
arpHaCriterion = (ArpHaCriterion) c;
mBuilder.setExact(MatchField.ARP_THA,
MacAddress.of(arpHaCriterion.mac().toLong()));
break;
case ARP_OP:
- case ARP_SHA:
case ARP_SPA:
case ARP_TPA:
case MPLS_TC:
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
+the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
The precise terms and conditions for copying, distribution and
modification follow.
-\f
- GNU GENERAL PUBLIC LICENSE
+
+ GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
-\f
+
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
-\f
+
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
-\f
+
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
- END OF TERMS AND CONDITIONS
-\f
- How to Apply These Terms to Your New Programs
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
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
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
+library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
The precise terms and conditions for copying, distribution and
modification follow.
- GNU GENERAL PUBLIC LICENSE
+ GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
- END OF TERMS AND CONDITIONS
+ END OF TERMS AND CONDITIONS
- How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
AC_ARG_ENABLE(non-bundled-htp,
AS_HELP_STRING([--enable-non-bundled-htp], [Enable the use of an already installed version of htp]),,[enable_non_bundled_htp=no])
AS_IF([test "x$enable_non_bundled_htp" = "xyes"], [
+ PKG_CHECK_MODULES([libhtp], htp,, [with_pkgconfig_htp=no])
+ if test "$with_pkgconfig_htp" != "no"; then
+ CPPFLAGS="${CPPFLAGS} ${libhtp_CFLAGS}"
+ LIBS="${LIBS} ${libhtp_LIBS}"
+ fi
+
AC_ARG_WITH(libhtp_includes,
[ --with-libhtp-includes=DIR libhtp include directory],
[with_libhtp_includes="$withval"],[with_libhtp_includes=no])
enable_geoip="yes"
fi
+ # Position Independent Executable
+ AC_ARG_ENABLE(pie,
+ AS_HELP_STRING([--enable-pie],[Enable compiling as a position independent executable]),
+ [ enable_pie="yes"],
+ [ enable_pie="no"])
+ if test "$enable_pie" = "yes"; then
+ CPPFLAGS="${CPPFLAGS} -fPIC"
+ LDFLAGS="${LDFLAGS} -pie"
+ fi
+
+# libhiredis
+ AC_ARG_ENABLE(hiredis,
+ AS_HELP_STRING([--enable-hiredis],[Enable Redis support]),
+ [ enable_hiredis="yes"],
+ [ enable_hiredis="no"])
+ AC_ARG_WITH(libhiredis_includes,
+ [ --with-libhiredis-includes=DIR libhiredis include directory],
+ [with_libhiredis_includes="$withval"],[with_libhiredis_includes="no"])
+ AC_ARG_WITH(libhiredis_libraries,
+ [ --with-libhiredis-libraries=DIR libhiredis library directory],
+ [with_libhiredis_libraries="$withval"],[with_libhiredis_libraries="no"])
+
+ if test "$enable_hiredis" = "yes"; then
+ if test "$with_libhiredis_includes" != "no"; then
+ CPPFLAGS="${CPPFLAGS} -I${with_libhiredis_includes}"
+ fi
+
+ AC_CHECK_HEADER("hiredis/hiredis.h",HIREDIS="yes",HIREDIS="no")
+ if test "$HIREDIS" = "yes"; then
+ if test "$with_libhiredis_libraries" != "no"; then
+ LDFLAGS="${LDFLAGS} -L${with_libhiredis_libraries}"
+ fi
+ AC_CHECK_LIB(hiredis, redisConnect,, HIREDIS="no")
+ fi
+ if test "$HIREDIS" = "no"; then
+ echo
+ echo " ERROR! libhiredis library not found, go get it"
+ echo " from https://github.com/redis/hiredis or your distribution:"
+ echo
+ echo " Ubuntu: apt-get install libhiredis-dev"
+ echo " Fedora: yum install libhiredis-devel"
+ echo
+ exit 1
+ fi
+ if test "$HIREDIS" = "yes"; then
+ AC_DEFINE([HAVE_LIBHIREDIS],[1],[libhiredis available])
+ enable_hiredis="yes"
+ fi
+ fi
+
# get cache line size
AC_PATH_PROG(HAVE_GETCONF_CMD, getconf, "no")
if test "$HAVE_GETCONF_CMD" != "no"; then
libnss support: ${enable_nss}
libnspr support: ${enable_nspr}
libjansson support: ${enable_jansson}
+ hiredis support: ${enable_hiredis}
Prelude support: ${enable_prelude}
PCRE jit: ${pcre_jit_available}
LUA support: ${enable_lua}
GCC Protect enabled: ${enable_gccprotect}
GCC march native enabled: ${enable_gccmarch_native}
GCC Profile enabled: ${enable_gccprofile}
+ Position Independent Executable enabled: ${enable_pie}
CFLAGS ${CFLAGS}
PCAP_CFLAGS ${PCAP_CFLAGS}
SECCFLAGS ${SECCFLAGS}"
parser.add_argument('-C', '--create', action='store_const', const=True, help='create docker container' + docker_deps, default=False)
parser.add_argument('-s', '--start', action='store_const', const=True, help='start docker container' + docker_deps, default=False)
parser.add_argument('-S', '--stop', action='store_const', const=True, help='stop docker container' + docker_deps, default=False)
+parser.add_argument('-R', '--rm', action='store_const', const=True, help='remove docker container and image' + docker_deps, default=False)
parser.add_argument('branch', metavar='branch', help='github branch to build', nargs='?')
args = parser.parse_args()
username = args.username
sys.exit(-1)
def CreateContainer():
- if not os.geteuid() == 0:
- print "Command must be run as root"
- sys.exit(-1)
cli = Client()
# FIXME check if existing
print "Pulling docking image, first run should take long"
sys.exit(0)
def StartContainer():
- if not os.geteuid() == 0:
- print "Command must be run as root"
- sys.exit(-1)
cli = Client()
suri_src_dir = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
print "Using base src dir: " + suri_src_dir
sys.exit(0)
def StopContainer():
- if not os.geteuid() == 0:
- print "Command must be run as root"
- sys.exit(-1)
cli = Client()
cli.stop('suri-buildbot')
sys.exit(0)
+def RmContainer():
+ cli = Client()
+ try:
+ cli.remove_container('suri-buildbot')
+ except:
+ print "Unable to remove suri-buildbot container"
+ pass
+ try:
+ cli.remove_image('regit/suri-buildbot:latest')
+ except:
+ print "Unable to remove suri-buildbot images"
+ pass
+ sys.exit(0)
+
if GOT_DOCKER:
if args.create:
CreateContainer()
StartContainer()
if args.stop:
StopContainer()
+ if args.rm:
+ RmContainer()
if not args.branch:
print "You need to specify a branch for this mode"
echo "Creating ${dst}."
- sed -e "s/TEMPLATE/${protoname_upper}/g" \
+ sed -e '/TEMPLATE_START_REMOVE/,/TEMPLATE_END_REMOVE/d' \
+ -e "s/TEMPLATE/${protoname_upper}/g" \
-e "s/template/${protoname_lower}/g" \
- -e "s/Template/${protoname}/g" > ${dst} < ${src}
+ -e "s/Template/${protoname}/g" \
+ > ${dst} < ${src}
}
function copy_templates() {
echo "Creating ${dst}."
- sed -e "s/TEMPLATE/${protoname_upper}/g" \
+ sed -e '/TEMPLATE_START_REMOVE/,/TEMPLATE_END_REMOVE/d' \
+ -e "s/TEMPLATE/${protoname_upper}/g" \
-e "s/template/${protoname_lower}/g" \
- -e "s/Template/${protoname}/g" > ${dst} < ${src}
+ -e "s/Template/${protoname}/g" \
+ > ${dst} < ${src}
}
function copy_templates() {
ed -s ${filename} > /dev/null <<EOF
/output-json-template.c
t-
-s/template/${protoname_lower}/
+s/template/${protoname_lower}/g
w
EOF
}
echo "Creating ${dst}."
- sed -e "s/TEMPLATE/${protoname_upper}/g" \
+ sed -e '/TEMPLATE_START_REMOVE/,/TEMPLATE_END_REMOVE/d' \
+ -e "s/TEMPLATE/${protoname_upper}/g" \
-e "s/template/${protoname_lower}/g" \
- -e "s/Template/${protoname}/g" > ${dst} < ${src}
+ -e "s/Template/${protoname}/g" \
+ > ${dst} < ${src}
}
function copy_app_layer_templates {
util-lua-dns.c util-lua-dns.h \
util-lua-http.c util-lua-http.h \
util-lua-tls.c util-lua-tls.h \
+util-lua-ssh.c util-lua-ssh.h \
util-magic.c util-magic.h \
util-memcmp.c util-memcmp.h \
util-memcpy.h \
typedef struct Unified2AlertFileCtx_ {
LogFileCtx *file_ctx;
HttpXFFCfg *xff_cfg;
+ uint32_t flags; /**< flags for all alerts */
} Unified2AlertFileCtx;
+#define UNIFIED2_ALERT_FLAGS_EMIT_PACKET (1 << 0)
+
/**
* Unified2 thread vars
*
{
int ret = 0;
+ if (!(aun->unified2alert_ctx->flags & UNIFIED2_ALERT_FLAGS_EMIT_PACKET))
+ return 1;
+
/* try stream logging first */
if (stream) {
SCLogDebug("logging the state");
}
}
+ uint32_t flags = UNIFIED2_ALERT_FLAGS_EMIT_PACKET;
+ if (conf != NULL) {
+ const char *payload = NULL;
+ payload = ConfNodeLookupChildValue(conf, "payload");
+ if (payload) {
+ if (ConfValIsFalse(payload)) {
+ flags &= ~UNIFIED2_ALERT_FLAGS_EMIT_PACKET;
+ } else if (!ConfValIsTrue(payload)) {
+ SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid payload: %s", payload);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
ret = Unified2AlertOpenFileCtx(file_ctx, filename);
if (ret < 0)
goto error;
unified2alert_ctx->file_ctx = file_ctx;
unified2alert_ctx->xff_cfg = xff_cfg;
+ unified2alert_ctx->flags = flags;
output_ctx->data = unified2alert_ctx;
output_ctx->DeInit = Unified2AlertDeInitCtx;
#include "util-memcmp.h"
-#ifndef HAVE_HTP_SET_PATH_DECODE_U_ENCODING
-void htp_config_set_path_decode_u_encoding(htp_cfg_t *cfg, int decode_u_encoding);
-#endif
-
//#define PRINT
/** Fast lookup tree (radix) for the various HTP configurations */
};
/* Create SMTP config structure */
-SMTPConfig smtp_config = { 0, { 0, 0, 0, 0 }, 0, 0, 0};
+SMTPConfig smtp_config = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 0};
+
+static SMTPString *SMTPStringAlloc(void);
/**
* \brief Configure SMTP Mime Decoder by parsing out mime section of YAML
if (ret) {
smtp_config.mime_config.extract_urls = val;
}
+
+ ret = ConfGetChildValueBool(config, "body-md5", &val);
+ if (ret) {
+ smtp_config.mime_config.body_md5 = val;
+ }
}
/* Pass mime config data to MimeDec API */
return NULL;
}
+ TAILQ_INIT(&tx->rcpt_to_list);
tx->mime_state = NULL;
return tx;
}
if (smtp_state->files_ts == NULL) {
ret = MIME_DEC_ERR_MEM;
SCLogError(SC_ERR_MEM_ALLOC, "Could not create file container");
- goto end;
+ SCReturnInt(ret);
}
}
files = smtp_state->files_ts;
if (files != NULL) {
FilePrune(files);
}
-end:
+
SCReturnInt(ret);
}
if (smtp_config.decode_mime && state->curr_tx->mime_state) {
int ret = MimeDecParseLine((const uint8_t *) state->current_line,
- state->current_line_len, state->curr_tx->mime_state);
+ state->current_line_len, state->current_line_delimiter_len,
+ state->curr_tx->mime_state);
if (ret != MIME_DEC_OK) {
SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret);
}
return 0;
}
+static int SMTPParseCommandWithParam(SMTPState *state, uint8_t prefix_len, uint8_t **target, uint16_t *target_len)
+{
+ int i = prefix_len + 1;
+ int spc_i = 0;
+
+ while (i < state->current_line_len) {
+ if (state->current_line[i] != ' ') {
+ break;
+ }
+ i++;
+ }
+
+ /* rfc1870: with the size extension the mail from can be followed by an option.
+ We use the space separator to detect it. */
+ spc_i = i;
+ while (spc_i < state->current_line_len) {
+ if (state->current_line[spc_i] == ' ') {
+ break;
+ }
+ spc_i++;
+ }
+
+ *target = SCMalloc(spc_i - i + 1);
+ if (*target == NULL)
+ return -1;
+ memcpy(*target, state->current_line + i, spc_i - i);
+ (*target)[spc_i - i] = '\0';
+ *target_len = spc_i - i;
+
+ return 0;
+}
+
+static int SMTPParseCommandHELO(SMTPState *state)
+{
+ return SMTPParseCommandWithParam(state, 4, &state->helo, &state->helo_len);
+}
+
+static int SMTPParseCommandMAILFROM(SMTPState *state)
+{
+ return SMTPParseCommandWithParam(state, 9,
+ &state->curr_tx->mail_from,
+ &state->curr_tx->mail_from_len);
+}
+
+static int SMTPParseCommandRCPTTO(SMTPState *state)
+{
+ uint8_t *rcptto;
+ uint16_t rcptto_len;
+
+ if (SMTPParseCommandWithParam(state, 7, &rcptto, &rcptto_len) == 0) {
+ SMTPString *rcptto_str = SMTPStringAlloc();
+ if (rcptto_str) {
+ rcptto_str->str = rcptto;
+ rcptto_str->len = rcptto_len;
+ TAILQ_INSERT_TAIL(&state->curr_tx->rcpt_to_list, rcptto_str, next);
+ } else {
+ SCFree(rcptto);
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
/* consider 'rset' and 'quit' to be part of the existing state */
static int NoNewTx(SMTPState *state)
{
}
state->current_command = SMTP_COMMAND_BDAT;
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
+ } else if (state->current_line_len >= 4 &&
+ ((SCMemcmpLowercase("helo", state->current_line, 4) == 0) ||
+ SCMemcmpLowercase("ehlo", state->current_line, 4) == 0)) {
+ r = SMTPParseCommandHELO(state);
+ if (r == -1) {
+ SCReturnInt(-1);
+ }
+ state->current_command = SMTP_COMMAND_OTHER_CMD;
+ } else if (state->current_line_len >= 9 &&
+ SCMemcmpLowercase("mail from", state->current_line, 9) == 0) {
+ r = SMTPParseCommandMAILFROM(state);
+ if (r == -1) {
+ SCReturnInt(-1);
+ }
+ state->current_command = SMTP_COMMAND_OTHER_CMD;
+ } else if (state->current_line_len >= 7 &&
+ SCMemcmpLowercase("rcpt to", state->current_line, 7) == 0) {
+ r = SMTPParseCommandRCPTTO(state);
+ if (r == -1) {
+ SCReturnInt(-1);
+ }
+ state->current_command = SMTP_COMMAND_OTHER_CMD;
} else {
state->current_command = SMTP_COMMAND_OTHER_CMD;
}
return smtp_state;
}
+static SMTPString *SMTPStringAlloc(void)
+{
+ SMTPString *smtp_string = SCMalloc(sizeof(SMTPString));
+ if (unlikely(smtp_string == NULL))
+ return NULL;
+ memset(smtp_string, 0, sizeof(SMTPString));
+
+ return smtp_string;
+}
+
+
+static void SMTPStringFree(SMTPString *str)
+{
+ if (str->str) {
+ SCFree(str->str);
+ }
+ SCFree(str);
+}
+
static void *SMTPLocalStorageAlloc(void)
{
/* needed by the mpm */
if (tx->de_state != NULL)
DetectEngineStateFree(tx->de_state);
+
+ if (tx->mail_from)
+ SCFree(tx->mail_from);
+
+ SMTPString *str = NULL;
+ while ((str = TAILQ_FIRST(&tx->rcpt_to_list))) {
+ TAILQ_REMOVE(&tx->rcpt_to_list, str, next);
+ SMTPStringFree(str);
+ }
#if 0
if (tx->decoder_events->cnt <= smtp_state->events)
smtp_state->events -= tx->decoder_events->cnt;
SCFree(smtp_state->tc_db);
}
+ if (smtp_state->helo) {
+ SCFree(smtp_state->helo);
+ }
+
FileContainerFree(smtp_state->files_ts);
SMTPTransaction *tx = NULL;
SCMutexUnlock(&f.m);
goto end;
}
+
+ if ((smtp_state->helo_len != 7) || strncmp("boo.com", (char *)smtp_state->helo, 7)) {
+ printf("incorrect parsing of HELO field '%s' (%d)\n", smtp_state->helo, smtp_state->helo_len);
+ SCMutexUnlock(&f.m);
+ goto end;
+ }
+
SCMutexUnlock(&f.m);
if (smtp_state->input_len != 0 ||
smtp_state->cmds_cnt != 0 ||
SCMutexUnlock(&f.m);
goto end;
}
+
+ if ((smtp_state->curr_tx->mail_from_len != 14) ||
+ strncmp("asdff@asdf.com", (char *)smtp_state->curr_tx->mail_from, 14)) {
+ printf("incorrect parsing of MAIL FROM field '%s' (%d)\n",
+ smtp_state->curr_tx->mail_from,
+ smtp_state->curr_tx->mail_from_len);
+ SCMutexUnlock(&f.m);
+ goto end;
+ }
+
SCMutexUnlock(&f.m);
if (smtp_state->input_len != 0 ||
smtp_state->cmds_cnt != 0 ||
SMTP_DECODER_EVENT_MIME_BOUNDARY_TOO_LONG,
};
+typedef struct SMTPString_ {
+ uint8_t *str;
+ uint16_t len;
+
+ TAILQ_ENTRY(SMTPString_) next;
+} SMTPString;
+
typedef struct SMTPTransaction_ {
/** id of this tx, starting at 0 */
uint64_t tx_id;
AppLayerDecoderEvents *decoder_events; /**< per tx events */
DetectEngineState *de_state;
+ /* MAIL FROM parameters */
+ uint8_t *mail_from;
+ uint16_t mail_from_len;
+
+ TAILQ_HEAD(, SMTPString_) rcpt_to_list; /**< rcpt to string list */
+
TAILQ_ENTRY(SMTPTransaction_) next;
} SMTPTransaction;
/** the list of files sent to the server */
FileContainer *files_ts;
+ /* HELO of HELO message content */
+ uint8_t *helo;
+ uint16_t helo_len;
} SMTPState;
/* Create SMTP config structure */
#define SSH_FLAG_STATE_LOGGED 0x04
+#define SSH_FLAG_STATE_LOGGED_LUA 0x08
+
/* MSG_CODE */
#define SSH_MSG_NEWKEYS 21
/* flags for file storage */
#define SSL_AL_FLAG_STATE_STORED 0x40000
+#define SSL_AL_FLAG_STATE_LOGGED_LUA 0x80000
+
/* config flags */
#define SSL_TLS_LOG_PEM (1 << 0)
#include "suricata-common.h"
#include "stream.h"
+#include "conf.h"
#include "util-unittest.h"
{
char *proto_name = "template";
+ /* TEMPLATE_START_REMOVE */
+ if (ConfGetNode("app-layer.protocols.template") == NULL) {
+ return;
+ }
+ /* TEMPLATE_END_REMOVE */
+
/* Check if Template TCP detection is enabled. If it does not exist in
* the configuration file then it will be enabled by default. */
if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
STREAM_TOSERVER, TemplateParseRequest);
/* Register response parser for parsing frames from server to client. */
- AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEMPLATE, STREAM_TOCLIENT,
- TemplateParseResponse);
+ AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEMPLATE,
+ STREAM_TOCLIENT, TemplateParseResponse);
/* Register a function to be called by the application layer
* when a transaction is to be freed. */
TemplateStateTxFree);
/* Register a function to return the current transaction count. */
- AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEMPLATE, TemplateGetTxCnt);
+ AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEMPLATE,
+ TemplateGetTxCnt);
/* Transaction handling. */
AppLayerParserRegisterGetStateProgressCompletionStatus(IPPROTO_TCP,
StreamTcpDisableAppLayer(f);
}
+static inline int ProtoDetectDone(const Flow *f, const TcpSession *ssn, uint8_t direction) {
+ const TcpStream *stream = (direction & STREAM_TOSERVER) ? &ssn->client : &ssn->server;
+ return ((stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+ (FLOW_IS_PM_DONE(f, direction) && FLOW_IS_PP_DONE(f, direction)));
+}
+
int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
Packet *p, Flow *f,
TcpSession *ssn, TcpStream *stream,
p->flowflags |= FLOW_PKT_TOCLIENT;
}
}
- int ret = StreamTcpReassembleAppLayer(tv, ra_ctx, ssn,
+
+ int ret = 0;
+ /* if the opposing side is not going to work, then
+ * we just have to give up. */
+ if (opposing_stream->flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)
+ ret = -1;
+ else
+ ret = StreamTcpReassembleAppLayer(tv, ra_ctx, ssn,
opposing_stream, p);
if (stream == &ssn->client) {
if (StreamTcpInlineMode()) {
} else {
f->data_al_so_far[dir] = data_len;
}
- } else {
+ } else {
/* See if we're going to have to give up:
*
* If we're getting a lot of data in one direction and the
uint32_t size_ts = ssn->client.last_ack - ssn->client.isn - 1;
uint32_t size_tc = ssn->server.last_ack - ssn->server.isn - 1;
SCLogDebug("size_ts %u, size_tc %u", size_ts, size_tc);
-
- if (FLOW_IS_PM_DONE(f, STREAM_TOSERVER) && FLOW_IS_PP_DONE(f, STREAM_TOSERVER) &&
- FLOW_IS_PM_DONE(f, STREAM_TOCLIENT) && FLOW_IS_PP_DONE(f, STREAM_TOCLIENT)) {
+#ifdef DEBUG_VALIDATION
+ if (!(ssn->client.flags & STREAMTCP_STREAM_FLAG_GAP))
+ BUG_ON(size_ts > 1000000UL);
+ if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_GAP))
+ BUG_ON(size_tc > 1000000UL);
+#endif /* DEBUG_VALIDATION */
+
+ if (ProtoDetectDone(f, ssn, STREAM_TOSERVER) &&
+ ProtoDetectDone(f, ssn, STREAM_TOCLIENT))
+ {
DisableAppLayer(f);
ssn->data_first_seen_dir = APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER;
ssn->data_first_seen_dir = APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER;
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
APPLAYER_PROTO_DETECTION_SKIPPED);
+ /* in case of really low TS data (e.g. 4 bytes) we can have
+ * the PP complete, PM not complete (depth not reached) and
+ * the TC side also not recognized (proto unknown) */
+ } else if (size_tc > 100000 &&
+ FLOW_IS_PP_DONE(f, STREAM_TOSERVER) && !(FLOW_IS_PM_DONE(f, STREAM_TOSERVER)) &&
+ (!FLOW_IS_PM_DONE(f, STREAM_TOCLIENT) && !FLOW_IS_PP_DONE(f, STREAM_TOCLIENT)))
+ {
+ DisableAppLayer(f);
+ ssn->data_first_seen_dir = APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER;
+ AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
+ APPLAYER_PROTO_DETECTION_SKIPPED);
}
- }
+ }
}
} else {
SCLogDebug("stream data (len %" PRIu32 " alproto "
dtv->counter_avg_pkt_size = StatsRegisterAvgCounter("decoder.avg_pkt_size", tv);
dtv->counter_max_pkt_size = StatsRegisterMaxCounter("decoder.max_pkt_size", tv);
dtv->counter_erspan = StatsRegisterMaxCounter("decoder.erspan", tv);
+ dtv->counter_flow_memcap = StatsRegisterCounter("flow.memcap", tv);
dtv->counter_defrag_ipv4_fragments =
StatsRegisterCounter("defrag.ipv4.fragments", tv);
uint16_t counter_defrag_ipv6_timeouts;
uint16_t counter_defrag_max_hit;
+ uint16_t counter_flow_memcap;
+
/* thread data for flow logging api: only used at forced
* flow recycle during lookups */
void *output_flow_thread_data;
dt->vlan_id[1] = p->vlan_id[1];
dt->policy = DefragGetOsPolicy(p);
dt->host_timeout = DefragPolicyGetHostTimeout(p);
+ dt->remove = 0;
+ dt->seen_last = 0;
TAILQ_INIT(&dt->frags);
(void) DefragTrackerIncrUsecnt(dt);
}
-static DefragTracker *DefragTrackerNew(Packet *p)
-{
- DefragTracker *dt = DefragTrackerAlloc();
- if (dt == NULL)
- goto error;
-
- DefragTrackerInit(dt, p);
- return dt;
-
-error:
- return NULL;
-}
-
void DefragTrackerRelease(DefragTracker *t)
{
(void) DefragTrackerDecrUsecnt(t);
/* freed a tracker, but it's unlocked */
} else {
/* now see if we can alloc a new tracker */
- dt = DefragTrackerNew(p);
+ dt = DefragTrackerAlloc();
if (dt == NULL) {
return NULL;
}
dt = hb->head;
/* see if this is the tracker we are looking for */
- if (DefragTrackerCompare(dt, p) == 0) {
+ if (dt->remove || DefragTrackerCompare(dt, p) == 0) {
DefragTracker *pdt = NULL; /* previous tracker */
while (dt) {
if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
}
+
+ if (!frag->more_frags) {
+ break;
+ }
}
SCLogDebug("ip_hdr_offset %u, hlen %u, fragmentable_len %u",
if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
}
+
+ if (!frag->more_frags) {
+ break;
+ }
}
rp->ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + ip_hdr_offset);
new->data_len = data_len - ltrim;
new->ip_hdr_offset = ip_hdr_offset;
new->frag_hdr_offset = frag_hdr_offset;
+ new->more_frags = more_frags;
#ifdef DEBUG
new->pcap_cnt = pcap_cnt;
#endif
return ret;
}
+static int DefragTrackerReuseTest(void)
+{
+ int ret = 0;
+ int id = 1;
+ Packet *p1 = NULL;
+ DefragTracker *tracker1 = NULL, *tracker2 = NULL;
+
+ DefragInit();
+
+ /* Build a packet, its not a fragment but shouldn't matter for
+ * this test. */
+ p1 = BuildTestPacket(id, 0, 0, 'A', 8);
+ if (p1 == NULL) {
+ goto end;
+ }
+
+ /* Get a tracker. It shouldn't look like its already in use. */
+ tracker1 = DefragGetTracker(NULL, NULL, p1);
+ if (tracker1 == NULL) {
+ goto end;
+ }
+ if (tracker1->seen_last) {
+ goto end;
+ }
+ if (tracker1->remove) {
+ goto end;
+ }
+ DefragTrackerRelease(tracker1);
+
+ /* Get a tracker again, it should be the same one. */
+ tracker2 = DefragGetTracker(NULL, NULL, p1);
+ if (tracker2 == NULL) {
+ goto end;
+ }
+ if (tracker2 != tracker1) {
+ goto end;
+ }
+ DefragTrackerRelease(tracker1);
+
+ /* Now mark the tracker for removal. It should not be returned
+ * when we get a tracker for a packet that may have the same
+ * attributes. */
+ tracker1->remove = 1;
+
+ tracker2 = DefragGetTracker(NULL, NULL, p1);
+ if (tracker2 == NULL) {
+ goto end;
+ }
+ if (tracker2 == tracker1) {
+ goto end;
+ }
+ if (tracker2->remove) {
+ goto end;
+ }
+
+ ret = 1;
+end:
+ if (p1 != NULL) {
+ SCFree(p1);
+ }
+ DefragDestroy();
+ return ret;
+}
+
+/**
+ * IPV4: Test the case where you have a packet fragmented in 3 parts
+ * and send like:
+ * - Offset: 2; MF: 1
+ * - Offset: 0; MF: 1
+ * - Offset: 1; MF: 0
+ *
+ * Only the fragments with offset 0 and 1 should be reassembled.
+ */
+static int DefragMfIpv4Test(void)
+{
+ int retval = 0;
+ int ip_id = 9;
+ Packet *p = NULL;
+
+ 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);
+ if (p1 == NULL || p2 == NULL || p3 == NULL) {
+ goto end;
+ }
+
+ p = Defrag(NULL, NULL, p1, NULL);
+ if (p != NULL) {
+ goto end;
+ }
+
+ p = Defrag(NULL, NULL, p2, NULL);
+ if (p != NULL) {
+ goto end;
+ }
+
+ /* This should return a packet as MF=0. */
+ p = Defrag(NULL, NULL, p3, NULL);
+ if (p == NULL) {
+ goto end;
+ }
+
+ /* Expected IP length is 20 + 8 + 8 = 36 as only 2 of the
+ * fragments should be in the re-assembled packet. */
+ if (IPV4_GET_IPLEN(p) != 36) {
+ goto end;
+ }
+
+ retval = 1;
+end:
+ if (p1 != NULL) {
+ SCFree(p1);
+ }
+ if (p2 != NULL) {
+ SCFree(p2);
+ }
+ if (p3 != NULL) {
+ SCFree(p3);
+ }
+ if (p != NULL) {
+ SCFree(p);
+ }
+ DefragDestroy();
+ return retval;
+}
+
+/**
+ * IPV6: Test the case where you have a packet fragmented in 3 parts
+ * and send like:
+ * - Offset: 2; MF: 1
+ * - Offset: 0; MF: 1
+ * - Offset: 1; MF: 0
+ *
+ * Only the fragments with offset 0 and 1 should be reassembled.
+ */
+static int DefragMfIpv6Test(void)
+{
+ int retval = 0;
+ int ip_id = 9;
+ Packet *p = NULL;
+
+ 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);
+ if (p1 == NULL || p2 == NULL || p3 == NULL) {
+ goto end;
+ }
+
+ p = Defrag(NULL, NULL, p1, NULL);
+ if (p != NULL) {
+ goto end;
+ }
+
+ p = Defrag(NULL, NULL, p2, NULL);
+ if (p != NULL) {
+ goto end;
+ }
+
+ /* This should return a packet as MF=0. */
+ p = Defrag(NULL, NULL, p3, NULL);
+ if (p == NULL) {
+ goto end;
+ }
+
+ /* For IPv6 the expected length is just the length of the payload
+ * of 2 fragments, so 16. */
+ if (IPV6_GET_PLEN(p) != 16) {
+ goto end;
+ }
+
+ retval = 1;
+end:
+ if (p1 != NULL) {
+ SCFree(p1);
+ }
+ if (p2 != NULL) {
+ SCFree(p2);
+ }
+ if (p3 != NULL) {
+ SCFree(p3);
+ }
+ if (p != NULL) {
+ SCFree(p);
+ }
+ DefragDestroy();
+ return retval;
+}
+
#endif /* UNITTESTS */
void
UtRegisterTest("DefragVlanTest", DefragVlanTest, 1);
UtRegisterTest("DefragVlanQinQTest", DefragVlanQinQTest, 1);
-
+ UtRegisterTest("DefragTrackerReuseTest", DefragTrackerReuseTest, 1);
UtRegisterTest("DefragTimeoutTest",
DefragTimeoutTest, 1);
+ UtRegisterTest("DefragMfIpv4Test", DefragMfIpv4Test, 1);
+ UtRegisterTest("DefragMfIpv6Test", DefragMfIpv6Test, 1);
#endif /* UNITTESTS */
}
TAILQ_ENTRY(Frag_) next; /**< Pointer to next fragment for tailq. */
} Frag;
-/** \brief Reset tracker fields except "lock" */
-#define DEFRAG_TRACKER_RESET(t) { \
- (t)->timeout = 0; \
- (t)->id = 0; \
- (t)->policy = 0; \
- (t)->af = 0; \
- (t)->seen_last = 0; \
- (t)->remove = 0; \
- CLEAR_ADDR(&(t)->src_addr); \
- CLEAR_ADDR(&(t)->dst_addr); \
- (t)->frags.tqh_first = NULL; \
- (t)->frags.tqh_last = NULL; \
-}
-
/**
* A defragmentation tracker. Used to track fragments that make up a
* single packet.
uint32_t cnt = 0;
uint32_t buffer_len = 0;
uint32_t stream_start_offset = 0;
- uint8_t *buffer = 0;
+ uint8_t *buffer = NULL;
if (ffc != NULL) {
File *file = ffc->head;
flags,
&buffer_len,
&stream_start_offset);
-
if (buffer_len == 0)
goto end;
- cnt = SMTPFiledataPatternSearch(det_ctx, buffer, buffer_len, flags);
+ cnt += SMTPFiledataPatternSearch(det_ctx, buffer, buffer_len, flags);
}
}
end:
#ifdef __SC_CUDA_SUPPORT__
#include "util-mpm-ac.h"
#endif
+#include "util-validate.h"
/** \todo make it possible to use multiple pattern matcher algorithms next to
each other. */
SCReturnInt(0);
}
- if (!(s->proto.proto[6 / 8] & 1 << (6 % 8))) {
+ if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
SCReturnInt(1);
}
SCReturnInt(0);
}
- if (!(s->proto.proto[6 / 8] & 1 << (6 % 8))) {
+ if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
SCReturnInt(0);
}
done:
#ifdef __tile__
if (mpm_algo_val == MPM_AC)
- mpm_algo_val = MPM_AC_TILE;
+ mpm_algo_val = MPM_AC_TILE;
#endif
return mpm_algo_val;
uint32_t ret = 0;
if (p->flowflags & FLOW_PKT_TOSERVER) {
- if (det_ctx->sgh->mpm_stream_ctx_ts == NULL)
- SCReturnInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_stream_ctx_ts == NULL);
ret = mpm_table[det_ctx->sgh->mpm_stream_ctx_ts->mpm_type].
Search(det_ctx->sgh->mpm_stream_ctx_ts, &det_ctx->mtc, &det_ctx->pmq,
p->payload, p->payload_len);
} else {
- if (det_ctx->sgh->mpm_stream_ctx_tc == NULL)
- SCReturnInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_stream_ctx_tc == NULL);
ret = mpm_table[det_ctx->sgh->mpm_stream_ctx_tc->mpm_type].
Search(det_ctx->sgh->mpm_stream_ctx_tc, &det_ctx->mtc, &det_ctx->pmq,
} else {
mpm_ctx = det_ctx->sgh->mpm_proto_other_ctx;
}
-
- if (mpm_ctx == NULL)
+ if (unlikely(mpm_ctx == NULL))
SCReturnInt(0);
#ifdef __SC_CUDA_SUPPORT__
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_uri_ctx_ts == NULL)
- SCReturnUInt(0U);
- ret = mpm_table[det_ctx->sgh->mpm_uri_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_uri_ctx_ts,
- &det_ctx->mtcu, &det_ctx->pmq, uri, uri_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_uri_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_uri_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_uri_ctx_ts,
+ &det_ctx->mtcu, &det_ctx->pmq, uri, uri_len);
//PrintRawDataFp(stdout, uri, uri_len);
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hcbd_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hcbd_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_hcbd_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, body, body_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hcbd_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hcbd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hcbd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, body, body_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- BUG_ON(1);
- } else {
- if (det_ctx->sgh->mpm_hsbd_ctx_tc == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hsbd_ctx_tc->mpm_type].
- Search(det_ctx->sgh->mpm_hsbd_ctx_tc, &det_ctx->mtcu,
- &det_ctx->pmq, body, body_len);
- }
+ DEBUG_VALIDATE_BUG_ON(!(flags & STREAM_TOCLIENT));
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hsbd_ctx_tc == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hsbd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hsbd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, body, body_len);
SCReturnUInt(ret);
}
uint32_t ret;
if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hhd_ctx_ts == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hhd_ctx_ts == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_ts->mpm_type].
Search(det_ctx->sgh->mpm_hhd_ctx_ts, &det_ctx->mtcu,
&det_ctx->pmq, headers, headers_len);
} else {
- if (det_ctx->sgh->mpm_hhd_ctx_tc == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hhd_ctx_tc == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_tc->mpm_type].
Search(det_ctx->sgh->mpm_hhd_ctx_tc, &det_ctx->mtcu,
uint32_t ret;
if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hrhd_ctx_ts == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hrhd_ctx_ts == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hrhd_ctx_ts->mpm_type].
Search(det_ctx->sgh->mpm_hrhd_ctx_ts, &det_ctx->mtcu,
&det_ctx->pmq, raw_headers, raw_headers_len);
} else {
- if (det_ctx->sgh->mpm_hrhd_ctx_tc == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hrhd_ctx_tc == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hrhd_ctx_tc->mpm_type].
Search(det_ctx->sgh->mpm_hrhd_ctx_tc, &det_ctx->mtcu,
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hmd_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hmd_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_hmd_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, raw_method, raw_method_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hmd_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hmd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hmd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, raw_method, raw_method_len);
SCReturnUInt(ret);
}
uint32_t ret;
if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hcd_ctx_ts == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hcd_ctx_ts == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hcd_ctx_ts->mpm_type].
Search(det_ctx->sgh->mpm_hcd_ctx_ts, &det_ctx->mtcu,
&det_ctx->pmq, cookie, cookie_len);
} else {
- if (det_ctx->sgh->mpm_hcd_ctx_tc == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hcd_ctx_tc == NULL);
ret = mpm_table[det_ctx->sgh->mpm_hcd_ctx_tc->mpm_type].
Search(det_ctx->sgh->mpm_hcd_ctx_tc, &det_ctx->mtcu,
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hrud_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hrud_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_hrud_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, uri, uri_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hrud_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrud_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hrud_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, uri, uri_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- BUG_ON(1);
- } else {
- if (det_ctx->sgh->mpm_hsmd_ctx_tc == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hsmd_ctx_tc->mpm_type].
- Search(det_ctx->sgh->mpm_hsmd_ctx_tc, &det_ctx->mtcu,
- &det_ctx->pmq, stat_msg, stat_msg_len);
- }
+ DEBUG_VALIDATE_BUG_ON(!(flags & STREAM_TOCLIENT));
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hsmd_ctx_tc == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hsmd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hsmd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, stat_msg, stat_msg_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- BUG_ON(1);
- } else {
- if (det_ctx->sgh->mpm_hscd_ctx_tc == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hscd_ctx_tc->mpm_type].
- Search(det_ctx->sgh->mpm_hscd_ctx_tc, &det_ctx->mtcu,
- &det_ctx->pmq, stat_code, stat_code_len);
- }
+ DEBUG_VALIDATE_BUG_ON(!(flags & STREAM_TOCLIENT));
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hscd_ctx_tc == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hscd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hscd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, stat_code, stat_code_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_huad_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_huad_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_huad_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, ua, ua_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_huad_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_huad_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_huad_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, ua, ua_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hhhd_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hhhd_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_hhhd_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, hh, hh_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hhhd_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hhhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hhhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, hh, hh_len);
SCReturnUInt(ret);
}
SCEnter();
uint32_t ret;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_hrhhd_ctx_ts == NULL)
- SCReturnUInt(0);
- ret = mpm_table[det_ctx->sgh->mpm_hrhhd_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_hrhhd_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, hrh, hrh_len);
- } else {
- BUG_ON(1);
- }
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_hrhhd_ctx_ts == NULL);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrhhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hrhhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, hrh, hrh_len);
SCReturnUInt(ret);
}
uint32_t ret = 0;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_dnsquery_ctx_ts == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_dnsquery_ctx_ts == NULL);
- ret = mpm_table[det_ctx->sgh->mpm_dnsquery_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_dnsquery_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, buffer, buffer_len);
- }
+ ret = mpm_table[det_ctx->sgh->mpm_dnsquery_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_dnsquery_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, buffer, buffer_len);
SCReturnUInt(ret);
}
uint32_t ret = 0;
- if (flags & STREAM_TOSERVER) {
- if (det_ctx->sgh->mpm_smtp_filedata_ctx_ts == NULL)
- SCReturnUInt(0);
+ DEBUG_VALIDATE_BUG_ON(flags & STREAM_TOCLIENT);
+ DEBUG_VALIDATE_BUG_ON(det_ctx->sgh->mpm_smtp_filedata_ctx_ts == NULL);
- ret = mpm_table[det_ctx->sgh->mpm_smtp_filedata_ctx_ts->mpm_type].
- Search(det_ctx->sgh->mpm_smtp_filedata_ctx_ts, &det_ctx->mtcu,
- &det_ctx->pmq, buffer, buffer_len);
- }
+ ret = mpm_table[det_ctx->sgh->mpm_smtp_filedata_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_smtp_filedata_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, buffer, buffer_len);
SCReturnUInt(ret);
}
{
/* content */
if (!(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
- SCLogDebug("destroying mpm_ctx %p (sh %p)",
- sh->mpm_proto_tcp_ctx_ts, sh);
if (sh->mpm_proto_tcp_ctx_ts != NULL &&
- !sh->mpm_proto_tcp_ctx_ts->global) {
+ !sh->mpm_proto_tcp_ctx_ts->global)
+ {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_tcp_ctx_ts, sh);
mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].
DestroyCtx(sh->mpm_proto_tcp_ctx_ts);
SCFree(sh->mpm_proto_tcp_ctx_ts);
/* ready for reuse */
sh->mpm_proto_tcp_ctx_ts = NULL;
- SCLogDebug("destroying mpm_ctx %p (sh %p)",
- sh->mpm_proto_tcp_ctx_tc, sh);
if (sh->mpm_proto_tcp_ctx_tc != NULL &&
- !sh->mpm_proto_tcp_ctx_tc->global) {
+ !sh->mpm_proto_tcp_ctx_tc->global)
+ {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_tcp_ctx_tc, sh);
mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].
DestroyCtx(sh->mpm_proto_tcp_ctx_tc);
SCFree(sh->mpm_proto_tcp_ctx_tc);
/* ready for reuse */
sh->mpm_proto_tcp_ctx_tc = NULL;
- SCLogDebug("destroying mpm_ctx %p (sh %p)",
- sh->mpm_proto_udp_ctx_ts, sh);
if (sh->mpm_proto_udp_ctx_ts != NULL &&
- !sh->mpm_proto_udp_ctx_ts->global) {
+ !sh->mpm_proto_udp_ctx_ts->global)
+ {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_udp_ctx_ts, sh);
mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].
DestroyCtx(sh->mpm_proto_udp_ctx_ts);
SCFree(sh->mpm_proto_udp_ctx_ts);
/* ready for reuse */
sh->mpm_proto_udp_ctx_ts = NULL;
- SCLogDebug("destroying mpm_ctx %p (sh %p)",
- sh->mpm_proto_udp_ctx_tc, sh);
if (sh->mpm_proto_udp_ctx_tc != NULL &&
- !sh->mpm_proto_udp_ctx_tc->global) {
+ !sh->mpm_proto_udp_ctx_tc->global)
+ {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_udp_ctx_tc, sh);
mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].
DestroyCtx(sh->mpm_proto_udp_ctx_tc);
SCFree(sh->mpm_proto_udp_ctx_tc);
/* ready for reuse */
sh->mpm_proto_udp_ctx_tc = NULL;
- SCLogDebug("destroying mpm_ctx %p (sh %p)",
- sh->mpm_proto_other_ctx, sh);
if (sh->mpm_proto_other_ctx != NULL &&
- !sh->mpm_proto_other_ctx->global) {
+ !sh->mpm_proto_other_ctx->global)
+ {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_other_ctx, sh);
mpm_table[sh->mpm_proto_other_ctx->mpm_type].
DestroyCtx(sh->mpm_proto_other_ctx);
SCFree(sh->mpm_proto_other_ctx);
/* uricontent */
if ((sh->mpm_uri_ctx_ts != NULL) && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
if (sh->mpm_uri_ctx_ts != NULL) {
- SCLogDebug("destroying mpm_uri_ctx %p (sh %p)", sh->mpm_uri_ctx_ts, sh);
if (!sh->mpm_uri_ctx_ts->global) {
+ SCLogDebug("destroying mpm_uri_ctx %p (sh %p)", sh->mpm_uri_ctx_ts, sh);
mpm_table[sh->mpm_uri_ctx_ts->mpm_type].DestroyCtx(sh->mpm_uri_ctx_ts);
SCFree(sh->mpm_uri_ctx_ts);
}
if ((sh->mpm_stream_ctx_ts != NULL || sh->mpm_stream_ctx_tc != NULL) &&
!(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
if (sh->mpm_stream_ctx_ts != NULL) {
- SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_ts, sh);
if (!sh->mpm_stream_ctx_ts->global) {
+ SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_ts, sh);
mpm_table[sh->mpm_stream_ctx_ts->mpm_type].DestroyCtx(sh->mpm_stream_ctx_ts);
SCFree(sh->mpm_stream_ctx_ts);
}
sh->mpm_stream_ctx_ts = NULL;
}
if (sh->mpm_stream_ctx_tc != NULL) {
- SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_tc, sh);
if (!sh->mpm_stream_ctx_tc->global) {
+ SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_tc, sh);
mpm_table[sh->mpm_stream_ctx_tc->mpm_type].DestroyCtx(sh->mpm_stream_ctx_tc);
SCFree(sh->mpm_stream_ctx_tc);
}
has_co_hrhhd ||
has_co_dnsquery)
{
-
PatternMatchPreparePopulateMpm(de_ctx, sh);
- //if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (sh->mpm_proto_tcp_ctx_ts != NULL) {
- if (sh->mpm_proto_tcp_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_ts);
- sh->mpm_proto_tcp_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].
- Prepare(sh->mpm_proto_tcp_ctx_ts);
- }
- }
- }
- }
- if (sh->mpm_proto_tcp_ctx_tc != NULL) {
- if (sh->mpm_proto_tcp_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_tc);
- sh->mpm_proto_tcp_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].
- Prepare(sh->mpm_proto_tcp_ctx_tc);
- }
- }
- }
- }
-
- if (sh->mpm_proto_udp_ctx_ts != NULL) {
- if (sh->mpm_proto_udp_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_ts);
- sh->mpm_proto_udp_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].
- Prepare(sh->mpm_proto_udp_ctx_ts);
- }
- }
- }
- }
- if (sh->mpm_proto_udp_ctx_tc != NULL) {
- if (sh->mpm_proto_udp_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_tc);
- sh->mpm_proto_udp_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].
- Prepare(sh->mpm_proto_udp_ctx_tc);
- }
- }
- }
- }
-
- if (sh->mpm_proto_other_ctx != NULL) {
- if (sh->mpm_proto_other_ctx->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx);
- sh->mpm_proto_other_ctx = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_proto_other_ctx->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_proto_other_ctx->mpm_type].
- Prepare(sh->mpm_proto_other_ctx);
- }
- }
- }
- }
-
- if (sh->mpm_stream_ctx_ts != NULL) {
- if (sh->mpm_stream_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_ts);
- sh->mpm_stream_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare(sh->mpm_stream_ctx_ts);
- }
- }
- }
- if (sh->mpm_stream_ctx_tc != NULL) {
- if (sh->mpm_stream_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_tc);
- sh->mpm_stream_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare(sh->mpm_stream_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_uri_ctx_ts != NULL) {
- if (sh->mpm_uri_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_uri_ctx_ts);
- sh->mpm_uri_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare(sh->mpm_uri_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hcbd_ctx_ts != NULL) {
- if (sh->mpm_hcbd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcbd_ctx_ts);
- sh->mpm_hcbd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare(sh->mpm_hcbd_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hsbd_ctx_tc != NULL) {
- if (sh->mpm_hsbd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsbd_ctx_tc);
- sh->mpm_hsbd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare(sh->mpm_hsbd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_smtp_filedata_ctx_ts != NULL) {
- if (sh->mpm_smtp_filedata_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_smtp_filedata_ctx_ts);
- sh->mpm_smtp_filedata_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare != NULL) {
- mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare(sh->mpm_smtp_filedata_ctx_ts);
- }
- }
- }
- }
-
- if (sh->mpm_hhd_ctx_ts != NULL) {
- if (sh->mpm_hhd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_ts);
- sh->mpm_hhd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhd_ctx_ts);
- }
- }
- }
- if (sh->mpm_hhd_ctx_tc != NULL) {
- if (sh->mpm_hhd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_tc);
- sh->mpm_hhd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare(sh->mpm_hhd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_hrhd_ctx_ts != NULL) {
- if (sh->mpm_hrhd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_ts);
- sh->mpm_hrhd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhd_ctx_ts);
- }
- }
- }
- if (sh->mpm_hrhd_ctx_tc != NULL) {
- if (sh->mpm_hrhd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_tc);
- sh->mpm_hrhd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare(sh->mpm_hrhd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_hmd_ctx_ts != NULL) {
- if (sh->mpm_hmd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hmd_ctx_ts);
- sh->mpm_hmd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare(sh->mpm_hmd_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hcd_ctx_ts != NULL) {
- if (sh->mpm_hcd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_ts);
- sh->mpm_hcd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare(sh->mpm_hcd_ctx_ts);
- }
- }
- }
- if (sh->mpm_hcd_ctx_tc != NULL) {
- if (sh->mpm_hcd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_tc);
- sh->mpm_hcd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare(sh->mpm_hcd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_hrud_ctx_ts != NULL) {
- if (sh->mpm_hrud_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrud_ctx_ts);
- sh->mpm_hrud_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare(sh->mpm_hrud_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hsmd_ctx_tc != NULL) {
- if (sh->mpm_hsmd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsmd_ctx_tc);
- sh->mpm_hsmd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare(sh->mpm_hsmd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_hscd_ctx_tc != NULL) {
- if (sh->mpm_hscd_ctx_tc->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hscd_ctx_tc);
- sh->mpm_hscd_ctx_tc = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare(sh->mpm_hscd_ctx_tc);
- }
- }
- }
-
- if (sh->mpm_huad_ctx_ts != NULL) {
- if (sh->mpm_huad_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_huad_ctx_ts);
- sh->mpm_huad_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare(sh->mpm_huad_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hhhd_ctx_ts != NULL) {
- if (sh->mpm_hhhd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_ts);
- sh->mpm_hhhd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhhd_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_hrhhd_ctx_ts != NULL) {
- if (sh->mpm_hrhhd_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts);
- sh->mpm_hrhhd_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhhd_ctx_ts);
- }
- }
- }
-
- if (sh->mpm_dnsquery_ctx_ts != NULL) {
- if (sh->mpm_dnsquery_ctx_ts->pattern_cnt == 0) {
- MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_dnsquery_ctx_ts);
- sh->mpm_dnsquery_ctx_ts = NULL;
- } else {
- if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
- if (mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare != NULL)
- mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare(sh->mpm_dnsquery_ctx_ts);
- }
- }
- }
- //} /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */
+ if (sh->mpm_proto_tcp_ctx_ts != NULL) {
+ if (sh->mpm_proto_tcp_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_ts);
+ sh->mpm_proto_tcp_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].
+ Prepare(sh->mpm_proto_tcp_ctx_ts);
+ }
+ }
+ }
+ }
+ if (sh->mpm_proto_tcp_ctx_tc != NULL) {
+ if (sh->mpm_proto_tcp_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_tc);
+ sh->mpm_proto_tcp_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].
+ Prepare(sh->mpm_proto_tcp_ctx_tc);
+ }
+ }
+ }
+ }
+
+ if (sh->mpm_proto_udp_ctx_ts != NULL) {
+ if (sh->mpm_proto_udp_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_ts);
+ sh->mpm_proto_udp_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].
+ Prepare(sh->mpm_proto_udp_ctx_ts);
+ }
+ }
+ }
+ }
+ if (sh->mpm_proto_udp_ctx_tc != NULL) {
+ if (sh->mpm_proto_udp_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_tc);
+ sh->mpm_proto_udp_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].
+ Prepare(sh->mpm_proto_udp_ctx_tc);
+ }
+ }
+ }
+ }
+
+ if (sh->mpm_proto_other_ctx != NULL) {
+ if (sh->mpm_proto_other_ctx->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx);
+ sh->mpm_proto_other_ctx = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_proto_other_ctx->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_proto_other_ctx->mpm_type].
+ Prepare(sh->mpm_proto_other_ctx);
+ }
+ }
+ }
+ }
+
+ if (sh->mpm_stream_ctx_ts != NULL) {
+ if (sh->mpm_stream_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_ts);
+ sh->mpm_stream_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare(sh->mpm_stream_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_stream_ctx_tc != NULL) {
+ if (sh->mpm_stream_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_tc);
+ sh->mpm_stream_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare(sh->mpm_stream_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_uri_ctx_ts != NULL) {
+ if (sh->mpm_uri_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_uri_ctx_ts);
+ sh->mpm_uri_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare(sh->mpm_uri_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hcbd_ctx_ts != NULL) {
+ if (sh->mpm_hcbd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcbd_ctx_ts);
+ sh->mpm_hcbd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare(sh->mpm_hcbd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hsbd_ctx_tc != NULL) {
+ if (sh->mpm_hsbd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsbd_ctx_tc);
+ sh->mpm_hsbd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare(sh->mpm_hsbd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_smtp_filedata_ctx_ts != NULL) {
+ if (sh->mpm_smtp_filedata_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_smtp_filedata_ctx_ts);
+ sh->mpm_smtp_filedata_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare(sh->mpm_smtp_filedata_ctx_ts);
+ }
+ }
+ }
+ }
+
+ if (sh->mpm_hhd_ctx_ts != NULL) {
+ if (sh->mpm_hhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_ts);
+ sh->mpm_hhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hhd_ctx_tc != NULL) {
+ if (sh->mpm_hhd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_tc);
+ sh->mpm_hhd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare(sh->mpm_hhd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hrhd_ctx_ts != NULL) {
+ if (sh->mpm_hrhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_ts);
+ sh->mpm_hrhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hrhd_ctx_tc != NULL) {
+ if (sh->mpm_hrhd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_tc);
+ sh->mpm_hrhd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare(sh->mpm_hrhd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hmd_ctx_ts != NULL) {
+ if (sh->mpm_hmd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hmd_ctx_ts);
+ sh->mpm_hmd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare(sh->mpm_hmd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hcd_ctx_ts != NULL) {
+ if (sh->mpm_hcd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_ts);
+ sh->mpm_hcd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare(sh->mpm_hcd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hcd_ctx_tc != NULL) {
+ if (sh->mpm_hcd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_tc);
+ sh->mpm_hcd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare(sh->mpm_hcd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hrud_ctx_ts != NULL) {
+ if (sh->mpm_hrud_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrud_ctx_ts);
+ sh->mpm_hrud_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare(sh->mpm_hrud_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hsmd_ctx_tc != NULL) {
+ if (sh->mpm_hsmd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsmd_ctx_tc);
+ sh->mpm_hsmd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare(sh->mpm_hsmd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hscd_ctx_tc != NULL) {
+ if (sh->mpm_hscd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hscd_ctx_tc);
+ sh->mpm_hscd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare(sh->mpm_hscd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_huad_ctx_ts != NULL) {
+ if (sh->mpm_huad_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_huad_ctx_ts);
+ sh->mpm_huad_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare(sh->mpm_huad_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hhhd_ctx_ts != NULL) {
+ if (sh->mpm_hhhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_ts);
+ sh->mpm_hhhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhhd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hrhhd_ctx_ts != NULL) {
+ if (sh->mpm_hrhhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts);
+ sh->mpm_hrhhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhhd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_dnsquery_ctx_ts != NULL) {
+ if (sh->mpm_dnsquery_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_dnsquery_ctx_ts);
+ sh->mpm_dnsquery_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare(sh->mpm_dnsquery_ctx_ts);
+ }
+ }
+ }
} else {
MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx);
sh->mpm_proto_other_ctx = NULL;
uint32_t hash = 0;
uint32_t b = 0;
- SCLogDebug("hashing sgh %p (mpm_content_maxlen %u)", sgh, sgh->mpm_content_maxlen);
+ SCLogDebug("hashing sgh %p (mpm_content_minlen %u)", sgh, sgh->mpm_content_minlen);
for (b = 0; b < sgh->init->sig_size; b++)
hash += sgh->init->sig_array[b];
return;
}
+static uint16_t SignatureGetMpmPatternLen(Signature *s, 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.
*
/* enable the sig in the bitarray */
(*sgh)->init->sig_array[s->num / 8] |= 1 << (s->num % 8);
- /* update maxlen for mpm */
+ /* update minlen for mpm */
if (s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
/* check with the precalculated values from the sig */
- if (s->mpm_content_maxlen > 0) {
- if ((*sgh)->mpm_content_maxlen == 0)
- (*sgh)->mpm_content_maxlen = s->mpm_content_maxlen;
+ uint16_t mpm_content_minlen = SignatureGetMpmPatternLen(s, DETECT_SM_LIST_PMATCH);
+ if (mpm_content_minlen > 0) {
+ if ((*sgh)->mpm_content_minlen == 0)
+ (*sgh)->mpm_content_minlen = mpm_content_minlen;
- if ((*sgh)->mpm_content_maxlen > s->mpm_content_maxlen)
- (*sgh)->mpm_content_maxlen = s->mpm_content_maxlen;
+ if ((*sgh)->mpm_content_minlen > mpm_content_minlen)
+ (*sgh)->mpm_content_minlen = mpm_content_minlen;
- SCLogDebug("(%p)->mpm_content_maxlen %u", *sgh, (*sgh)->mpm_content_maxlen);
- }
- }
- if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) {
- if (s->mpm_uricontent_maxlen > 0) {
- if ((*sgh)->mpm_uricontent_maxlen == 0)
- (*sgh)->mpm_uricontent_maxlen = s->mpm_uricontent_maxlen;
-
- if ((*sgh)->mpm_uricontent_maxlen > s->mpm_uricontent_maxlen)
- (*sgh)->mpm_uricontent_maxlen = s->mpm_uricontent_maxlen;
-
- SCLogDebug("(%p)->mpm_uricontent_maxlen %u", *sgh, (*sgh)->mpm_uricontent_maxlen);
+ SCLogDebug("(%p)->mpm_content_minlen %u", *sgh, (*sgh)->mpm_content_minlen);
}
}
return 0;
for (idx = 0; idx < src->init->sig_size; idx++)
(*dst)->init->sig_array[idx] = (*dst)->init->sig_array[idx] | src->init->sig_array[idx];
- if (src->mpm_content_maxlen != 0) {
- if ((*dst)->mpm_content_maxlen == 0)
- (*dst)->mpm_content_maxlen = src->mpm_content_maxlen;
-
- if ((*dst)->mpm_content_maxlen > src->mpm_content_maxlen)
- (*dst)->mpm_content_maxlen = src->mpm_content_maxlen;
+ if (src->mpm_content_minlen != 0) {
+ if ((*dst)->mpm_content_minlen == 0)
+ (*dst)->mpm_content_minlen = src->mpm_content_minlen;
- SCLogDebug("src (%p)->mpm_content_maxlen %u", src, src->mpm_content_maxlen);
- SCLogDebug("dst (%p)->mpm_content_maxlen %u", (*dst), (*dst)->mpm_content_maxlen);
- BUG_ON((*dst)->mpm_content_maxlen == 0);
- }
- if (src->mpm_uricontent_maxlen != 0) {
- if ((*dst)->mpm_uricontent_maxlen == 0)
- (*dst)->mpm_uricontent_maxlen = src->mpm_uricontent_maxlen;
+ if ((*dst)->mpm_content_minlen > src->mpm_content_minlen)
+ (*dst)->mpm_content_minlen = src->mpm_content_minlen;
- if ((*dst)->mpm_uricontent_maxlen > src->mpm_uricontent_maxlen)
- (*dst)->mpm_uricontent_maxlen = src->mpm_uricontent_maxlen;
+ SCLogDebug("src (%p)->mpm_content_minlen %u", src, src->mpm_content_minlen);
+ SCLogDebug("dst (%p)->mpm_content_minlen %u", (*dst), (*dst)->mpm_content_minlen);
+ BUG_ON((*dst)->mpm_content_minlen == 0);
}
return 0;
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.
*
void SigGroupHeadSetFilestoreCount(DetectEngineCtx *, SigGroupHead *);
void SigGroupHeadSetFileMd5Flag(DetectEngineCtx *, SigGroupHead *);
void SigGroupHeadSetFilesizeFlag(DetectEngineCtx *, SigGroupHead *);
+uint16_t SigGroupHeadGetMinMpmSize(DetectEngineCtx *de_ctx,
+ SigGroupHead *sgh, int list);
int SigGroupHeadBuildNonMpmArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
switch (td->track) {
case TRACK_DST:
m = DetectAddressLookupInHead(&td->addrs, &p->dst);
- SCLogInfo("TRACK_DST");
+ SCLogDebug("TRACK_DST");
break;
case TRACK_SRC:
m = DetectAddressLookupInHead(&td->addrs, &p->src);
- SCLogInfo("TRACK_SRC");
+ SCLogDebug("TRACK_SRC");
break;
/* suppress if either src or dst is a match on the suppress
* address list */
* \retval -1 error
* \retval 0 ok
*/
-int DetectEngineReload(const char *filename)
+int DetectEngineReload(const char *filename, SCInstance *suri)
{
DetectEngineCtx *new_de_ctx = NULL;
DetectEngineCtx *old_de_ctx = NULL;
DetectEngineDeReference(&old_de_ctx);
return -1;
}
- if (SigLoadSignatures(new_de_ctx, NULL, 0) != 0) {
+ if (SigLoadSignatures(new_de_ctx,
+ suri->sig_file, suri->sig_file_exclusive) != 0) {
DetectEngineCtxFree(new_de_ctx);
DetectEngineDeReference(&old_de_ctx);
return -1;
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx);
DetectEngineCtx *DetectEngineReference(DetectEngineCtx *);
void DetectEngineDeReference(DetectEngineCtx **de_ctx);
-int DetectEngineReload(const char *filename);
+int DetectEngineReload(const char *filename, SCInstance *suri);
int DetectEngineEnabled(void);
int DetectEngineMTApply(void);
int DetectEngineMultiTenantEnabled(void);
#include "util-lua-http.h"
#include "util-lua-dns.h"
#include "util-lua-tls.h"
+#include "util-lua-ssh.h"
static const char luaext_key_ld[] = "suricata:luajitdata";
static const char luaext_key_det_ctx[] = "suricata:det_ctx";
LuaRegisterHttpFunctions(lua_state);
LuaRegisterDnsFunctions(lua_state);
LuaRegisterTlsFunctions(lua_state);
+ LuaRegisterSshFunctions(lua_state);
return 0;
}
#define DATATYPE_TLS (1<<18)
+#define DATATYPE_SSH (1<<19)
+
#ifdef HAVE_LUAJIT
static void *LuaStatePoolAlloc(void)
{
pthread_mutex_lock(&luajit_states_lock);
if (luajit_states == NULL) {
- int cnt = 0;
- char *conf_val = NULL;
+ intmax_t cnt = 0;
+ ConfNode *denode = NULL;
+ ConfNode *decnf = ConfGetNode("detect-engine");
+ if (decnf != NULL) {
+ TAILQ_FOREACH(denode, &decnf->head, next) {
+ if (strcmp(denode->val, "luajit-states") == 0) {
+ ConfGetChildValueInt(denode, "luajit-states", &cnt);
+ }
+ }
+ }
- if ((ConfGet("detect-engine.luajit-states", &conf_val)) == 1) {
- cnt = (int)atoi(conf_val);
- } else {
+ if (cnt == 0) {
int cpus = UtilCpuGetNumProcessorsOnline();
if (cpus == 0) {
cpus = 10;
ld->flags |= DATATYPE_TLS;
+ } else if (strncmp(k, "ssh", 3) == 0 && strcmp(v, "true") == 0) {
+
+ ld->alproto = ALPROTO_SSH;
+
+ ld->flags |= DATATYPE_SSH;
+
} else {
SCLogError(SC_ERR_LUA_ERROR, "unsupported data type %s", k);
goto error;
}
} else if (luajit->alproto == ALPROTO_TLS) {
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
+ } else if (luajit->alproto == ALPROTO_SSH) {
+ SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
} else {
SCLogError(SC_ERR_LUA_ERROR, "luajit can't be used with protocol %s",
AppLayerGetProtoName(luajit->alproto));
static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
uint8_t dir)
{
- SigMatch *sm;
Signature *sig = SigAlloc();
if (sig == NULL)
goto error;
if (DetectAppLayerEventPrepare(sig) < 0)
goto error;
- /* set mpm_content_len */
-
- /* determine the length of the longest pattern in the sig */
- if (sig->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
- sig->mpm_content_maxlen = 0;
-
- for (sm = sig->sm_lists[DETECT_SM_LIST_PMATCH]; sm != NULL; sm = sm->next) {
- if (sm->type == DETECT_CONTENT) {
- DetectContentData *cd = (DetectContentData *)sm->ctx;
- if (cd == NULL)
- continue;
-
- if (sig->mpm_content_maxlen == 0)
- sig->mpm_content_maxlen = cd->content_len;
- if (sig->mpm_content_maxlen < cd->content_len)
- sig->mpm_content_maxlen = cd->content_len;
- }
- }
- }
- if (sig->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) {
- sig->mpm_uricontent_maxlen = 0;
-
- for (sm = sig->sm_lists[DETECT_SM_LIST_UMATCH]; sm != NULL; sm = sm->next) {
- if (sm->type == DETECT_CONTENT) {
- DetectContentData *ud = (DetectContentData *)sm->ctx;
- if (ud == NULL)
- continue;
-
- if (sig->mpm_uricontent_maxlen == 0)
- sig->mpm_uricontent_maxlen = ud->content_len;
- if (sig->mpm_uricontent_maxlen < ud->content_len)
- sig->mpm_uricontent_maxlen = ud->content_len;
- }
- }
- }
-
/* set the packet and app layer flags, but only if the
* app layer flag wasn't already set in which case we
* only consider the app layer */
goto end;
}
- if (sig->mpm_content_maxlen != 4) {
- printf("mpm content max len %"PRIu16", expected 4: ", sig->mpm_content_maxlen);
- goto end;
- }
-
- if (sig->mpm_uricontent_maxlen != 0) {
- printf("mpm uricontent max len %"PRIu16", expected 0: ", sig->mpm_uricontent_maxlen);
- goto end;
- }
-
result = 1;
end:
if (sig != NULL)
goto end;
}
- if (sig->mpm_content_maxlen != 6) {
- printf("mpm content max len %"PRIu16", expected 6: ", sig->mpm_content_maxlen);
- goto end;
- }
-
- if (sig->mpm_uricontent_maxlen != 0) {
- printf("mpm uricontent max len %"PRIu16", expected 0: ", sig->mpm_uricontent_maxlen);
- goto end;
- }
-
result = 1;
end:
if (sig != NULL)
return set;
}
+static int DetectPcreHasUpperCase(const char *re)
+{
+ size_t len = strlen(re);
+ int is_meta = 0;
+
+ for (size_t i = 0; i < len; i++) {
+ if (is_meta) {
+ is_meta = 0;
+ }
+ else if (re[i] == '\\') {
+ is_meta = 1;
+ }
+ else if (isupper((unsigned char)re[i])) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx, char *regexstr, int *sm_list)
{
int ec;
char re[slen], op_str[64] = "";
uint16_t pos = 0;
uint8_t negate = 0;
- uint16_t re_len = 0;
- uint32_t u = 0;
while (pos < slen && isspace((unsigned char)regexstr[pos])) {
pos++;
"Since the hostname buffer we match against "
"is actually lowercase, having a "
"nocase is redundant.");
- } else {
- re_len = strlen(re);
- for (u = 0; u < re_len; u++) {
- if (isupper((unsigned char)re[u])) {
- SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre host(\"W\") "
- "specified has an uppercase char. "
- "Since the hostname buffer we match against "
- "is actually lowercase, please specify an "
- "all lowercase based pcre.");
- goto error;
- }
- }
+ }
+ else if (DetectPcreHasUpperCase(re)) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre host(\"W\") "
+ "specified has an uppercase char. "
+ "Since the hostname buffer we match against "
+ "is actually lowercase, please specify an "
+ "all lowercase based pcre.");
+ goto error;
}
}
return result;
}
+/**
+ * \brief Test parsing of pcre's with the W modifier set.
+ */
+static int DetectPcreParseHttpHost(void)
+{
+ int result = 0;
+ DetectPcreData *pd = NULL;
+ int list = DETECT_SM_LIST_NOTSET;
+ DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+
+ if (de_ctx == NULL) {
+ return 0;
+ }
+
+ pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list);
+ if (pd == NULL) {
+ goto end;
+ }
+ DetectPcreFree(pd);
+
+ list = DETECT_SM_LIST_NOTSET;
+ pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list);
+ if (pd != NULL) {
+ DetectPcreFree(pd);
+ goto end;
+ }
+
+ /* Uppercase meta characters are valid. */
+ list = DETECT_SM_LIST_NOTSET;
+ pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list);
+ if (pd == NULL) {
+ goto end;
+ }
+ DetectPcreFree(pd);
+
+ /* This should not parse as the first \ escapes the second \, then
+ * we have a D. */
+ list = DETECT_SM_LIST_NOTSET;
+ pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list);
+ if (pd != NULL) {
+ DetectPcreFree(pd);
+ goto end;
+ }
+
+ result = 1;
+
+end:
+ DetectEngineCtxFree(de_ctx);
+ return result;
+}
+
#endif /* UNITTESTS */
/**
UtRegisterTest("DetectPcreFlowvarCapture02 -- capture for http_header", DetectPcreFlowvarCapture02, 1);
UtRegisterTest("DetectPcreFlowvarCapture03 -- capture for http_header", DetectPcreFlowvarCapture03, 1);
+ UtRegisterTest("DetectPcreParseHttpHost", DetectPcreParseHttpHost, 1);
+
#endif /* UNITTESTS */
}
*/
#include "suricata-common.h"
+#include "conf.h"
#include "detect.h"
#include "app-layer-template.h"
void DetectTemplateBufferRegister(void)
{
+ if (ConfGetNode("app-layer.protocols.template") == NULL) {
+ return;
+ }
+
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].name = "template_buffer";
sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].desc =
"Template content modififier to match on the template buffers";
{
int ret = 0;
/* run the pattern matcher against the uri */
- if (det_ctx->sgh->mpm_uricontent_maxlen > uri_len) {
- SCLogDebug("not searching as pkt payload is smaller than the "
- "largest uricontent length we need to match");
+ if (det_ctx->sgh->mpm_uricontent_minlen > uri_len) {
+ SCLogDebug("not searching as uri len is smaller than the "
+ "shortest uricontent length we need to match");
} else {
- SCLogDebug("search: (%p, maxlen %" PRIu32 ", sgh->sig_cnt "
- "%" PRIu32 ")", det_ctx->sgh, det_ctx->sgh->
- mpm_uricontent_maxlen, det_ctx->sgh->sig_cnt);
+ SCLogDebug("search: (%p, minlen %" PRIu32 ", sgh->sig_cnt "
+ "%" PRIu32 ")", det_ctx->sgh,
+ det_ctx->sgh->mpm_uricontent_minlen, det_ctx->sgh->sig_cnt);
ret += UriPatternSearch(det_ctx, uri, uri_len, flags);
/* if the smsg is bigger than the current packet, we will
* process the smsg in a later run */
- if ((head->seq + head->data_len) > (TCP_GET_SEQ(p) + p->payload_len)) {
+ if (SEQ_GT((head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len))) {
SCLogDebug("smsg ends beyond current packet, skipping for now %"PRIu32">%"PRIu32,
(head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len));
goto end;
/* if the smsg is bigger than the current packet, we will
* process the smsg in a later run */
- if ((head->seq + head->data_len) > (TCP_GET_SEQ(p) + p->payload_len)) {
+ if (SEQ_GT((head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len))) {
SCLogDebug("smsg ends beyond current packet, skipping for now %"PRIu32">%"PRIu32,
(head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len));
goto end;
}
if (det_ctx->sgh->flags & SIG_GROUP_HEAD_MPM_PACKET) {
/* run the multi packet matcher against the payload of the packet */
- SCLogDebug("search: (%p, maxlen %" PRIu32 ", sgh->sig_cnt %" PRIu32 ")",
- det_ctx->sgh, det_ctx->sgh->mpm_content_maxlen, det_ctx->sgh->sig_cnt);
+ SCLogDebug("search: (%p, minlen %" PRIu32 ", sgh->sig_cnt %" PRIu32 ")",
+ det_ctx->sgh, det_ctx->sgh->mpm_content_minlen, det_ctx->sgh->sig_cnt);
PACKET_PROFILING_DETECT_START(p, PROF_DETECT_MPM_PACKET);
PacketPatternSearch(det_ctx, p);
return 0;
}
-int CreateGroupedAddrListCmpMpmMaxlen(DetectAddress *a, DetectAddress *b)
+int CreateGroupedAddrListCmpMpmMinlen(DetectAddress *a, DetectAddress *b)
{
if (a->sh == NULL || b->sh == NULL)
return 0;
- if (SMALL_MPM(a->sh->mpm_content_maxlen))
+ if (SMALL_MPM(a->sh->mpm_content_minlen))
return 1;
- if (a->sh->mpm_content_maxlen < b->sh->mpm_content_maxlen)
+ if (a->sh->mpm_content_minlen < b->sh->mpm_content_minlen)
return 1;
return 0;
}
for (gr = srchead; gr != NULL; gr = gr->next) {
BUG_ON(gr->ip.family == 0 && !(gr->flags & ADDRESS_FLAG_ANY));
- if (SMALL_MPM(gr->sh->mpm_content_maxlen) && unique_groups > 0)
+ if (SMALL_MPM(gr->sh->mpm_content_minlen) && unique_groups > 0)
unique_groups++;
groups++;
return 0;
}
-int CreateGroupedPortListCmpMpmMaxlen(DetectPort *a, DetectPort *b)
+int CreateGroupedPortListCmpMpmMinlen(DetectPort *a, DetectPort *b)
{
if (a->sh == NULL || b->sh == NULL)
return 0;
- if (SMALL_MPM(a->sh->mpm_content_maxlen))
+ if (SMALL_MPM(a->sh->mpm_content_minlen))
return 1;
- if (a->sh->mpm_content_maxlen < b->sh->mpm_content_maxlen)
+ if (a->sh->mpm_content_minlen < b->sh->mpm_content_minlen)
return 1;
return 0;
SCLogDebug("hash list gr %p", gr);
DetectPortPrint(gr);
- if (SMALL_MPM(gr->sh->mpm_content_maxlen) && unique_groups > 0)
+ if (SMALL_MPM(gr->sh->mpm_content_minlen) && unique_groups > 0)
unique_groups++;
groups++;
CreateGroupedAddrList(de_ctx,
de_ctx->flow_gh[f].tmp_gh[proto]->ipv4_head, AF_INET,
de_ctx->flow_gh[f].src_gh[proto], groups,
- CreateGroupedAddrListCmpMpmMaxlen, DetectEngineGetMaxSigId(de_ctx));
+ CreateGroupedAddrListCmpMpmMinlen, DetectEngineGetMaxSigId(de_ctx));
CreateGroupedAddrList(de_ctx,
de_ctx->flow_gh[f].tmp_gh[proto]->ipv6_head, AF_INET6,
de_ctx->flow_gh[f].src_gh[proto], groups,
- CreateGroupedAddrListCmpMpmMaxlen, DetectEngineGetMaxSigId(de_ctx));
+ CreateGroupedAddrListCmpMpmMinlen, DetectEngineGetMaxSigId(de_ctx));
CreateGroupedAddrList(de_ctx,
de_ctx->flow_gh[f].tmp_gh[proto]->any_head, AF_UNSPEC,
de_ctx->flow_gh[f].src_gh[proto], groups,
- CreateGroupedAddrListCmpMpmMaxlen, DetectEngineGetMaxSigId(de_ctx));
+ CreateGroupedAddrListCmpMpmMinlen, DetectEngineGetMaxSigId(de_ctx));
DetectAddressHeadFree(de_ctx->flow_gh[f].tmp_gh[proto]);
de_ctx->flow_gh[f].tmp_gh[proto] = NULL;
* mind the limits we use. */
int groups = (flow ? de_ctx->max_uniq_toserver_dst_groups : de_ctx->max_uniq_toclient_dst_groups);
- CreateGroupedAddrList(de_ctx, tmp_gr_list, family, gr->dst_gh, groups, CreateGroupedAddrListCmpMpmMaxlen, max_idx);
+ CreateGroupedAddrList(de_ctx, tmp_gr_list, family, gr->dst_gh, groups,
+ CreateGroupedAddrListCmpMpmMinlen, max_idx);
/* see if the sig group head of each address group is the
* same as an earlier one. If it is, free our head and use
printf("PatternMatchPrepareGroup failed\n");
goto error;
}
- if (sgr->sh->mpm_proto_tcp_ctx_ts != NULL) {
- if (de_ctx->mpm_max_patcnt < sgr->sh->mpm_proto_tcp_ctx_ts->pattern_cnt)
- de_ctx->mpm_max_patcnt = sgr->sh->mpm_proto_tcp_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += sgr->sh->mpm_proto_tcp_ctx_ts->pattern_cnt;
- }
- if (sgr->sh->mpm_proto_tcp_ctx_tc != NULL) {
- if (de_ctx->mpm_max_patcnt < sgr->sh->mpm_proto_tcp_ctx_tc->pattern_cnt)
- de_ctx->mpm_max_patcnt = sgr->sh->mpm_proto_tcp_ctx_tc->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += sgr->sh->mpm_proto_tcp_ctx_tc->pattern_cnt;
- }
- if (sgr->sh->mpm_proto_udp_ctx_ts != NULL) {
- if (de_ctx->mpm_max_patcnt < sgr->sh->mpm_proto_udp_ctx_ts->pattern_cnt)
- de_ctx->mpm_max_patcnt = sgr->sh->mpm_proto_udp_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += sgr->sh->mpm_proto_udp_ctx_ts->pattern_cnt;
- }
- if (sgr->sh->mpm_proto_udp_ctx_tc != NULL) {
- if (de_ctx->mpm_max_patcnt < sgr->sh->mpm_proto_udp_ctx_tc->pattern_cnt)
- de_ctx->mpm_max_patcnt = sgr->sh->mpm_proto_udp_ctx_tc->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += sgr->sh->mpm_proto_udp_ctx_tc->pattern_cnt;
- }
- if (sgr->sh->mpm_proto_other_ctx != NULL) {
- if (de_ctx->mpm_max_patcnt < sgr->sh->mpm_proto_other_ctx->pattern_cnt)
- de_ctx->mpm_max_patcnt = sgr->sh->mpm_proto_other_ctx->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += sgr->sh->mpm_proto_other_ctx->pattern_cnt;
- }
- if (sgr->sh->mpm_uri_ctx_ts != NULL) {
- if (de_ctx->mpm_uri_max_patcnt < sgr->sh->mpm_uri_ctx_ts->pattern_cnt)
- de_ctx->mpm_uri_max_patcnt = sgr->sh->mpm_uri_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_uri_tot_patcnt += sgr->sh->mpm_uri_ctx_ts->pattern_cnt;
- }
- /* dbg */
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && sgr->sh->mpm_proto_tcp_ctx_ts) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_proto_tcp_ctx_ts->memory_size;
- }
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && sgr->sh->mpm_proto_tcp_ctx_tc) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_proto_tcp_ctx_tc->memory_size;
- }
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && sgr->sh->mpm_proto_udp_ctx_ts) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_proto_udp_ctx_ts->memory_size;
- }
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && sgr->sh->mpm_proto_udp_ctx_tc) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_proto_udp_ctx_tc->memory_size;
- }
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && sgr->sh->mpm_proto_other_ctx) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_proto_other_ctx->memory_size;
- }
- if (!(sgr->sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY) && sgr->sh->mpm_uri_ctx_ts) {
- de_ctx->mpm_memory_size += sgr->sh->mpm_uri_ctx_ts->memory_size;
- }
-
SigGroupHeadHashAdd(de_ctx, sgr->sh);
SigGroupHeadStore(de_ctx, sgr->sh);
de_ctx->gh_unique++;
* mind the limits we use. */
int groups = (flow ? de_ctx->max_uniq_toserver_dst_groups : de_ctx->max_uniq_toclient_dst_groups);
- CreateGroupedAddrList(de_ctx, tmp_gr_list, family, src_gr->dst_gh, groups, CreateGroupedAddrListCmpMpmMaxlen, max_idx);
+ CreateGroupedAddrList(de_ctx, tmp_gr_list, family, src_gr->dst_gh, groups,
+ CreateGroupedAddrListCmpMpmMinlen, max_idx);
/* add the ports to the dst address groups and the sigs
* to the ports */
int spgroups = (flow ? de_ctx->max_uniq_toserver_sp_groups : de_ctx->max_uniq_toclient_sp_groups);
- CreateGroupedPortList(de_ctx, de_ctx->sport_hash_table, &dst_gr->port, spgroups, CreateGroupedPortListCmpMpmMaxlen, max_idx);
+ CreateGroupedPortList(de_ctx, de_ctx->sport_hash_table, &dst_gr->port, spgroups,
+ CreateGroupedPortListCmpMpmMinlen, max_idx);
SCLogDebug("adding sgh %p to the hash", dst_gr->sh);
SigGroupHeadHashAdd(de_ctx, dst_gr->sh);
CreateGroupedPortList(de_ctx, de_ctx->dport_hash_table,
&sp->dst_ph, dpgroups,
- CreateGroupedPortListCmpMpmMaxlen, max_idx);
+ CreateGroupedPortListCmpMpmMinlen, max_idx);
SigGroupHeadSPortHashAdd(de_ctx, sp->sh);
printf("PatternMatchPrepareGroup failed\n");
goto error;
}
- if (dp->sh->mpm_proto_tcp_ctx_ts != NULL) {
- if (de_ctx->mpm_max_patcnt < dp->sh->mpm_proto_tcp_ctx_ts->pattern_cnt)
- de_ctx->mpm_max_patcnt = dp->sh->mpm_proto_tcp_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += dp->sh->mpm_proto_tcp_ctx_ts->pattern_cnt;
- }
- if (dp->sh->mpm_proto_tcp_ctx_tc != NULL) {
- if (de_ctx->mpm_max_patcnt < dp->sh->mpm_proto_tcp_ctx_tc->pattern_cnt)
- de_ctx->mpm_max_patcnt = dp->sh->mpm_proto_tcp_ctx_tc->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += dp->sh->mpm_proto_tcp_ctx_tc->pattern_cnt;
- }
- if (dp->sh->mpm_proto_udp_ctx_ts != NULL) {
- if (de_ctx->mpm_max_patcnt < dp->sh->mpm_proto_udp_ctx_ts->pattern_cnt)
- de_ctx->mpm_max_patcnt = dp->sh->mpm_proto_udp_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += dp->sh->mpm_proto_udp_ctx_ts->pattern_cnt;
- }
- if (dp->sh->mpm_proto_udp_ctx_tc != NULL) {
- if (de_ctx->mpm_max_patcnt < dp->sh->mpm_proto_udp_ctx_tc->pattern_cnt)
- de_ctx->mpm_max_patcnt = dp->sh->mpm_proto_udp_ctx_tc->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += dp->sh->mpm_proto_udp_ctx_tc->pattern_cnt;
- }
- if (dp->sh->mpm_proto_other_ctx != NULL) {
- if (de_ctx->mpm_max_patcnt < dp->sh->mpm_proto_other_ctx->pattern_cnt)
- de_ctx->mpm_max_patcnt = dp->sh->mpm_proto_other_ctx->pattern_cnt;
-
- de_ctx->mpm_tot_patcnt += dp->sh->mpm_proto_other_ctx->pattern_cnt;
- }
- if (dp->sh->mpm_uri_ctx_ts != NULL) {
- if (de_ctx->mpm_uri_max_patcnt < dp->sh->mpm_uri_ctx_ts->pattern_cnt)
- de_ctx->mpm_uri_max_patcnt = dp->sh->mpm_uri_ctx_ts->pattern_cnt;
-
- de_ctx->mpm_uri_tot_patcnt += dp->sh->mpm_uri_ctx_ts->pattern_cnt;
- }
- /* dbg */
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && dp->sh->mpm_proto_tcp_ctx_ts) {
- de_ctx->mpm_memory_size += dp->sh->mpm_proto_tcp_ctx_ts->memory_size;
- }
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && dp->sh->mpm_proto_tcp_ctx_tc) {
- de_ctx->mpm_memory_size += dp->sh->mpm_proto_tcp_ctx_tc->memory_size;
- }
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && dp->sh->mpm_proto_udp_ctx_ts) {
- de_ctx->mpm_memory_size += dp->sh->mpm_proto_udp_ctx_ts->memory_size;
- }
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && dp->sh->mpm_proto_udp_ctx_tc) {
- de_ctx->mpm_memory_size += dp->sh->mpm_proto_udp_ctx_tc->memory_size;
- }
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_COPY) && dp->sh->mpm_proto_other_ctx) {
- de_ctx->mpm_memory_size += dp->sh->mpm_proto_other_ctx->memory_size;
- }
- if (!(dp->sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY) && dp->sh->mpm_uri_ctx_ts) {
- de_ctx->mpm_memory_size += dp->sh->mpm_uri_ctx_ts->memory_size;
- }
-
SigGroupHeadDPortHashAdd(de_ctx, dp->sh);
SigGroupHeadStore(de_ctx, dp->sh);
de_ctx->gh_unique++;
DetectPortSpHashFree(de_ctx);
if (!(de_ctx->flags & DE_QUIET)) {
- SCLogDebug("MPM memory %" PRIuMAX " (dynamic %" PRIu32 ", ctxs %" PRIuMAX ", avg per ctx %" PRIu32 ")",
- de_ctx->mpm_memory_size + ((de_ctx->mpm_unique + de_ctx->mpm_uri_unique) * (uintmax_t)sizeof(MpmCtx)),
- de_ctx->mpm_memory_size, ((de_ctx->mpm_unique + de_ctx->mpm_uri_unique) * (uintmax_t)sizeof(MpmCtx)),
- de_ctx->mpm_unique ? de_ctx->mpm_memory_size / de_ctx->mpm_unique: 0);
-
SCLogDebug("max sig id %" PRIu32 ", array size %" PRIu32 "", DetectEngineGetMaxSigId(de_ctx), DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
SCLogDebug("signature group heads: unique %" PRIu32 ", copies %" PRIu32 ".", de_ctx->gh_unique, de_ctx->gh_reuse);
- SCLogDebug("MPM instances: %" PRIu32 " unique, copies %" PRIu32 " (none %" PRIu32 ").",
- de_ctx->mpm_unique, de_ctx->mpm_reuse, de_ctx->mpm_none);
- SCLogDebug("MPM (URI) instances: %" PRIu32 " unique, copies %" PRIu32 " (none %" PRIu32 ").",
- de_ctx->mpm_uri_unique, de_ctx->mpm_uri_reuse, de_ctx->mpm_uri_none);
- SCLogDebug("MPM max patcnt %" PRIu32 ", avg %" PRIu32 "", de_ctx->mpm_max_patcnt, de_ctx->mpm_unique?de_ctx->mpm_tot_patcnt/de_ctx->mpm_unique:0);
- if (de_ctx->mpm_uri_tot_patcnt && de_ctx->mpm_uri_unique)
- SCLogDebug("MPM (URI) max patcnt %" PRIu32 ", avg %" PRIu32 " (%" PRIu32 "/%" PRIu32 ")", de_ctx->mpm_uri_max_patcnt, de_ctx->mpm_uri_tot_patcnt/de_ctx->mpm_uri_unique, de_ctx->mpm_uri_tot_patcnt, de_ctx->mpm_uri_unique);
SCLogDebug("port maxgroups: %" PRIu32 ", avg %" PRIu32 ", tot %" PRIu32 "", g_groupportlist_maxgroups, g_groupportlist_groupscnt ? g_groupportlist_totgroups/g_groupportlist_groupscnt : 0, g_groupportlist_totgroups);
SCLogInfo("building signature grouping structure, stage 3: building destination address lists... complete");
SCLogDebug("filestore count %u", sgh->filestore_cnt);
SigGroupHeadBuildNonMpmArray(de_ctx, sgh);
+
+ sgh->mpm_uricontent_minlen = SigGroupHeadGetMinMpmSize(de_ctx, sgh, DETECT_SM_LIST_UMATCH);
+ SCLogDebug("http_uri content min mpm len: %u", sgh->mpm_uricontent_minlen);
}
if (de_ctx->decoder_event_sgh != NULL) {
DetectPort *dp = sp->dst_ph;
for ( ; dp != NULL; dp = dp->next) {
printf(" 4 Dst port(range): "); DetectPortPrint(dp);
- printf(" (sigs %" PRIu32 ", sgh %p, maxlen %" PRIu32 ")", dp->sh->sig_cnt, dp->sh, dp->sh->mpm_content_maxlen);
+ printf(" (sigs %" PRIu32 ", sgh %p, minlen %" PRIu32 ")", dp->sh->sig_cnt, dp->sh, dp->sh->mpm_content_minlen);
#ifdef PRINTSIGS
printf(" - ");
for (u = 0; u < dp->sh->sig_cnt; u++) {
printf("internal id != 0: ");
goto end;
}
- if (de_ctx->sig_list->mpm_content_maxlen != 3) {
- printf("de_ctx->sig_list->mpm_content_maxlen %u, expected 3: ", de_ctx->sig_list->mpm_content_maxlen);
- goto end;
- }
de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any 81 (msg:\"2\"; content:\"two\"; content:\"abcd\"; sid:2;)");
if (de_ctx->sig_list->next == NULL) {
printf("internal id != 1: ");
goto end;
}
- if (de_ctx->sig_list->next->mpm_content_maxlen != 4) {
- printf("de_ctx->sig_list->mpm_content_maxlen %u, expected 4: ", de_ctx->sig_list->next->mpm_content_maxlen);
- goto end;
- }
de_ctx->sig_list->next->next = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"3\"; content:\"three\"; sid:3;)");
if (de_ctx->sig_list->next->next == NULL) {
printf("internal id != 2: ");
goto end;
}
- if (de_ctx->sig_list->next->next->mpm_content_maxlen != 5) {
- printf("de_ctx->sig_list->next->next->mpm_content_maxlen %u, expected 5: ", de_ctx->sig_list->next->next->mpm_content_maxlen);
- goto end;
- }
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
#endif
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
#if 0
printf("-\n");
- printf("sgh2->mpm_content_maxlen %u\n", sgh2->mpm_content_maxlen);
- printf("sgh2->mpm_uricontent_maxlen %u\n", sgh2->mpm_uricontent_maxlen);
+ printf("sgh2->mpm_content_minlen %u\n", sgh2->mpm_content_minlen);
+ printf("sgh2->mpm_uricontent_minlen %u\n", sgh2->mpm_uricontent_minlen);
printf("sgh2->sig_cnt %u\n", sgh2->sig_cnt);
printf("sgh2->sig_size %u\n", sgh2->sig_size);
#endif
- if (sgh2->mpm_content_maxlen != 4) {
- printf("sgh2->mpm_content_maxlen %u, expected 4: ", sgh2->mpm_content_maxlen);
+ if (sgh2->mpm_content_minlen != 4) {
+ printf("sgh2->mpm_content_minlen %u, expected 4: ", sgh2->mpm_content_minlen);
goto end;
}
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
}
#if 0
printf("-\n");
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
#endif
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
#if 0
printf("-\n");
printf("sgh %p\n", sgh);
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3 (%x): ", sgh->mpm_content_maxlen, p->dst.addr_data32[0]);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3 (%x): ", sgh->mpm_content_minlen, p->dst.addr_data32[0]);
goto end;
}
}
#if 0
printf("-\n");
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
#endif
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
goto end;
}
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
goto end;
}
#if 0
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
}
#if 0
printf("-\n");
- printf("sgh->mpm_content_maxlen %u\n", sgh->mpm_content_maxlen);
- printf("sgh->mpm_uricontent_maxlen %u\n", sgh->mpm_uricontent_maxlen);
+ printf("sgh->mpm_content_minlen %u\n", sgh->mpm_content_minlen);
+ printf("sgh->mpm_uricontent_minlen %u\n", sgh->mpm_uricontent_minlen);
printf("sgh->sig_cnt %u\n", sgh->sig_cnt);
printf("sgh->sig_size %u\n", sgh->sig_size);
printf("sgh->refcnt %u\n", sgh->refcnt);
#endif
- if (sgh->mpm_content_maxlen != 3) {
- printf("sgh->mpm_content_maxlen %u, expected 3: ", sgh->mpm_content_maxlen);
+ if (sgh->mpm_content_minlen != 3) {
+ printf("sgh->mpm_content_minlen %u, expected 3: ", sgh->mpm_content_minlen);
goto end;
}
SigMatch *dsize_sm;
/* the fast pattern added from this signature */
SigMatch *mpm_sm;
- /* helper for init phase */
- uint16_t mpm_content_maxlen;
- uint16_t mpm_uricontent_maxlen;
+ /* SigMatch list used for adding content and friends. E.g. file_data; */
int list;
/* Be careful, this pointer is only valid while parsing the sig,
/* main sigs */
DetectEngineLookupFlow flow_gh[FLOW_STATES];
- uint32_t mpm_unique, mpm_reuse, mpm_none,
- mpm_uri_unique, mpm_uri_reuse, mpm_uri_none;
uint32_t gh_unique, gh_reuse;
- uint32_t mpm_max_patcnt, mpm_min_patcnt, mpm_tot_patcnt,
- mpm_uri_max_patcnt, mpm_uri_min_patcnt, mpm_uri_tot_patcnt;
-
/* init phase vars */
HashListTable *sgh_hash_table;
/* hash table used to cull out duplicate sigs */
HashListTable *dup_sig_hash_table;
- /* memory counters */
- uint32_t mpm_memory_size;
-
DetectEngineIPOnlyCtx io_ctx;
ThresholdCtx ths_ctx;
/* number of sigs in this head */
SigIntId sig_cnt;
- uint16_t mpm_content_maxlen;
+ /* track min pattern length for content. Used in grouping */
+ uint16_t mpm_content_minlen;
/** array of masks, used to check multiple masks against
* a packet using SIMD. */
MpmCtx *mpm_hsmd_ctx_tc;
MpmCtx *mpm_hscd_ctx_tc;
- uint16_t mpm_uricontent_maxlen;
+ uint16_t mpm_uricontent_minlen; /**< len of shortest mpm pattern in sgh */
/** the number of signatures in this sgh that have the filestore keyword
* set. */
#include "flow-util.h"
#include "flow-private.h"
#include "flow-manager.h"
+#include "flow-storage.h"
#include "app-layer-parser.h"
#include "util-time.h"
f = FlowDequeue(&flow_spare_q);
if (f == NULL) {
/* If we reached the max memcap, we get a used flow */
- if (!(FLOW_CHECK_MEMCAP(sizeof(Flow)))) {
+ if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) {
/* declare state of emergency */
if (!(SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)) {
SC_ATOMIC_OR(flow_flags, FLOW_EMERGENCY);
f = FlowGetUsedFlow(tv, dtv);
if (f == NULL) {
+ /* max memcap reached, so increments the counter */
+ if (tv != NULL && dtv != NULL) {
+ StatsIncr(tv, dtv->counter_flow_memcap);
+ }
+
/* very rare, but we can fail. Just giving up */
return NULL;
}
/* now see if we can alloc a new flow */
f = FlowAlloc();
if (f == NULL) {
+ if (tv != NULL && dtv != NULL) {
+ StatsIncr(tv, dtv->counter_flow_memcap);
+ }
return NULL;
}
/* pre allocate flows */
for (i = 0; i < flow_config.prealloc; i++) {
- if (!(FLOW_CHECK_MEMCAP(sizeof(Flow)))) {
+ if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) {
SCLogError(SC_ERR_FLOW_INIT, "preallocating flows failed: "
"max flow memcap reached. Memcap %"PRIu64", "
"Memuse %"PRIu64".", flow_config.memcap,
if (quiet == FALSE) {
SCLogInfo("preallocated %" PRIu32 " flows of size %" PRIuMAX "",
- flow_spare_q.len, (uintmax_t)sizeof(Flow));
+ flow_spare_q.len, (uintmax_t)(sizeof(Flow) + + FlowStorageSize()));
SCLogInfo("flow memory usage: %llu bytes, maximum: %"PRIu64,
SC_ATOMIC_GET(flow_memuse), flow_config.memcap);
}
return StorageGetSize(STORAGE_HOST);
}
-void *HostGetStorageById(Host *h, int id)
-{
- return StorageGetById((Storage *)((void *)h + sizeof(Host)), STORAGE_HOST, id);
+/** \defgroup hoststorage Host storage API
+ *
+ * The Host storage API is a per-host storage. It is a mean to extend
+ * the Host structure with arbitrary data.
+ *
+ * You have first to register the storage via HostStorageRegister() during
+ * the init of your module. Then you can attach data via HostSetStorageById()
+ * and access them via HostGetStorageById().
+ * @{
+ */
+
+/**
+ * \brief Register a Host storage
+ *
+ * \param name the name of the storage
+ * \param size integer coding the size of the stored value (sizeof(void *) is best choice here)
+ * \param Alloc allocation function for the storage (can be null)
+ * \param Free free function for the new storage
+ *
+ * \retval The ID of the newly register storage that will be used to access data
+ *
+ * It has to be called once during the init of the sub system
+ */
+
+int HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void (*Free)(void *)) {
+ return StorageRegister(STORAGE_HOST, name, size, Alloc, Free);
}
+/**
+ * \brief Store a pointer in a given Host storage
+ *
+ * \param h a pointer to the Host
+ * \param id the id of the storage (return of HostStorageRegister() call)
+ * \param ptr pointer to the data to store
+ */
+
int HostSetStorageById(Host *h, int id, void *ptr)
{
return StorageSetById((Storage *)((void *)h + sizeof(Host)), STORAGE_HOST, id, ptr);
}
+/**
+ * \brief Get a value from a given Host storage
+ *
+ * \param h a pointer to the Host
+ * \param id the id of the storage (return of HostStorageRegister() call)
+ *
+ */
+
+void *HostGetStorageById(Host *h, int id)
+{
+ return StorageGetById((Storage *)((void *)h + sizeof(Host)), STORAGE_HOST, id);
+}
+
+/**
+ * @}
+ */
+
+/* Start of "private" function */
+
void *HostAllocStorageById(Host *h, int id)
{
return StorageAllocByIdPrealloc((Storage *)((void *)h + sizeof(Host)), STORAGE_HOST, id);
StorageFreeAll((Storage *)((void *)h + sizeof(Host)), STORAGE_HOST);
}
-int HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void (*Free)(void *)) {
- return StorageRegister(STORAGE_HOST, name, size, Alloc, Free);
-}
#ifdef UNITTESTS
/** queue with spare hosts */
static HostQueue host_spare_q;
+/** size of the host object. Maybe updated in HostInitConfig to include
+ * the storage APIs additions. */
+static uint16_t g_host_size = sizeof(Host);
+
uint32_t HostSpareQueueGetSize(void)
{
return HostQueueLen(&host_spare_q);
Host *HostAlloc(void)
{
- size_t size = sizeof(Host) + HostStorageSize();
-
- if (!(HOST_CHECK_MEMCAP(size))) {
+ if (!(HOST_CHECK_MEMCAP(g_host_size))) {
return NULL;
}
+ (void) SC_ATOMIC_ADD(host_memuse, g_host_size);
- (void) SC_ATOMIC_ADD(host_memuse, size);
-
- Host *h = SCMalloc(size);
+ Host *h = SCMalloc(g_host_size);
if (unlikely(h == NULL))
goto error;
- memset(h, 0x00, size);
+ memset(h, 0x00, g_host_size);
SCMutexInit(&h->m, NULL);
SC_ATOMIC_INIT(h->use_cnt);
SC_ATOMIC_DESTROY(h->use_cnt);
SCMutexDestroy(&h->m);
SCFree(h);
- (void) SC_ATOMIC_SUB(host_memuse, (sizeof(Host) + HostStorageSize()));
+ (void) SC_ATOMIC_SUB(host_memuse, g_host_size);
}
}
void HostInitConfig(char quiet)
{
SCLogDebug("initializing host engine...");
+ if (HostStorageSize() > 0)
+ g_host_size = sizeof(Host) + HostStorageSize();
memset(&host_config, 0, sizeof(host_config));
//SC_ATOMIC_INIT(flow_flags);
/* pre allocate hosts */
for (i = 0; i < host_config.prealloc; i++) {
- if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) {
+ if (!(HOST_CHECK_MEMCAP(g_host_size))) {
SCLogError(SC_ERR_HOST_INIT, "preallocating hosts failed: "
"max host memcap reached. Memcap %"PRIu64", "
"Memuse %"PRIu64".", host_config.memcap,
- ((uint64_t)SC_ATOMIC_GET(host_memuse) + (uint64_t)sizeof(Host)));
+ ((uint64_t)SC_ATOMIC_GET(host_memuse) + g_host_size));
exit(EXIT_FAILURE);
}
}
if (quiet == FALSE) {
- SCLogInfo("preallocated %" PRIu32 " hosts of size %" PRIuMAX "",
- host_spare_q.len, (uintmax_t)sizeof(Host));
+ SCLogInfo("preallocated %" PRIu32 " hosts of size %" PRIu16 "",
+ host_spare_q.len, g_host_size);
SCLogInfo("host memory usage: %llu bytes, maximum: %"PRIu64,
SC_ATOMIC_GET(host_memuse), host_config.memcap);
}
h = HostDequeue(&host_spare_q);
if (h == NULL) {
/* If we reached the max memcap, we get a used host */
- if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) {
+ if (!(HOST_CHECK_MEMCAP(g_host_size))) {
/* declare state of emergency */
//if (!(SC_ATOMIC_GET(host_flags) & HOST_EMERGENCY)) {
// SC_ATOMIC_OR(host_flags, HOST_EMERGENCY);
/** queue with spare ippairs */
static IPPairQueue ippair_spare_q;
+/** size of the ippair object. Maybe updated in IPPairInitConfig to include
+ * the storage APIs additions. */
+static uint16_t g_ippair_size = sizeof(IPPair);
+
uint32_t IPPairSpareQueueGetSize(void)
{
return IPPairQueueLen(&ippair_spare_q);
IPPair *IPPairAlloc(void)
{
- size_t size = sizeof(IPPair) + IPPairStorageSize();
-
- if (!(IPPAIR_CHECK_MEMCAP(size))) {
+ if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
return NULL;
}
- (void) SC_ATOMIC_ADD(ippair_memuse, size);
+ (void) SC_ATOMIC_ADD(ippair_memuse, g_ippair_size);
- IPPair *h = SCMalloc(size);
+ IPPair *h = SCMalloc(g_ippair_size);
if (unlikely(h == NULL))
goto error;
- memset(h, 0x00, size);
+ memset(h, 0x00, g_ippair_size);
SCMutexInit(&h->m, NULL);
SC_ATOMIC_INIT(h->use_cnt);
SC_ATOMIC_DESTROY(h->use_cnt);
SCMutexDestroy(&h->m);
SCFree(h);
- (void) SC_ATOMIC_SUB(ippair_memuse, (sizeof(IPPair) + IPPairStorageSize()));
+ (void) SC_ATOMIC_SUB(ippair_memuse, g_ippair_size);
}
}
void IPPairInitConfig(char quiet)
{
SCLogDebug("initializing ippair engine...");
+ if (IPPairStorageSize() > 0)
+ g_ippair_size = sizeof(IPPair) + IPPairStorageSize();
memset(&ippair_config, 0, sizeof(ippair_config));
//SC_ATOMIC_INIT(flow_flags);
/* pre allocate ippairs */
for (i = 0; i < ippair_config.prealloc; i++) {
- if (!(IPPAIR_CHECK_MEMCAP(sizeof(IPPair)))) {
+ if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
SCLogError(SC_ERR_IPPAIR_INIT, "preallocating ippairs failed: "
"max ippair memcap reached. Memcap %"PRIu64", "
"Memuse %"PRIu64".", ippair_config.memcap,
- ((uint64_t)SC_ATOMIC_GET(ippair_memuse) + (uint64_t)sizeof(IPPair)));
+ ((uint64_t)SC_ATOMIC_GET(ippair_memuse) + g_ippair_size));
exit(EXIT_FAILURE);
}
}
if (quiet == FALSE) {
- SCLogInfo("preallocated %" PRIu32 " ippairs of size %" PRIuMAX "",
- ippair_spare_q.len, (uintmax_t)sizeof(IPPair));
+ SCLogInfo("preallocated %" PRIu32 " ippairs of size %" PRIu16 "",
+ ippair_spare_q.len, g_ippair_size);
SCLogInfo("ippair memory usage: %llu bytes, maximum: %"PRIu64,
SC_ATOMIC_GET(ippair_memuse), ippair_config.memcap);
}
h = IPPairDequeue(&ippair_spare_q);
if (h == NULL) {
/* If we reached the max memcap, we get a used ippair */
- if (!(IPPAIR_CHECK_MEMCAP(sizeof(IPPair)))) {
+ if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
/* declare state of emergency */
//if (!(SC_ATOMIC_GET(ippair_flags) & IPPAIR_EMERGENCY)) {
// SC_ATOMIC_OR(ippair_flags, IPPAIR_EMERGENCY);
#include "app-layer-htp-xff.h"
#include "util-classification-config.h"
#include "util-syslog.h"
+#include "util-logopenfile.h"
#include "output.h"
#include "output-json.h"
#include "output-json-http.h"
#include "output-json-tls.h"
#include "output-json-ssh.h"
+#include "output-json-smtp.h"
+#include "output-json-email-common.h"
#include "util-byte.h"
#include "util-privs.h"
#include "util-proto-name.h"
#include "util-optimize.h"
#include "util-buffer.h"
-#include "util-logopenfile.h"
#include "util-crypt.h"
#define MODULE_NAME "JsonAlertLog"
#define LOG_JSON_HTTP 8
#define LOG_JSON_TLS 16
#define LOG_JSON_SSH 32
+#define LOG_JSON_SMTP 64
#define JSON_STREAM_BUFFER_SIZE 4096
return 1;
}
-/** Handle the case where no JSON support is compiled in.
- *
- */
-static void AlertJsonHttp(const Flow *f, json_t *js)
-{
- HtpState *htp_state = (HtpState *)FlowGetAppState(f);
- if (htp_state) {
- uint64_t tx_id = AppLayerParserGetTransactionLogId(f->alparser);
- htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, tx_id);
-
- if (tx) {
- json_t *hjs = json_object();
- if (unlikely(hjs == NULL))
- return;
-
- JsonHttpLogJSONBasic(hjs, tx);
- JsonHttpLogJSONExtended(hjs, tx);
-
- json_object_set_new(js, "http", hjs);
- }
- }
-
- return;
-}
-
static void AlertJsonTls(const Flow *f, json_t *js)
{
SSLState *ssl_state = (SSLState *)FlowGetAppState(f);
action = "blocked";
}
+ /* Add tx_id to root element for correlation with other events. */
+ json_object_del(js, "tx_id");
+ if (pa->flags & PACKET_ALERT_FLAG_TX)
+ json_object_set_new(js, "tx_id", json_integer(pa->tx_id));
+
json_t *ajs = json_object();
if (ajs == NULL) {
json_decref(js);
json_string((pa->s->class_msg) ? pa->s->class_msg : ""));
json_object_set_new(ajs, "severity", json_integer(pa->s->prio));
- if (pa->flags & PACKET_ALERT_FLAG_TX)
- json_object_set_new(ajs, "tx_id", json_integer(pa->tx_id));
-
if (p->tenant_id > 0)
json_object_set_new(ajs, "tenant_id", json_integer(p->tenant_id));
{
MemBuffer *payload = aft->payload_buffer;
AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx;
+ json_t *hjs = NULL;
int i;
uint16_t proto = FlowGetAppProtocol(p->flow);
/* http alert */
- if (proto == ALPROTO_HTTP)
- AlertJsonHttp(p->flow, js);
+ if (proto == ALPROTO_HTTP) {
+ hjs = JsonHttpAddMetadata(p->flow, pa->tx_id);
+ if (hjs)
+ json_object_set_new(js, "http", hjs);
+ }
FLOWLOCK_UNLOCK(p->flow);
}
}
}
+ if (json_output_ctx->flags & LOG_JSON_SMTP) {
+ if (p->flow != NULL) {
+ FLOWLOCK_RDLOCK(p->flow);
+ uint16_t proto = FlowGetAppProtocol(p->flow);
+
+ /* http alert */
+ if (proto == ALPROTO_SMTP) {
+ hjs = JsonSMTPAddMetadata(p->flow, pa->tx_id);
+ if (hjs)
+ json_object_set_new(js, "smtp", hjs);
+
+ hjs = JsonEmailAddMetadata(p->flow, pa->tx_id);
+ if (hjs)
+ json_object_set_new(js, "email", hjs);
+ }
+
+ FLOWLOCK_UNLOCK(p->flow);
+ }
+ }
+
/* payload */
if (json_output_ctx->flags & (LOG_JSON_PAYLOAD | LOG_JSON_PAYLOAD_BASE64)) {
int stream = (p->proto == IPPROTO_TCP) ?
const char *http = ConfNodeLookupChildValue(conf, "http");
const char *tls = ConfNodeLookupChildValue(conf, "tls");
const char *ssh = ConfNodeLookupChildValue(conf, "ssh");
+ const char *smtp = ConfNodeLookupChildValue(conf, "smtp");
if (ssh != NULL) {
if (ConfValIsTrue(ssh)) {
json_output_ctx->flags |= LOG_JSON_HTTP;
}
}
+ if (smtp != NULL) {
+ if (ConfValIsTrue(smtp)) {
+ json_output_ctx->flags |= LOG_JSON_SMTP;
+ }
+ }
if (payload_printable != NULL) {
if (ConfValIsTrue(payload_printable)) {
json_output_ctx->flags |= LOG_JSON_PAYLOAD;
-/* Copyright (C) 2007-2014 Open Information Security Foundation
+/* Copyright (C) 2007-2015 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
* \file
*
* \author Tom DeCanio <td@npulsetech.com>
+ * \author Eric Leblond <eric@regit.org>
*
* Implements json common email logging portion of the engine.
*/
#ifdef HAVE_LIBJANSSON
#include <jansson.h>
+#define LOG_EMAIL_DEFAULT 0
+#define LOG_EMAIL_EXTENDED (1<<0)
+#define LOG_EMAIL_ARRAY (1<<1) /* require array handling */
+#define LOG_EMAIL_COMMA (1<<2) /* require array handling */
+#define LOG_EMAIL_BODY_MD5 (1<<3)
+#define LOG_EMAIL_SUBJECT_MD5 (1<<4)
+
+struct {
+ char *config_field;
+ char *email_field;
+ uint32_t flags;
+} email_fields[] = {
+ { "reply_to", "reply-to", LOG_EMAIL_DEFAULT },
+ { "bcc", "bcc", LOG_EMAIL_COMMA|LOG_EMAIL_EXTENDED },
+ { "message_id", "message-id", LOG_EMAIL_EXTENDED },
+ { "subject", "subject", LOG_EMAIL_EXTENDED },
+ { "x_mailer", "x-mailer", LOG_EMAIL_EXTENDED },
+ { "user_agent", "user-agent", LOG_EMAIL_EXTENDED },
+ { "received", "received", LOG_EMAIL_ARRAY },
+ { "x_originating_ip", "x-originating-ip", LOG_EMAIL_DEFAULT },
+ { "in_reply_to", "in-reply-to", LOG_EMAIL_DEFAULT },
+ { "references", "references", LOG_EMAIL_DEFAULT },
+ { "importance", "importance", LOG_EMAIL_DEFAULT },
+ { "priority", "priority", LOG_EMAIL_DEFAULT },
+ { "sensitivity", "sensitivity", LOG_EMAIL_DEFAULT },
+ { "organization", "organization", LOG_EMAIL_DEFAULT },
+ { "content_md5", "content-md5", LOG_EMAIL_DEFAULT },
+ { "date", "date", LOG_EMAIL_DEFAULT },
+ { NULL, NULL, LOG_EMAIL_DEFAULT},
+};
+
+static inline char *SkipWhiteSpaceTill(char *p, char *savep)
+{
+ char *sp = p;
+ if (unlikely(p == NULL)) {
+ return NULL;
+ }
+ while (((*sp == '\t') || (*sp == ' ')) && (sp < savep)) {
+ sp++;
+ }
+ return sp;
+}
+
+static json_t* JsonEmailJsonArrayFromCommaList(const uint8_t *val, size_t len)
+{
+ json_t *ajs = json_array();
+ if (likely(ajs != NULL)) {
+ char *savep = NULL;
+ char *p;
+ char *sp;
+ char *to_line = BytesToString((uint8_t *)val, len);
+ if (likely(to_line != NULL)) {
+ p = strtok_r(to_line, ",", &savep);
+ if (p == NULL) {
+ json_decref(ajs);
+ SCFree(to_line);
+ return NULL;
+ }
+ sp = SkipWhiteSpaceTill(p, savep);
+ json_array_append_new(ajs, json_string(sp));
+ while ((p = strtok_r(NULL, ",", &savep)) != NULL) {
+ sp = SkipWhiteSpaceTill(p, savep);
+ json_array_append_new(ajs, json_string(sp));
+ }
+ }
+ SCFree(to_line);
+ }
+
+ return ajs;
+}
+
+
+#ifdef HAVE_NSS
+static void JsonEmailLogJSONMd5(OutputJsonEmailCtx *email_ctx, json_t *js, SMTPTransaction *tx)
+{
+ if (email_ctx->flags & LOG_EMAIL_SUBJECT_MD5) {
+ MimeDecField *field;
+ MimeDecEntity *entity = tx->msg_tail;
+ if (entity == NULL) {
+ return;
+ }
+ field = MimeDecFindField(entity, "subject");
+ if (field != NULL) {
+ unsigned char md5[MD5_LENGTH];
+ char smd5[256];
+ char *value = BytesToString((uint8_t *)field->value , field->value_len);
+ if (value) {
+ size_t i,x;
+ HASH_HashBuf(HASH_AlgMD5, md5, (unsigned char *)value, strlen(value));
+ for (i = 0, x = 0; x < sizeof(md5); x++) {
+ i += snprintf(smd5 + i, 255 - i, "%02x", md5[x]);
+ }
+ json_object_set_new(js, "subject_md5", json_string(smd5));
+ SCFree(value);
+ }
+ }
+ }
+
+ if (email_ctx->flags & LOG_EMAIL_BODY_MD5) {
+ MimeDecParseState *mime_state = tx->mime_state;
+ if (mime_state && mime_state->md5_ctx && (mime_state->state_flag == PARSE_DONE)) {
+ size_t x;
+ int i;
+ char s[256];
+ if (likely(s != NULL)) {
+ for (i = 0, x = 0; x < sizeof(mime_state->md5); x++) {
+ i += snprintf(s + i, 255-i, "%02x", mime_state->md5[x]);
+ }
+ json_object_set_new(js, "body_md5", json_string(s));
+ }
+ }
+ }
+}
+#endif
+
+static int JsonEmailAddToJsonArray(const uint8_t *val, size_t len, void *data)
+{
+ json_t *ajs = data;
+
+ if (ajs == NULL)
+ return 0;
+ char *value = BytesToString((uint8_t *)val, len);
+ json_array_append_new(ajs, json_string(value));
+ SCFree(value);
+ return 1;
+}
+
+static void JsonEmailLogJSONCustom(OutputJsonEmailCtx *email_ctx, json_t *js, SMTPTransaction *tx)
+{
+ int f = 0;
+ MimeDecField *field;
+ MimeDecEntity *entity = tx->msg_tail;
+ if (entity == NULL) {
+ return;
+ }
+
+ while(email_fields[f].config_field) {
+ if (((email_ctx->fields & (1ULL<<f)) != 0)
+ ||
+ ((email_ctx->flags & LOG_EMAIL_EXTENDED) && (email_fields[f].flags & LOG_EMAIL_EXTENDED))
+ ) {
+ if (email_fields[f].flags & LOG_EMAIL_ARRAY) {
+ json_t *ajs = json_array();
+ if (ajs) {
+ int found = MimeDecFindFieldsForEach(entity, email_fields[f].email_field, JsonEmailAddToJsonArray, ajs);
+ if (found > 0) {
+ json_object_set_new(js, email_fields[f].config_field, ajs);
+ } else {
+ json_decref(ajs);
+ }
+ }
+ } else if (email_fields[f].flags & LOG_EMAIL_COMMA) {
+ field = MimeDecFindField(entity, email_fields[f].email_field);
+ if (field) {
+ json_t *ajs = JsonEmailJsonArrayFromCommaList(field->value, field->value_len);
+ if (ajs) {
+ json_object_set_new(js, email_fields[f].config_field, ajs);
+ }
+ }
+ } else {
+ field = MimeDecFindField(entity, email_fields[f].email_field);
+ if (field != NULL) {
+ char *s = BytesToString((uint8_t *)field->value,
+ (size_t)field->value_len);
+ if (likely(s != NULL)) {
+ json_object_set_new(js, email_fields[f].config_field, json_string(s));
+ SCFree(s);
+ }
+ }
+ }
+
+ }
+ f++;
+ }
+}
+
/* JSON format logging */
-static TmEcode JsonEmailLogJson(JsonEmailLogThread *aft, json_t *js, const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id)
+json_t *JsonEmailLogJsonData(const Flow *f, void *state, void *vtx, uint64_t tx_id)
{
SMTPState *smtp_state;
MimeDecParseState *mime_state;
MimeDecEntity *entity;
- char *protos = NULL;
json_t *sjs = json_object();
if (sjs == NULL) {
- SCReturnInt(TM_ECODE_FAILED);
+ SCReturnPtr(NULL, "json_t");
}
/* check if we have SMTP state or not */
- AppProto proto = FlowGetAppProtocol(p->flow);
+ AppProto proto = FlowGetAppProtocol(f);
switch (proto) {
case ALPROTO_SMTP:
smtp_state = (SMTPState *)state;
if (smtp_state == NULL) {
SCLogDebug("no smtp state, so no request logging");
- SCReturnInt(TM_ECODE_FAILED);
+ SCReturnPtr(NULL, "json_t");
}
SMTPTransaction *tx = vtx;
mime_state = tx->mime_state;
entity = tx->msg_tail;
- protos = "smtp";
SCLogDebug("lets go mime_state %p, entity %p, state_flag %u", mime_state, entity, mime_state ? mime_state->state_flag : 0);
break;
default:
/* don't know how we got here */
- SCReturnInt(TM_ECODE_FAILED);
+ SCReturnPtr(NULL, "json_t");
}
if ((mime_state != NULL)) {
if (entity == NULL) {
- SCReturnInt(TM_ECODE_FAILED);
+ SCReturnPtr(NULL, "json_t");
}
- if ((entity->header_flags & HDR_IS_LOGGED) == 0) {
- MimeDecField *field;
- //printf("email LOG\n");
-
- /* From: */
- field = MimeDecFindField(entity, "from");
- if (field != NULL) {
- char *s = BytesToString((uint8_t *)field->value,
- (size_t)field->value_len);
- if (likely(s != NULL)) {
- //printf("From: \"%s\"\n", s);
- json_object_set_new(sjs, "from", json_string(s));
- SCFree(s);
- }
+ json_object_set_new(sjs, "status",
+ json_string(MimeDecParseStateGetStatus(mime_state)));
+
+ MimeDecField *field;
+
+ /* From: */
+ field = MimeDecFindField(entity, "from");
+ if (field != NULL) {
+ char *s = BytesToString((uint8_t *)field->value,
+ (size_t)field->value_len);
+ if (likely(s != NULL)) {
+ //printf("From: \"%s\"\n", s);
+ char * sp = SkipWhiteSpaceTill(s, s + strlen(s));
+ json_object_set_new(sjs, "from", json_string(sp));
+ SCFree(s);
}
+ }
- /* To: */
- char *to_line = NULL;
- field = MimeDecFindField(entity, "to");
- if (field != NULL) {
- json_t *js_to = json_array();
- if (likely(js_to != NULL)) {
- to_line = BytesToString((uint8_t *)field->value,
- (size_t)field->value_len);
- if (likely(to_line != NULL)) {
- char *savep = NULL;
- char *p;
- //printf("to_line:: TO: \"%s\" (%d)\n", to_line, strlen(to_line));
- p = strtok_r(to_line, ",", &savep);
- //printf("got another addr: \"%s\"\n", p);
- json_array_append_new(js_to, json_string(p));
- while ((p = strtok_r(NULL, ",", &savep)) != NULL) {
- //printf("got another addr: \"%s\"\n", p);
- json_array_append_new(js_to, json_string(&p[strspn(p, " ")]));
- }
- SCFree(to_line);
- }
- json_object_set_new(sjs, "to", js_to);
- }
+ /* To: */
+ field = MimeDecFindField(entity, "to");
+ if (field != NULL) {
+ json_t *ajs = JsonEmailJsonArrayFromCommaList(field->value, field->value_len);
+ if (ajs) {
+ json_object_set_new(sjs, "to", ajs);
}
+ }
- /* Cc: */
- char *cc_line = NULL;
- field = MimeDecFindField(entity, "cc");
- if (field != NULL) {
- json_t *js_cc = json_array();
- if (likely(js_cc != NULL)) {
- cc_line = BytesToString((uint8_t *)field->value,
- (size_t)field->value_len);
- if (likely(cc_line != NULL)) {
- char *savep = NULL;
- char *p;
- //printf("cc_line:: CC: \"%s\" (%d)\n", to_line, strlen(to_line));
- p = strtok_r(cc_line, ",", &savep);
- //printf("got another addr: \"%s\"\n", p);
- json_array_append_new(js_cc, json_string(p));
- while ((p = strtok_r(NULL, ",", &savep)) != NULL) {
- //printf("got another addr: \"%s\"\n", p);
- json_array_append_new(js_cc, json_string(&p[strspn(p, " ")]));
- }
- SCFree(cc_line);
- }
- json_object_set_new(sjs, "cc", js_cc);
- }
+ /* Cc: */
+ field = MimeDecFindField(entity, "cc");
+ if (field != NULL) {
+ json_t *ajs = JsonEmailJsonArrayFromCommaList(field->value, field->value_len);
+ if (ajs) {
+ json_object_set_new(sjs, "cc", ajs);
}
+ }
- /* Subject: */
- field = MimeDecFindField(entity, "subject");
- if (field != NULL) {
- char *s = BytesToString((uint8_t *)field->value, (size_t) field->value_len);
- if (likely(s != NULL)) {
- //printf("Subject: \"%s\"\n", s);
- json_object_set_new(sjs, "subject", json_string(s));
+ if (mime_state->stack == NULL || mime_state->stack->top == NULL || mime_state->stack->top->data == NULL)
+ SCReturnPtr(NULL, "json_t");
+
+ entity = (MimeDecEntity *)mime_state->stack->top->data;
+ int attch_cnt = 0;
+ int url_cnt = 0;
+ json_t *js_attch = json_array();
+ json_t *js_url = json_array();
+ if (entity->url_list != NULL) {
+ MimeDecUrl *url;
+ for (url = entity->url_list; url != NULL; url = url->next) {
+ char *s = BytesToString((uint8_t *)url->url,
+ (size_t)url->url_len);
+ if (s != NULL) {
+ json_array_append_new(js_url,
+ json_string(s));
SCFree(s);
+ url_cnt += 1;
}
}
+ }
+ for (entity = entity->child; entity != NULL; entity = entity->next) {
+ if (entity->ctnt_flags & CTNT_IS_ATTACHMENT) {
- entity->header_flags |= HDR_IS_LOGGED;
-
- if (mime_state->stack == NULL || mime_state->stack->top == NULL || mime_state->stack->top->data == NULL)
- SCReturnInt(TM_ECODE_OK);
-
- entity = (MimeDecEntity *)mime_state->stack->top->data;
- int attch_cnt = 0;
- int url_cnt = 0;
- json_t *js_attch = json_array();
- json_t *js_url = json_array();
+ char *s = BytesToString((uint8_t *)entity->filename,
+ (size_t)entity->filename_len);
+ json_array_append_new(js_attch,
+ json_string(s));
+ SCFree(s);
+ attch_cnt += 1;
+ }
if (entity->url_list != NULL) {
MimeDecUrl *url;
for (url = entity->url_list; url != NULL; url = url->next) {
char *s = BytesToString((uint8_t *)url->url,
(size_t)url->url_len);
if (s != NULL) {
- //printf("URL: \"%s\"\n", s);
json_array_append_new(js_url,
json_string(s));
SCFree(s);
}
}
}
- for (entity = entity->child; entity != NULL; entity = entity->next) {
- if (entity->ctnt_flags & CTNT_IS_ATTACHMENT) {
-
- char *s = BytesToString((uint8_t *)entity->filename,
- (size_t)entity->filename_len);
- //printf("found attachment \"%s\"\n", s);
- json_array_append_new(js_attch,
- json_string(s));
- SCFree(s);
- attch_cnt += 1;
- }
- if (entity->url_list != NULL) {
- MimeDecUrl *url;
- for (url = entity->url_list; url != NULL; url = url->next) {
- char *s = BytesToString((uint8_t *)url->url,
- (size_t)url->url_len);
- if (s != NULL) {
- //printf("URL: \"%s\"\n", s);
- json_array_append_new(js_url,
- json_string(s));
- SCFree(s);
- url_cnt += 1;
- }
- }
- }
- }
- if (attch_cnt > 0) {
- json_object_set_new(sjs, "attachment", js_attch);
- } else {
- json_decref(js_attch);
- }
- if (url_cnt > 0) {
- json_object_set_new(sjs, "url", js_url);
- } else {
- json_decref(js_url);
- }
- json_object_set_new(js, protos, sjs);
-
-// FLOWLOCK_UNLOCK(p->flow);
- SCReturnInt(TM_ECODE_OK);
}
+ if (attch_cnt > 0) {
+ json_object_set_new(sjs, "attachment", js_attch);
+ } else {
+ json_decref(js_attch);
+ }
+ if (url_cnt > 0) {
+ json_object_set_new(sjs, "url", js_url);
+ } else {
+ json_decref(js_url);
+ }
+ SCReturnPtr(sjs, "json_t");
}
-// FLOWLOCK_UNLOCK(p->flow);
- SCReturnInt(TM_ECODE_DONE);
+ json_decref(sjs);
+ SCReturnPtr(NULL, "json_t");
}
-int JsonEmailLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) {
- SCEnter();
- JsonEmailLogThread *jhl = (JsonEmailLogThread *)thread_data;
- MemBuffer *buffer = (MemBuffer *)jhl->buffer;
+/* JSON format logging */
+TmEcode JsonEmailLogJson(JsonEmailLogThread *aft, json_t *js, const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id)
+{
+ json_t *sjs = JsonEmailLogJsonData(f, state, vtx, tx_id);
+ OutputJsonEmailCtx *email_ctx = aft->emaillog_ctx;
+ SMTPTransaction *tx = (SMTPTransaction *) vtx;
+
+ if ((email_ctx->flags & LOG_EMAIL_EXTENDED) || (email_ctx->fields != 0))
+ JsonEmailLogJSONCustom(email_ctx, sjs, tx);
- json_t *js = CreateJSONHeader((Packet *)p, 1, "smtp");
- if (unlikely(js == NULL))
- return TM_ECODE_OK;
+#ifdef HAVE_NSS
+ JsonEmailLogJSONMd5(email_ctx, sjs, tx);
+#endif
- /* reset */
- MemBufferReset(buffer);
+ if (sjs) {
+ json_object_set_new(js, "email", sjs);
+ SCReturnInt(TM_ECODE_OK);
+ } else
+ SCReturnInt(TM_ECODE_FAILED);
+}
+
+json_t *JsonEmailAddMetadata(const Flow *f, uint32_t tx_id)
+{
+ SMTPState *smtp_state = (SMTPState *)FlowGetAppState(f);
+ if (smtp_state) {
+ SMTPTransaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_SMTP, smtp_state, tx_id);
- if (JsonEmailLogJson(jhl, js, p, f, state, tx, tx_id) == TM_ECODE_OK) {
- OutputJSONBuffer(js, jhl->emaillog_ctx->file_ctx, buffer);
+ if (tx) {
+ return JsonEmailLogJsonData(f, smtp_state, tx, tx_id);
+ }
}
- json_object_del(js, "smtp");
- json_object_clear(js);
- json_decref(js);
+ return NULL;
+}
+
+
+void OutputEmailInitConf(ConfNode *conf, OutputJsonEmailCtx *email_ctx)
+{
+ if (conf) {
+ const char *extended = ConfNodeLookupChildValue(conf, "extended");
+
+ if (extended != NULL) {
+ if (ConfValIsTrue(extended)) {
+ email_ctx->flags = LOG_EMAIL_EXTENDED;
+ }
+ }
+
+ email_ctx->fields = 0;
+ ConfNode *custom;
+ if ((custom = ConfNodeLookupChild(conf, "custom")) != NULL) {
+ ConfNode *field;
+ TAILQ_FOREACH(field, &custom->head, next) {
+ if (field != NULL) {
+ int f = 0;
+ while(email_fields[f].config_field) {
+ if ((strcmp(email_fields[f].config_field,
+ field->val) == 0) ||
+ (strcasecmp(email_fields[f].email_field,
+ field->val) == 0))
+ {
+ email_ctx->fields |= (1ULL<<f);
+ break;
+ }
+ f++;
+ }
+ }
+ }
+ }
- SCReturnInt(TM_ECODE_OK);
+ email_ctx->flags = 0;
+ ConfNode *md5_conf;
+ if ((md5_conf = ConfNodeLookupChild(conf, "md5")) != NULL) {
+ ConfNode *field;
+ TAILQ_FOREACH(field, &md5_conf->head, next) {
+ if (field != NULL) {
+ if (strcmp("body", field->val) == 0) {
+ SCLogInfo("Going to log the md5 sum of email body");
+ email_ctx->flags |= LOG_EMAIL_BODY_MD5;
+ }
+ if (strcmp("subject", field->val) == 0) {
+ SCLogInfo("Going to log the md5 sum of email subject");
+ email_ctx->flags |= LOG_EMAIL_SUBJECT_MD5;
+ }
+ }
+ }
+ }
+ }
+ return;
}
+
#endif
typedef struct OutputJsonEmailCtx_ {
LogFileCtx *file_ctx;
uint32_t flags; /** Store mode */
+ uint64_t fields;/** Store fields */
} OutputJsonEmailCtx;
+#ifdef HAVE_LIBJANSSON
typedef struct JsonEmailLogThread_ {
OutputJsonEmailCtx *emaillog_ctx;
MemBuffer *buffer;
} JsonEmailLogThread;
-int JsonEmailLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id);
+TmEcode JsonEmailLogJson(JsonEmailLogThread *aft, json_t *js, const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id);
+json_t *JsonEmailAddMetadata(const Flow *f, uint32_t tx_id);
+#endif
+
+void OutputEmailInitConf(ConfNode *conf, OutputJsonEmailCtx *email_ctx);
#endif /* __OUTPUT_JSON_EMAIL_COMMON_H__ */
#include "util-buffer.h"
#include "util-byte.h"
-#include "output.h"
-#include "output-json.h"
-
#include "log-file.h"
#include "util-logopenfile.h"
+#include "output.h"
+#include "output-json.h"
+#include "output-json-http.h"
+#include "output-json-smtp.h"
+#include "output-json-email-common.h"
+
#include "app-layer-htp.h"
#include "util-memcmp.h"
#include "stream-tcp-reassemble.h"
MemBuffer *buffer;
} JsonFileLogThread;
-static json_t *LogFileMetaGetUri(const Packet *p, const File *ff)
-{
- HtpState *htp_state = (HtpState *)p->flow->alstate;
- json_t *js = NULL;
- if (htp_state != NULL) {
- htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
- if (tx != NULL) {
- HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
- if (tx_ud != NULL && tx_ud->request_uri_normalized != NULL) {
- char *s = bstr_util_strdup_to_c(tx_ud->request_uri_normalized);
- if (s != NULL) {
- js = json_string(s);
- SCFree(s);
- if (js != NULL)
- return js;
- }
- }
- }
- }
-
- return NULL;
-}
-
-static json_t *LogFileMetaGetHost(const Packet *p, const File *ff)
-{
- HtpState *htp_state = (HtpState *)p->flow->alstate;
- json_t *js = NULL;
- if (htp_state != NULL) {
- htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
- if (tx != NULL && tx->request_hostname != NULL) {
- char *s = bstr_util_strdup_to_c(tx->request_hostname);
- if (s != NULL) {
- js = json_string(s);
- SCFree(s);
- if (js != NULL)
- return js;
- }
- }
- }
-
- return NULL;
-}
-
-static json_t *LogFileMetaGetReferer(const Packet *p, const File *ff)
-{
- HtpState *htp_state = (HtpState *)p->flow->alstate;
- json_t *js = NULL;
- if (htp_state != NULL) {
- htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
- if (tx != NULL) {
- htp_header_t *h = NULL;
- h = (htp_header_t *)htp_table_get_c(tx->request_headers,
- "Referer");
- if (h != NULL) {
- char *s = bstr_util_strdup_to_c(h->value);
- if (s != NULL) {
- js = json_string(s);
- SCFree(s);
- if (js != NULL)
- return js;
- }
- }
- }
- }
-
- return NULL;
-}
-
-static json_t *LogFileMetaGetUserAgent(const Packet *p, const File *ff)
-{
- HtpState *htp_state = (HtpState *)p->flow->alstate;
- json_t *js = NULL;
- if (htp_state != NULL) {
- htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, ff->txid);
- if (tx != NULL) {
- htp_header_t *h = NULL;
- h = (htp_header_t *)htp_table_get_c(tx->request_headers,
- "User-Agent");
- if (h != NULL) {
- char *s = bstr_util_strdup_to_c(h->value);
- if (s != NULL) {
- js = json_string(s);
- SCFree(s);
- if (js != NULL)
- return js;
- }
- }
- }
- }
-
- return NULL;
-}
-
/**
* \internal
* \brief Write meta data on a single line json record
{
MemBuffer *buffer = (MemBuffer *)aft->buffer;
json_t *js = CreateJSONHeader((Packet *)p, 0, "fileinfo"); //TODO const
+ json_t *hjs = NULL;
if (unlikely(js == NULL))
return;
/* reset */
MemBufferReset(buffer);
- json_t *hjs = json_object();
- if (unlikely(hjs == NULL)) {
- json_decref(js);
- return;
- }
-
- json_object_set_new(hjs, "app_proto", json_string(AppProtoToString(p->flow->alproto)));
switch (p->flow->alproto) {
case ALPROTO_HTTP:
- json_object_set_new(hjs, "url", LogFileMetaGetUri(p, ff));
- json_object_set_new(hjs, "hostname", LogFileMetaGetHost(p, ff));
- json_object_set_new(hjs, "http_refer", LogFileMetaGetReferer(p, ff));
- json_object_set_new(hjs, "http_user_agent", LogFileMetaGetUserAgent(p, ff));
- json_object_set_new(js, "http", hjs);
+ hjs = JsonHttpAddMetadata(p->flow, ff->txid);
+ if (hjs)
+ json_object_set_new(js, "http", hjs);
+ break;
+ case ALPROTO_SMTP:
+ hjs = JsonSMTPAddMetadata(p->flow, ff->txid);
+ if (hjs)
+ json_object_set_new(js, "smtp", hjs);
+ hjs = JsonEmailAddMetadata(p->flow, ff->txid);
+ if (hjs)
+ json_object_set_new(js, "email", hjs);
break;
}
json_t *fjs = json_object();
if (unlikely(fjs == NULL)) {
- json_decref(hjs);
json_decref(js);
return;
}
if (ff->flags & FILE_MD5) {
size_t x;
int i;
- char *s = SCMalloc(256);
- if (likely(s != NULL)) {
- for (i = 0, x = 0; x < sizeof(ff->md5); x++) {
- i += snprintf(&s[i], 255-i, "%02x", ff->md5[x]);
- }
- json_object_set_new(fjs, "md5", json_string(s));
- SCFree(s);
+ char s[256];
+ for (i = 0, x = 0; x < sizeof(ff->md5); x++) {
+ i += snprintf(&s[i], 255-i, "%02x", ff->md5[x]);
}
+ json_object_set_new(fjs, "md5", json_string(s));
}
#endif
break;
json_object_set_new(js, "fileinfo", fjs);
OutputJSONBuffer(js, aft->filelog_ctx->file_ctx, buffer);
json_object_del(js, "fileinfo");
- json_object_del(js, "http");
+
+ switch (p->flow->alproto) {
+ case ALPROTO_HTTP:
+ json_object_del(js, "http");
+ break;
+ case ALPROTO_SMTP:
+ json_object_del(js, "smtp");
+ json_object_del(js, "email");
+ break;
+ }
json_object_clear(js);
json_decref(js);
if (http_ctx->flags & LOG_HTTP_EXTENDED)
JsonHttpLogJSONExtended(hjs, tx);
- /* tx id for correlation with alerts */
- json_object_set_new(hjs, "tx_id", json_integer(tx_id));
-
json_object_set_new(js, "http", hjs);
}
JsonHttpLogThread *jhl = (JsonHttpLogThread *)thread_data;
MemBuffer *buffer = (MemBuffer *)jhl->buffer;
- json_t *js = CreateJSONHeader((Packet *)p, 1, "http"); //TODO const
+ json_t *js = CreateJSONHeaderWithTxId((Packet *)p, 1, "http", tx_id); //TODO const
if (unlikely(js == NULL))
return TM_ECODE_OK;
SCReturnInt(TM_ECODE_OK);
}
+json_t *JsonHttpAddMetadata(const Flow *f, uint64_t tx_id)
+{
+ HtpState *htp_state = (HtpState *)FlowGetAppState(f);
+ if (htp_state) {
+ htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, tx_id);
+
+ if (tx) {
+ json_t *hjs = json_object();
+ if (unlikely(hjs == NULL))
+ return NULL;
+
+ JsonHttpLogJSONBasic(hjs, tx);
+ JsonHttpLogJSONExtended(hjs, tx);
+
+ return hjs;
+ }
+ }
+
+ return NULL;
+}
+
static void OutputHttpLogDeinit(OutputCtx *output_ctx)
{
LogHttpFileCtx *http_ctx = output_ctx->data;
#ifdef HAVE_LIBJANSSON
void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx);
void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx);
+json_t *JsonHttpAddMetadata(const Flow *f, uint64_t tx_id);
#endif /* HAVE_LIBJANSSON */
#endif /* __OUTPUT_JSON_HTTP_H__ */
-/* Copyright (C) 2007-2013 Open Information Security Foundation
+/* Copyright (C) 2007-2015 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
#ifdef HAVE_LIBJANSSON
#include <jansson.h>
+static json_t *JsonSmtpDataLogger(const Flow *f, void *state, void *vtx, uint64_t tx_id)
+{
+ json_t *sjs = json_object();
+ SMTPTransaction *tx = vtx;
+ SMTPString *rcptto_str;
+ if (sjs == NULL) {
+ return NULL;
+ }
+ if (((SMTPState *)state)->helo) {
+ json_object_set_new(sjs, "helo",
+ json_string((const char *)((SMTPState *)state)->helo));
+ }
+ if (tx->mail_from) {
+ json_object_set_new(sjs, "mail_from",
+ json_string((const char *)tx->mail_from));
+ }
+ if (!TAILQ_EMPTY(&tx->rcpt_to_list)) {
+ json_t *js_rcptto = json_array();
+ if (likely(js_rcptto != NULL)) {
+ TAILQ_FOREACH(rcptto_str, &tx->rcpt_to_list, next) {
+ json_array_append_new(js_rcptto, json_string((char *)rcptto_str->str));
+ }
+ json_object_set_new(sjs, "rcpt_to", js_rcptto);
+ }
+ }
+
+ return sjs;
+}
+
static int JsonSmtpLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
{
SCEnter();
- int r = JsonEmailLogger(tv, thread_data, p, f, state, tx, tx_id);
- SCReturnInt(r);
+ JsonEmailLogThread *jhl = (JsonEmailLogThread *)thread_data;
+ MemBuffer *buffer = (MemBuffer *)jhl->buffer;
+
+ json_t *sjs;
+ json_t *js = CreateJSONHeaderWithTxId((Packet *)p, 1, "smtp", tx_id);
+ if (unlikely(js == NULL))
+ return TM_ECODE_OK;
+
+ /* reset */
+ MemBufferReset(buffer);
+
+ sjs = JsonSmtpDataLogger(f, state, tx, tx_id);
+ if (sjs) {
+ json_object_set_new(js, "smtp", sjs);
+ }
+
+ if (JsonEmailLogJson(jhl, js, p, f, state, tx, tx_id) == TM_ECODE_OK) {
+ OutputJSONBuffer(js, jhl->emaillog_ctx->file_ctx, buffer);
+ }
+ json_object_del(js, "email");
+ if (sjs) {
+ json_object_del(js, "smtp");
+ }
+
+ json_object_clear(js);
+ json_decref(js);
+
+ SCReturnInt(TM_ECODE_OK);
+
+}
+
+json_t *JsonSMTPAddMetadata(const Flow *f, uint64_t tx_id)
+{
+ SMTPState *smtp_state = (SMTPState *)FlowGetAppState(f);
+ if (smtp_state) {
+ SMTPTransaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_SMTP, smtp_state, tx_id);
+
+ if (tx) {
+ return JsonSmtpDataLogger(f, smtp_state, tx, tx_id);
+ }
+ }
+
+ return NULL;
}
static void OutputSmtpLogDeInitCtx(OutputCtx *output_ctx)
email_ctx->file_ctx = ojc->file_ctx;
+ OutputEmailInitConf(conf, email_ctx);
+
output_ctx->data = email_ctx;
output_ctx->DeInit = OutputSmtpLogDeInitCtxSub;
if(initdata == NULL)
{
- SCLogDebug("Error getting context for HTTPLog. \"initdata\" argument NULL");
+ SCLogDebug("Error getting context for SMTPLog. \"initdata\" argument NULL");
SCFree(aft);
return TM_ECODE_FAILED;
}
#define __OUTPUT_JSON_SMTP_H__
void TmModuleJsonSmtpLogRegister (void);
+#ifdef HAVE_LIBJANSSON
+json_t *JsonSMTPAddMetadata(const Flow *f, uint64_t tx_id);
+#endif
#endif /* __OUTPUT_JSON_SMTP_H__ */
void TmModuleJsonTemplateLogRegister(void)
{
+ if (ConfGetNode("app-layer.protocols.template") == NULL) {
+ return;
+ }
+
tmm_modules[TMM_JSONTEMPLATELOG].name = "JsonTemplateLog";
tmm_modules[TMM_JSONTEMPLATELOG].ThreadInit = JsonTemplateLogThreadInit;
tmm_modules[TMM_JSONTEMPLATELOG].ThreadDeinit = JsonTemplateLogThreadDeinit;
#define OUTPUT_BUFFER_SIZE 65535
-#ifndef OS_WIN32
-static int alert_syslog_level = DEFAULT_ALERT_SYSLOG_LEVEL;
-#endif /* OS_WIN32 */
-
TmEcode OutputJson (ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
TmEcode OutputJsonThreadInit(ThreadVars *, void *, void **);
TmEcode OutputJsonThreadDeinit(ThreadVars *, void *);
return js;
}
+json_t *CreateJSONHeaderWithTxId(Packet *p, int direction_sensitive, char *event_type, uint32_t tx_id)
+{
+ json_t *js = CreateJSONHeader(p, direction_sensitive, event_type);
+ if (unlikely(js == NULL))
+ return NULL;
+
+ /* tx id for correlation with other events */
+ json_object_set_new(js, "tx_id", json_integer(tx_id));
+
+ return js;
+}
+
+static int MemBufferCallback(const char *str, size_t size, void *data)
+{
+ MemBuffer *memb = data;
+#if 0 // can't expand, need a MemBuffer **
+ /* since we can have many threads, the buffer might not be big enough.
+ * * Expand if necessary. */
+ if (MEMBUFFER_OFFSET(memb) + size > MEMBUFFER_SIZE(memb)) {
+ MemBufferExpand(&memb, OUTPUT_BUFFER_SIZE);
+ }
+#endif
+ MemBufferWriteString(memb, "%s", str);
+ return 0;
+}
+
int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer *buffer)
{
- char *js_s = json_dumps(js,
- JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
+ if (file_ctx->sensor_name) {
+ json_object_set_new(js, "host",
+ json_string(file_ctx->sensor_name));
+ }
+
+ int r = json_dump_callback(js, MemBufferCallback, buffer,
+ JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
#ifdef JSON_ESCAPE_SLASH
JSON_ESCAPE_SLASH
#else
0
#endif
);
- if (unlikely(js_s == NULL))
+ if (r != 0)
return TM_ECODE_OK;
- SCMutexLock(&file_ctx->fp_mutex);
- if (file_ctx->type == LOGFILE_TYPE_SYSLOG)
- {
- if (file_ctx->prefix != NULL)
- {
- syslog(alert_syslog_level, "%s%s", file_ctx->prefix, js_s);
- }
- else
- {
- syslog(alert_syslog_level, "%s", js_s);
- }
- }
- else if (file_ctx->type == LOGFILE_TYPE_FILE ||
- file_ctx->type == LOGFILE_TYPE_UNIX_DGRAM ||
- file_ctx->type == LOGFILE_TYPE_UNIX_STREAM)
- {
- if (file_ctx->prefix != NULL)
- {
- MemBufferWriteString(buffer, "%s%s\n", file_ctx->prefix, js_s);
- }
- else
- {
- MemBufferWriteString(buffer, "%s\n", js_s);
- }
- file_ctx->Write((const char *)MEMBUFFER_BUFFER(buffer),
- MEMBUFFER_OFFSET(buffer), file_ctx);
- }
- SCMutexUnlock(&file_ctx->fp_mutex);
- free(js_s);
+ LogFileWrite(file_ctx, buffer);
return 0;
}
OutputCtx *OutputJsonInitCtx(ConfNode *conf)
{
OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx));;
+
+ const char *sensor_name = ConfNodeLookupChildValue(conf, "sensor-name");
+
if (unlikely(json_ctx == NULL)) {
SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx");
return NULL;
return NULL;
}
+ if (sensor_name) {
+ json_ctx->file_ctx->sensor_name = SCStrdup(sensor_name);
+ if (json_ctx->file_ctx->sensor_name == NULL) {
+ LogFileFreeCtx(json_ctx->file_ctx);
+ SCFree(json_ctx);
+ return NULL;
+ }
+ } else {
+ json_ctx->file_ctx->sensor_name = NULL;
+ }
+
OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
if (unlikely(output_ctx == NULL)) {
LogFileFreeCtx(json_ctx->file_ctx);
json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM;
} else if (strcmp(output_s, "unix_stream") == 0) {
json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM;
+ } else if (strcmp(output_s, "redis") == 0) {
+#ifdef HAVE_LIBHIREDIS
+ json_ctx->json_out = LOGFILE_TYPE_REDIS;
+#else
+ SCLogError(SC_ERR_INVALID_ARGUMENT,
+ "redis JSON output option is not compiled");
+ exit(EXIT_FAILURE);
+#endif
} else {
SCLogError(SC_ERR_INVALID_ARGUMENT,
"Invalid JSON output option: %s", output_s);
if (level_s != NULL) {
int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
if (level != -1) {
- alert_syslog_level = level;
+ json_ctx->file_ctx->syslog_setup.alert_syslog_level = level;
}
}
openlog(ident, LOG_PID|LOG_NDELAY, facility);
}
+#ifdef HAVE_LIBHIREDIS
+ else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) {
+ ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
+ if (!json_ctx->file_ctx->sensor_name) {
+ char hostname[1024];
+ gethostname(hostname, 1023);
+ json_ctx->file_ctx->sensor_name = SCStrdup(hostname);
+ }
+ if (json_ctx->file_ctx->sensor_name == NULL) {
+ LogFileFreeCtx(json_ctx->file_ctx);
+ SCFree(json_ctx);
+ SCFree(output_ctx);
+ return NULL;
+ }
+
+ if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) {
+ LogFileFreeCtx(json_ctx->file_ctx);
+ SCFree(json_ctx);
+ SCFree(output_ctx);
+ return NULL;
+ }
+ }
+#endif
const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
if (sensor_id_s != NULL) {
void CreateJSONFlowId(json_t *js, const Flow *f);
void JsonTcpFlags(uint8_t flags, json_t *js);
json_t *CreateJSONHeader(Packet *p, int direction_sensative, char *event_type);
+json_t *CreateJSONHeaderWithTxId(Packet *p, int direction_sensitive, char *event_type, uint32_t tx_id);
TmEcode OutputJSON(json_t *js, void *data, uint64_t *count);
int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer *buffer);
OutputCtx *OutputJsonInitCtx(ConfNode *);
-
enum JsonFormat { COMPACT, INDENT };
/*
#include "output.h"
#include "app-layer-htp.h"
#include "app-layer.h"
+#include "app-layer-ssl.h"
+#include "app-layer-ssh.h"
#include "app-layer-parser.h"
#include "util-privs.h"
#include "util-buffer.h"
#include "util-lua-common.h"
#include "util-lua-http.h"
#include "util-lua-dns.h"
+#include "util-lua-tls.h"
+#include "util-lua-ssh.h"
#define MODULE_NAME "LuaLog"
return FALSE;
}
+/** \internal
+ * \brief Packet Logger for lua scripts, for tls
+ *
+ * A single call to this function will run one script for a single
+ * packet. If it is called, it means that the registered condition
+ * function has returned TRUE.
+ *
+ * The script is called once for each packet.
+ */
+static int LuaPacketLoggerTls(ThreadVars *tv, void *thread_data, const Packet *p)
+{
+ LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
+
+ char timebuf[64];
+ CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
+
+ SCMutexLock(&td->lua_ctx->m);
+
+ lua_getglobal(td->lua_ctx->luastate, "log");
+
+ LuaStateSetThreadVars(td->lua_ctx->luastate, tv);
+ LuaStateSetPacket(td->lua_ctx->luastate, (Packet *)p);
+ LuaStateSetFlow(td->lua_ctx->luastate, p->flow, /* unlocked */LUA_FLOW_NOT_LOCKED_BY_PARENT);
+
+ int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
+ if (retval != 0) {
+ SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
+ }
+
+ SCMutexUnlock(&td->lua_ctx->m);
+ FLOWLOCK_WRLOCK(p->flow);
+
+ SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
+ if (ssl_state != NULL)
+ ssl_state->flags |= SSL_AL_FLAG_STATE_LOGGED_LUA;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ SCReturnInt(0);
+}
+
+static int LuaPacketConditionTls(ThreadVars *tv, const Packet *p)
+{
+ if (p->flow == NULL) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_IPV4(p)) && !(PKT_IS_IPV6(p))) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_TCP(p))) {
+ return FALSE;
+ }
+
+ FLOWLOCK_RDLOCK(p->flow);
+ uint16_t proto = FlowGetAppProtocol(p->flow);
+ if (proto != ALPROTO_TLS)
+ goto dontlog;
+
+ SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
+ if (ssl_state == NULL) {
+ SCLogDebug("no tls state, so no request logging");
+ goto dontlog;
+ }
+
+ if (ssl_state->server_connp.cert0_issuerdn == NULL ||
+ ssl_state->server_connp.cert0_subject == NULL)
+ goto dontlog;
+
+ /* We only log the state once */
+ if (ssl_state->flags & SSL_AL_FLAG_STATE_LOGGED_LUA)
+ goto dontlog;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ return TRUE;
+dontlog:
+ FLOWLOCK_UNLOCK(p->flow);
+ return FALSE;
+}
+
+/** \internal
+ * \brief Packet Logger for lua scripts, for ssh
+ *
+ * A single call to this function will run one script for a single
+ * packet. If it is called, it means that the registered condition
+ * function has returned TRUE.
+ *
+ * The script is called once for each packet.
+ */
+static int LuaPacketLoggerSsh(ThreadVars *tv, void *thread_data, const Packet *p)
+{
+ LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
+
+ char timebuf[64];
+ CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
+
+ SCMutexLock(&td->lua_ctx->m);
+
+ lua_getglobal(td->lua_ctx->luastate, "log");
+
+ LuaStateSetThreadVars(td->lua_ctx->luastate, tv);
+ LuaStateSetPacket(td->lua_ctx->luastate, (Packet *)p);
+ LuaStateSetFlow(td->lua_ctx->luastate, p->flow, /* unlocked */LUA_FLOW_NOT_LOCKED_BY_PARENT);
+
+ int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
+ if (retval != 0) {
+ SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
+ }
+
+ SCMutexUnlock(&td->lua_ctx->m);
+ FLOWLOCK_WRLOCK(p->flow);
+
+ SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
+ if (ssh_state != NULL)
+ ssh_state->cli_hdr.flags |= SSH_FLAG_STATE_LOGGED_LUA;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ SCReturnInt(0);
+}
+
+static int LuaPacketConditionSsh(ThreadVars *tv, const Packet *p)
+{
+ if (p->flow == NULL) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_IPV4(p)) && !(PKT_IS_IPV6(p))) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_TCP(p))) {
+ return FALSE;
+ }
+
+ FLOWLOCK_RDLOCK(p->flow);
+ uint16_t proto = FlowGetAppProtocol(p->flow);
+ if (proto != ALPROTO_SSH)
+ goto dontlog;
+
+ SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
+ if (ssh_state == NULL) {
+ SCLogDebug("no ssh state, so no request logging");
+ goto dontlog;
+ }
+
+ if (ssh_state->cli_hdr.software_version == NULL ||
+ ssh_state->srv_hdr.software_version == NULL)
+ goto dontlog;
+
+ /* We only log the state once */
+ if (ssh_state->cli_hdr.flags & SSH_FLAG_STATE_LOGGED_LUA)
+ goto dontlog;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ return TRUE;
+dontlog:
+ FLOWLOCK_UNLOCK(p->flow);
+ return FALSE;
+}
+
/** \internal
* \brief Packet Logger for lua scripts, for packets
*
options->alproto = ALPROTO_HTTP;
else if (strcmp(k,"protocol") == 0 && strcmp(v, "dns") == 0)
options->alproto = ALPROTO_DNS;
+ else if (strcmp(k,"protocol") == 0 && strcmp(v, "tls") == 0)
+ options->alproto = ALPROTO_TLS;
+ else if (strcmp(k,"protocol") == 0 && strcmp(v, "ssh") == 0)
+ options->alproto = ALPROTO_SSH;
else if (strcmp(k, "type") == 0 && strcmp(v, "packet") == 0)
options->packet = 1;
else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
* if the tx is registered in the state at runtime though. */
LuaRegisterHttpFunctions(luastate);
LuaRegisterDnsFunctions(luastate);
+ LuaRegisterTlsFunctions(luastate);
+ LuaRegisterSshFunctions(luastate);
if (lua_pcall(luastate, 0, 0, 0) != 0) {
SCLogError(SC_ERR_LUA_ERROR, "couldn't run script 'setup' function: %s", lua_tostring(luastate, -1));
om->TxLogFunc = LuaTxLogger;
om->alproto = ALPROTO_HTTP;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_HTTP);
+ } else if (opts.alproto == ALPROTO_TLS) {
+ om->PacketLogFunc = LuaPacketLoggerTls;
+ om->PacketConditionFunc = LuaPacketConditionTls;
} else if (opts.alproto == ALPROTO_DNS) {
om->TxLogFunc = LuaTxLogger;
om->alproto = ALPROTO_DNS;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_DNS);
AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_DNS);
+ } else if (opts.alproto == ALPROTO_SSH) {
+ om->PacketLogFunc = LuaPacketLoggerSsh;
+ om->PacketConditionFunc = LuaPacketConditionSsh;
} else if (opts.packet && opts.alerts) {
om->PacketLogFunc = LuaPacketLoggerAlerts;
om->PacketConditionFunc = LuaPacketConditionAlerts;
}
strlcpy(pfconf->iface, iface, sizeof(pfconf->iface));
+ pfconf->flags = 0;
pfconf->threads = 1;
pfconf->cluster_id = 1;
#ifdef HAVE_PFRING
SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config");
} else {
pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ pfconf->flags |= PFRING_CONF_FLAGS_CLUSTER;
SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id);
}
/* command line value has precedence */
if (ConfGet("pfring.cluster-id", &tmpclusterid) == 1) {
pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ pfconf->flags |= PFRING_CONF_FLAGS_CLUSTER;
SCLogDebug("Going to use command-line provided cluster-id %" PRId32,
pfconf->cluster_id);
} else {
"Could not get cluster-id from config");
} else {
pfconf->cluster_id = (uint16_t)atoi(tmpclusterid);
+ pfconf->flags |= PFRING_CONF_FLAGS_CLUSTER;
SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id);
}
}
CudaBufferRegisterUnittests();
#endif
AppLayerUnittestsRegister();
+ MimeDecRegisterTests();
if (list_unittests) {
UtListTests(regex_arg);
} else {
#define LIBPFRING_REENTRANT 0
#define LIBPFRING_WAIT_FOR_INCOMING 1
+typedef enum {
+ PFRING_FLAGS_ZERO_COPY = 0x1
+} PfringThreadVarsFlags;
+
/**
* \brief Structure to hold thread specific variables.
*/
uint16_t capture_kernel_packets;
uint16_t capture_kernel_drops;
+ uint32_t flags;
+
ThreadVars *tv;
TmSlot *slot;
struct pfring_pkthdr hdr;
TmSlot *s = (TmSlot *)slot;
time_t last_dump = 0;
- struct timeval current_time;
+ u_int buffer_size;
+ u_char *pkt_buffer;
ptv->slot = s->slot_next;
/* Some flavours of PF_RING may fail to set timestamp - see PF-RING-enabled libpcap code*/
hdr.ts.tv_sec = hdr.ts.tv_usec = 0;
+ /* Check for Zero-copy mode */
+ if (ptv->flags & PFRING_FLAGS_ZERO_COPY) {
+ buffer_size = 0;
+ pkt_buffer = NULL;
+ } else {
+ buffer_size = GET_PKT_DIRECT_MAX_SIZE(p);
+ pkt_buffer = GET_PKT_DIRECT_DATA(p);
+ }
+
/* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */
- u_char *pkt_buffer = GET_PKT_DIRECT_DATA(p);
- u_int buffer_size = GET_PKT_DIRECT_MAX_SIZE(p);
int r = pfring_recv(ptv->pd, &pkt_buffer,
buffer_size,
&hdr,
LIBPFRING_WAIT_FOR_INCOMING);
- /* Check for Zero-copy if buffer size is zero */
- if (buffer_size == 0) {
+ /* Check for Zero-copy mode */
+ if (ptv->flags & PFRING_FLAGS_ZERO_COPY) {
PacketSetData(p, pkt_buffer, hdr.caplen);
}
}
/* Trigger one dump of stats every second */
- TimeGet(¤t_time);
- if (current_time.tv_sec != last_dump) {
+ if (p->ts.tv_sec != last_dump) {
PfringDumpCounters(ptv);
- last_dump = current_time.tv_sec;
+ last_dump = p->ts.tv_sec;
}
} else {
SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error %" PRId32 "", r);
u_int32_t version = 0;
PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata;
unsigned int opflag;
-
+ char const *active_runmode = RunmodeGetActive();
if (pfconf == NULL)
return TM_ECODE_FAILED;
SCReturnInt(TM_ECODE_FAILED);
}
+ /* enable zero-copy mode for workers runmode */
+ if (active_runmode && strcmp("workers", active_runmode) == 0) {
+ ptv->flags |= PFRING_FLAGS_ZERO_COPY;
+ SCLogInfo("Enabling zero-copy for %s", ptv->interface);
+ }
+
ptv->checksum_mode = pfconf->checksum_mode;
- opflag = PF_RING_REENTRANT | PF_RING_PROMISC;
+ opflag = PF_RING_PROMISC;
/* if suri uses VLAN and if we have a recent kernel, we need
* to use parsed_pkt to get VLAN info */
if (rc != 0) {
SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster "
"returned %d for cluster-id: %d", rc, ptv->cluster_id);
- pfconf->DerefFunc(pfconf);
- return TM_ECODE_FAILED;
+ if (rc != PF_RING_ERROR_NOT_SUPPORTED || (pfconf->flags & PFRING_CONF_FLAGS_CLUSTER)) {
+ /* cluster is mandatory as explicitly specified in the configuration */
+ pfconf->DerefFunc(pfconf);
+ return TM_ECODE_FAILED;
+ }
}
}
#include <pfring.h>
#endif
+typedef enum {
+ PFRING_CONF_FLAGS_CLUSTER = 0x1
+} PfringIfaceConfigFlags;
+
typedef struct PfringIfaceConfig_
{
+ uint32_t flags;
+
/* cluster param */
int cluster_id;
#ifdef HAVE_PFRING
TcpSession *ssn, TcpStream *stream, TcpSegment *seg, ReassembleData *rd,
Packet *p)
{
- /* fast path 1: segment is exactly what we need */
- if (likely(rd->data_len == 0 &&
- SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
- SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len))))
- {
- /* process single segment directly */
- AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
- seg->payload, seg->payload_len,
- StreamGetAppLayerFlags(ssn, stream, p));
- AppLayerProfilingStore(ra_ctx->app_tctx, p);
- rd->data_sent += seg->payload_len;
- rd->ra_base_seq += seg->payload_len;
+ /* fast paths: send data directly into the app layer, w/o first doing
+ * a copy step. However, don't use the fast path until protocol detection
+ * has been completed
+ * TODO if initial data is big enough for proto detect, we could do the
+ * fast path anyway. */
+ if (stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) {
+ /* fast path 1: segment is exactly what we need */
+ if (likely(rd->data_len == 0 &&
+ SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
+ SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len))))
+ {
+ /* process single segment directly */
+ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
+ seg->payload, seg->payload_len,
+ StreamGetAppLayerFlags(ssn, stream, p));
+ AppLayerProfilingStore(ra_ctx->app_tctx, p);
+ rd->data_sent += seg->payload_len;
+ rd->ra_base_seq += seg->payload_len;
#ifdef DEBUG
- ra_ctx->fp1++;
+ ra_ctx->fp1++;
#endif
- /* if after the first data chunk we have no alproto yet,
- * there is no point in continueing here. */
- if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
- SCLogDebug("no alproto after first data chunk");
- return 0;
- }
- return 1;
- /* fast path 2: segment acked completely, meets minimal size req for 0copy processing */
- } else if (rd->data_len == 0 &&
- SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
- SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) &&
- seg->payload_len >= stream_config.zero_copy_size)
- {
- /* process single segment directly */
- AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
- seg->payload, seg->payload_len,
- StreamGetAppLayerFlags(ssn, stream, p));
- AppLayerProfilingStore(ra_ctx->app_tctx, p);
- rd->data_sent += seg->payload_len;
- rd->ra_base_seq += seg->payload_len;
+ /* if after the first data chunk we have no alproto yet,
+ * there is no point in continueing here. */
+ if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
+ SCLogDebug("no alproto after first data chunk");
+ return 0;
+ }
+ return 1;
+ /* fast path 2: segment acked completely, meets minimal size req for 0copy processing */
+ } else if (rd->data_len == 0 &&
+ SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
+ SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) &&
+ seg->payload_len >= stream_config.zero_copy_size)
+ {
+ /* process single segment directly */
+ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
+ seg->payload, seg->payload_len,
+ StreamGetAppLayerFlags(ssn, stream, p));
+ AppLayerProfilingStore(ra_ctx->app_tctx, p);
+ rd->data_sent += seg->payload_len;
+ rd->ra_base_seq += seg->payload_len;
#ifdef DEBUG
- ra_ctx->fp2++;
+ ra_ctx->fp2++;
#endif
- /* if after the first data chunk we have no alproto yet,
- * there is no point in continueing here. */
- if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
- SCLogDebug("no alproto after first data chunk");
- return 0;
+ /* if after the first data chunk we have no alproto yet,
+ * there is no point in continueing here. */
+ if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
+ SCLogDebug("no alproto after first data chunk");
+ return 0;
+ }
+ return 1;
}
- return 1;
}
#ifdef DEBUG
ra_ctx->sp++;
GetSessionSize(ssn, p);
#endif
+ /* Check if we have a gap at the start of the stream. 2 conditions:
+ * 1. no segments, but last_ack moved fwd
+ * 2. segments, but clearly some missing: if last_ack is
+ * bigger than the list start and the list start is bigger than
+ * next_seq, we know we are missing data that has been ack'd. That
+ * won't get retransmitted, so it's a data gap.
+ */
+ if (!(ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED)) {
+ int ackadd = (ssn->state >= TCP_FIN_WAIT2) ? 2 : 1;
+ if ((stream->seg_list == NULL && /*1*/
+ stream->ra_app_base_seq == stream->isn &&
+ SEQ_GT(stream->last_ack, stream->isn + ackadd))
+ ||
+ (stream->seg_list != NULL && /*2*/
+ SEQ_GT(stream->seg_list->seq, stream->ra_app_base_seq+1) &&
+ SEQ_LT(stream->seg_list->seq, stream->last_ack)))
+ {
+ if (stream->seg_list == NULL) {
+ SCLogDebug("no segs, last_ack moved fwd so GAP "
+ "(base %u, isn %u, last_ack %u => diff %u) p %"PRIu64,
+ stream->ra_app_base_seq, stream->isn, stream->last_ack,
+ stream->last_ack - (stream->isn + ackadd), p->pcap_cnt);
+ }
+
+ /* send gap signal */
+ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
+ NULL, 0,
+ StreamGetAppLayerFlags(ssn, stream, p)|STREAM_GAP);
+ AppLayerProfilingStore(ra_ctx->app_tctx, p);
+
+ /* set a GAP flag and make sure not bothering this stream anymore */
+ SCLogDebug("STREAMTCP_STREAM_FLAG_GAP set");
+ stream->flags |= STREAMTCP_STREAM_FLAG_GAP;
+
+ StreamTcpSetEvent(p, STREAM_REASSEMBLY_SEQ_GAP);
+ StatsIncr(tv, ra_ctx->counter_tcp_reass_gap);
+#ifdef DEBUG
+ dbg_app_layer_gap++;
+#endif
+ SCReturnInt(0);
+ }
+ }
+
/* if no segments are in the list or all are already processed,
* and state is beyond established, we send an empty msg */
TcpSegment *seg_tail = stream->seg_list_tail;
/* loop through the segments and fill one or more msgs */
TcpSegment *seg = stream->seg_list;
SCLogDebug("pre-loop seg %p", seg);
-
- /* Check if we have a gap at the start of the list. If last_ack is
- * bigger than the list start and the list start is bigger than
- * next_seq, we know we are missing data that has been ack'd. That
- * won't get retransmitted, so it's a data gap.
- */
- if (!(ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED)) {
- if (SEQ_GT(seg->seq, next_seq) && SEQ_LT(seg->seq, stream->last_ack)) {
- /* send gap signal */
- AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
- NULL, 0,
- StreamGetAppLayerFlags(ssn, stream, p)|STREAM_GAP);
- AppLayerProfilingStore(ra_ctx->app_tctx, p);
-
- /* set a GAP flag and make sure not bothering this stream anymore */
- SCLogDebug("STREAMTCP_STREAM_FLAG_GAP set");
- stream->flags |= STREAMTCP_STREAM_FLAG_GAP;
-
- StreamTcpSetEvent(p, STREAM_REASSEMBLY_SEQ_GAP);
- StatsIncr(tv, ra_ctx->counter_tcp_reass_gap);
-#ifdef DEBUG
- dbg_app_layer_gap++;
+#ifdef DEBUG_VALIDATION
+ uint64_t bytes = 0;
#endif
- SCReturnInt(0);
- }
- }
-
for (; seg != NULL; )
{
+#ifdef DEBUG_VALIDATION
+ bytes += seg->payload_len;
+#endif
/* if in inline mode, we process all segments regardless of whether
* they are ack'd or not. In non-inline, we process only those that
* are at least partly ack'd. */
}
seg = next_seg;
}
+#ifdef DEBUG_VALIDATION /* we should never have this much data queued */
+ BUG_ON(bytes > 1000000ULL && bytes > (stream->window * 1.5));
+#endif
/* put the partly filled smsg in the queue to the l7 handler */
if (rd.data_len > 0) {
} else {
TcpSegment *tmp_seg = stream->seg_list;
while (tmp_seg != NULL) {
+ if (!(tmp_seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED))
+ break;
tmp_seg->flags &= ~SEGMENTTCP_FLAG_APPLAYER_PROCESSED;
tmp_seg = tmp_seg->next;
}
th_flag = TH_ACK|TH_PUSH;
th_flags = TH_ACK;
+ ssn.client.last_ack = 2;
+ ssn.client.isn = 1;
+
ssn.server.last_ack = 22;
ssn.server.ra_raw_base_seq = ssn.server.ra_app_base_seq = 9;
ssn.server.isn = 9;
ssn.server.last_ack = 60;
ssn.client.ra_raw_base_seq = ssn.client.ra_app_base_seq = 9;
ssn.client.isn = 9;
- ssn.client.last_ack = 60;
+ ssn.client.last_ack = 9;
f.alproto = ALPROTO_UNKNOWN;
f.flags |= FLOW_IPV4;
ssn.server.last_ack = 60;
STREAMTCP_SET_RA_BASE_SEQ(&ssn.client, 9);
ssn.client.isn = 9;
- ssn.client.last_ack = 60;
+ ssn.client.last_ack = 9;
f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
if (f == NULL)
ssn.server.next_seq = ssn.server.isn;
STREAMTCP_SET_RA_BASE_SEQ(&ssn.client, 9);
ssn.client.isn = 9;
- ssn.client.last_ack = 60;
+ ssn.client.last_ack = 9;
ssn.client.next_seq = ssn.client.isn;
f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
StreamTcpUTInitInline();
StreamTcpUTSetupSession(&ssn);
StreamTcpUTSetupStream(&ssn.server, 1);
+ ssn.server.last_ack = 2;
+ StreamTcpUTSetupStream(&ssn.client, 1);
+ ssn.client.last_ack = 2;
f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
if (f == NULL)
#define StreamTcpUpdateLastAck(ssn, stream, ack) { \
if (SEQ_GT((ack), (stream)->last_ack)) \
{ \
+ SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
+ if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
+ SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
+ } else { \
+ SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
+ }\
(stream)->last_ack = (ack); \
- SCLogDebug("ssn %p: last_ack set to %"PRIu32, (ssn), (stream)->last_ack); \
StreamTcpSackPruneList((stream)); \
} else { \
SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
if (p->payload_len == 0)
SCReturnInt(0);
+ /* retransmission of already partially ack'd data */
+ if (SEQ_LT(TCP_GET_SEQ(p), stream->last_ack) && SEQ_GT((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack))
+ {
+ StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
+ SCReturnInt(1);
+ }
+
/* retransmission of already ack'd data */
if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack)) {
StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION);
SCReturnInt(2);
}
- SCLogDebug("seq %u payload_len %u => %u, last_ack %u", TCP_GET_SEQ(p),
- p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack);
+ SCLogDebug("seq %u payload_len %u => %u, last_ack %u, next_seq %u", TCP_GET_SEQ(p),
+ p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack, stream->next_seq);
SCReturnInt(0);
}
SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
" (started before next_seq, ended after)",
ssn, ssn->client.next_seq);
+ /* if next_seq has fallen behind last_ack, we got some catching up to do */
+ } else if (SEQ_LT(ssn->client.next_seq, ssn->client.last_ack)) {
+ ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32
+ " (next_seq had fallen behind last_ack)",
+ ssn, ssn->client.next_seq);
+ } else {
+ SCLogDebug("ssn %p: no update to ssn->client.next_seq %"PRIu32
+ " SEQ %u SEQ+ %u last_ack %u",
+ ssn, ssn->client.next_seq,
+ TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->client.last_ack);
}
/* in window check */
SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32
" (started before next_seq, ended after)",
ssn, ssn->server.next_seq);
+ /* if next_seq has fallen behind last_ack, we got some catching up to do */
+ } else if (SEQ_LT(ssn->server.next_seq, ssn->server.last_ack)) {
+ ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
+ SCLogDebug("ssn %p: ssn->server.next_seq %"PRIu32
+ " (next_seq had fallen behind last_ack)",
+ ssn, ssn->server.next_seq);
+ } else {
+ SCLogDebug("ssn %p: no update to ssn->server.next_seq %"PRIu32
+ " SEQ %u SEQ+ %u last_ack %u",
+ ssn, ssn->server.next_seq,
+ TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->server.last_ack);
}
if (zerowindowprobe) {
ssn->server.next_seq);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
ssn->server.next_seq);
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
ssn);
if (PKT_IS_TOSERVER(p)) {
- StreamTcpUpdateLastAck(ssn, &ssn->server,
- StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->server,
+ StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->client,
StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p)));
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
} else {
- StreamTcpUpdateLastAck(ssn, &ssn->client,
- StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
+ if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0)
+ StreamTcpUpdateLastAck(ssn, &ssn->client,
+ StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p)));
StreamTcpUpdateLastAck(ssn, &ssn->server,
StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p)));
* back on a sane default. */
char *temp_default_packet_size;
if ((ConfGet("default-packet-size", &temp_default_packet_size)) != 1) {
+ int lthread;
+ int nlive;
switch (suri->run_mode) {
case RUNMODE_PCAP_DEV:
case RUNMODE_AFP_DEV:
case RUNMODE_NETMAP:
case RUNMODE_PFRING:
- /* FIXME this don't work effficiently in multiinterface */
- /* find payload for interface and use it */
- default_packet_size = GetIfaceMaxPacketSize(suri->pcap_dev);
+ nlive = LiveGetDeviceCount();
+ for (lthread = 0; lthread < nlive; lthread++) {
+ char *live_dev = LiveGetDeviceName(lthread);
+ unsigned int iface_max_packet_size = GetIfaceMaxPacketSize(live_dev);
+ if (iface_max_packet_size > default_packet_size)
+ default_packet_size = iface_max_packet_size;
+ }
if (default_packet_size)
break;
/* fall through */
exit(EXIT_FAILURE);
}
+ if (suri.run_mode == RUNMODE_DUMP_CONFIG) {
+ ConfDump();
+ exit(EXIT_SUCCESS);
+ }
+
/* Since our config is now loaded we can finish configurating the
* logging module. */
SCLogLoadConfig(suri.daemon, suri.verbose);
UtilCpuPrintSummary();
- if (suri.run_mode == RUNMODE_DUMP_CONFIG) {
- ConfDump();
- exit(EXIT_SUCCESS);
+ if (ParseInterfacesList(suri.run_mode, suri.pcap_dev) != TM_ECODE_OK) {
+ exit(EXIT_FAILURE);
}
if (PostConfLoadedSetup(&suri) != TM_ECODE_OK) {
StatsSetupPostConfig();
}
- if (ParseInterfacesList(suri.run_mode, suri.pcap_dev) != TM_ECODE_OK) {
- exit(EXIT_FAILURE);
- }
-
if(suri.run_mode == RUNMODE_CONF_TEST){
SCLogNotice("Configuration provided was successfully loaded. Exiting.");
exit(EXIT_SUCCESS);
}
(void) SC_ATOMIC_CAS(&engine_stage, SURICATA_INIT, SURICATA_RUNTIME);
+ PacketPoolPostRunmodes();
/* Un-pause all the paused threads */
TmThreadContinueThreads();
if (suri.delayed_detect) {
/* force 'reload', this will load the rules and swap engines */
- DetectEngineReload(NULL);
+ DetectEngineReload(NULL, &suri);
if (suri.sig_file != NULL)
UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2SigFileStartup);
}
if (sigusr2_count > 0) {
- DetectEngineReload(conf_filename);
+ DetectEngineReload(conf_filename, &suri);
sigusr2_count--;
} else if (DetectEngineReloadIsStart()) {
- DetectEngineReload(conf_filename);
+ DetectEngineReload(conf_filename, &suri);
DetectEngineReloadSetDone();
}
/** no of times the thread has been restarted on failure */
uint8_t restarted;
+ /** TmModule::flags for each module part of this thread */
+ uint8_t tmm_flags;
+
/** local id */
int id;
* received a TM as arg, if it didn't exist */
slot->tm_id = TmModuleGetIDForTM(tm);
+ tv->tmm_flags |= tm->flags;
tv->cap_flags |= tm->cap_flags;
if (tv->tm_slots == NULL) {
return NULL;
}
+/**
+ * \brief returns a count of all the threads that match the flag
+ */
+uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
+{
+ ThreadVars *tv = NULL;
+ int i = 0;
+ uint32_t cnt = 0;
+
+ SCMutexLock(&tv_root_lock);
+ for (i = 0; i < TVT_MAX; i++) {
+ tv = tv_root[i];
+ while (tv != NULL) {
+ if ((tv->tmm_flags & flags) == flags)
+ cnt++;
+
+ tv = tv->next;
+ }
+ }
+ SCMutexUnlock(&tv_root_lock);
+ return cnt;
+}
+
typedef struct Thread_ {
ThreadVars *tv; /**< threadvars structure */
const char *name;
void TmThreadDisableReceiveThreads(void);
TmSlot *TmThreadGetFirstTmSlotForPartialPattern(const char *);
+uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags);
+
/**
* \brief Process the rest of the functions (if any) and queue.
*/
#include "stream-tcp-reassemble.h"
#include "tm-queuehandlers.h"
+#include "tm-threads.h"
+#include "tm-modules.h"
#include "pkt-var.h"
/* Number of freed packet to save for one pool before freeing them. */
#define MAX_PENDING_RETURN_PACKETS 32
+static uint32_t max_pending_return_packets = MAX_PENDING_RETURN_PACKETS;
#ifdef TLS
__thread PktPool thread_pkt_pool;
p->next = my_pool->pending_head;
my_pool->pending_head = p;
my_pool->pending_count++;
- if (SC_ATOMIC_GET(pool->return_stack.sync_now) || my_pool->pending_count > MAX_PENDING_RETURN_PACKETS) {
+ if (SC_ATOMIC_GET(pool->return_stack.sync_now) || my_pool->pending_count > max_pending_return_packets) {
/* Return the entire list of pending packets. */
SCMutexLock(&pool->return_stack.mutex);
my_pool->pending_tail->next = pool->return_stack.head;
return;
}
+
+/**
+ * \brief Set the max_pending_return_packets value
+ *
+ * Set it to the max pending packets value, devided by the number
+ * of lister threads. Normally, in autofp these are the stream/detect/log
+ * worker threads.
+ *
+ * The max_pending_return_packets value needs to stay below the packet
+ * pool size of the 'producers' (normally pkt capture threads but also
+ * flow timeout injection ) to avoid a deadlock where all the 'workers'
+ * keep packets in their return pools, while the capture thread can't
+ * continue because its pool is empty.
+ */
+void PacketPoolPostRunmodes(void)
+{
+ extern intmax_t max_pending_packets;
+
+ uint32_t threads = TmThreadCountThreadsByTmmFlags(TM_FLAG_DETECT_TM);
+ if (threads == 0)
+ return;
+ if (threads > max_pending_packets)
+ return;
+
+ uint32_t packets = (max_pending_packets / threads) - 1;
+ if (packets < max_pending_return_packets)
+ max_pending_return_packets = packets;
+
+ SCLogDebug("detect threads %u, max packets %u, max_pending_return_packets %u",
+ threads, (uint)threads, max_pending_return_packets);
+}
void PacketPoolInit(void);
void PacketPoolInitEmpty(void);
void PacketPoolDestroy(void);
+void PacketPoolPostRunmodes(void);
#endif /* __TMQH_PACKETPOOL_H__ */
json_decref(server_msg);
/* client connected */
- SCLogInfo("Unix socket: client connected");
+ SCLogDebug("Unix socket: client connected");
uclient = SCMalloc(sizeof(UnixClient));
if (unlikely(uclient == NULL)) {
ret = recv(client->fd, buffer, sizeof(buffer) - 1, 0);
if (ret <= 0) {
if (ret == 0) {
- SCLogInfo("Unix socket: lost connection with client");
+ SCLogDebug("Unix socket: lost connection with client");
} else {
- SCLogInfo("Unix socket: error on recv() from client: %s",
+ SCLogError(SC_ERR_SOCKET, "Unix socket: error on recv() from client: %s",
strerror(errno));
}
UnixCommandClose(this, client->fd);
if (errno == EINTR) {
return 1;
}
- SCLogInfo("Command server: select() fatal error: %s", strerror(errno));
+ SCLogError(SC_ERR_SOCKET, "Command server: select() fatal error: %s", strerror(errno));
return 0;
}
}
iface_ctx->log_level = tmp_log_level;
- if (isatty(fileno(stdout))) {
+ if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
iface_ctx->use_color = TRUE;
}
#define MAX_IP6_CHARS 39
/* Globally hold configuration data */
-static MimeDecConfig mime_dec_config = { 1, 1, 1, MAX_HEADER_VALUE };
+static MimeDecConfig mime_dec_config = { 1, 1, 1, 0, MAX_HEADER_VALUE };
-#ifdef DEBUG
/* Mime Parser String translation */
static const char *StateFlags[] = { "NONE",
"HEADER_READY",
"PARSE_DONE",
"PARSE_ERROR",
NULL };
-#endif
/* URL executable file extensions */
static const char *UrlExeExts[] = { ".exe",
return node;
}
+
+/**
+ * \brief Searches for header fields with the specified name
+ *
+ * \param entity The entity to search
+ * \param name The header name (lowercase)
+ *
+ * \return number of items found
+ *
+ */
+int MimeDecFindFieldsForEach(const MimeDecEntity *entity, const char *name, int (*DataCallback)(const uint8_t *val, const size_t, void *data), void *data)
+{
+ MimeDecField *curr = entity->field_list;
+ int found = 0;
+
+ while (curr != NULL) {
+ /* name is stored lowercase */
+ if (strlen(name) == curr->name_len) {
+ if (SCMemcmp(curr->name, name, curr->name_len) == 0) {
+ if (DataCallback(curr->value, curr->value_len, data))
+ found++;
+ }
+ }
+ curr = curr->next;
+ }
+
+ return found;
+}
+
/**
* \brief Searches for a header field with the specified name
*
*/
static int IsIpv6Host(const uint8_t *urlhost, uint32_t len)
{
- struct sockaddr_in sa;
+ struct in6_addr in6;
char tempIp[MAX_IP6_CHARS + 1];
/* Cut off at '/' */
memcpy(tempIp, urlhost, i);
tempIp[i] = '\0';
- return inet_pton(AF_INET6, tempIp, &(sa.sin_addr));
+ return inet_pton(AF_INET6, tempIp, &in6);
}
/**
*
* \return MIME_DEC_OK on success, otherwise < 0 on failure
*/
+
static int ProcessBodyComplete(MimeDecParseState *state)
{
int ret = MIME_DEC_OK;
}
}
+#ifdef HAVE_NSS
+ if (state->md5_ctx) {
+ unsigned int len = 0;
+ HASH_End(state->md5_ctx, state->md5, &len, sizeof(state->md5));
+ }
+#endif
+
/* Invoke pre-processor and callback with remaining data */
ret = ProcessDecodedDataChunk(state->data_chunk, state->data_chunk_len, state);
if (ret != MIME_DEC_OK) {
int body_found = 0;
uint32_t tlen;
+#ifdef HAVE_NSS
+ if (MimeDecGetConfig()->body_md5) {
+ if (state->body_begin == 1) {
+ if (state->md5_ctx == NULL) {
+ state->md5_ctx = HASH_Create(HASH_AlgMD5);
+ HASH_Begin(state->md5_ctx);
+ }
+ }
+ HASH_Update(state->md5_ctx, buf, len + state->current_line_delimiter_len);
+ }
+#endif
+
/* Ignore empty lines */
if (len == 0) {
return ret;
return ret;
}
+const char *MimeDecParseStateGetStatus(MimeDecParseState *state)
+{
+ return StateFlags[state->state_flag];
+}
+
/**
* \brief Processes the MIME Entity based on the input line and current state of
* the parser
SCFree(state->hname);
FreeDataValue(state->hvalue);
FreeMimeDecStack(state->stack);
+#ifdef HAVE_NSS
+ if (state->md5_ctx)
+ HASH_Destroy(state->md5_ctx);
+#endif
SCFree(state);
}
*
* \param line A string representing the line (w/out CRLF)
* \param len The length of the line
+ * \param delim_len The length of the line end delimiter
* \param state The parser state
*
* \return MIME_DEC_OK on success, otherwise < 0 on failure
*/
int MimeDecParseLine(const uint8_t *line, const uint32_t len,
- MimeDecParseState *state)
+ const uint8_t delim_len, MimeDecParseState *state)
{
int ret = MIME_DEC_OK;
SCLogDebug("SMTP LINE - EMPTY");
}
+ state->current_line_delimiter_len = delim_len;
/* Process the entity */
ret = ProcessMimeEntity(line, len, state);
if (ret != MIME_DEC_OK) {
line = tok;
+ state->current_line_delimiter_len = (remainPtr - tok) - tokLen;
/* Parse the line */
- ret = MimeDecParseLine(line, tokLen, state);
+ ret = MimeDecParseLine(line, tokLen,
+ (remainPtr - tok) - tokLen, state);
if (ret != MIME_DEC_OK) {
SCLogDebug("Error: MimeDecParseLine() function failed: %d",
ret);
TestDataChunkCallback);
char *str = "From: Sender1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "To: Recipient1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "Content-Type: text/plain";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 2";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 3";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
if (ret != MIME_DEC_OK) {
return ret;
TestDataChunkCallback);
char *str = "From: Sender1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "To: Recipient1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "Content-Type: text/plain";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 1";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 2 click on http://www.test.com/malware.exe?"
"hahah hopefully you click this link";
- ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state);
+ ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
if (ret != MIME_DEC_OK) {
return ret;
return ret;
}
+/* Test full message with linebreaks */
+static int MimeDecParseFullMsgTest02(void)
+{
+ int ret = MIME_DEC_OK;
+
+ uint32_t expected_count = 3;
+ uint32_t line_count = 0;
+
+ char msg[] = "From: Sender2\r\n"
+ "To: Recipient2\r\n"
+ "Subject: subject2\r\n"
+ "Content-Type: text/plain\r\n"
+ "\r\n"
+ "Line 1\r\n"
+ "Line 2\r\n"
+ "Line 3\r\n";
+
+ MimeDecEntity *entity = MimeDecParseFullMsg((uint8_t *)msg, strlen(msg), &line_count,
+ TestDataChunkCallback);
+
+ if (entity == NULL) {
+ SCLogInfo("Warning: Message failed to parse");
+ return -1;
+ }
+
+ MimeDecField *field = MimeDecFindField(entity, "subject");
+ if (field == NULL) {
+ SCLogInfo("Warning: Message failed to parse");
+ return -1;
+ }
+
+ if (field->value_len != sizeof("subject2") - 1) {
+ SCLogInfo("Warning: failed to get subject");
+ return -1;
+ }
+
+ if (memcmp(field->value, "subject2", field->value_len) != 0) {
+ SCLogInfo("Warning: failed to get subject");
+ return -1;
+ }
+
+
+ MimeDecFreeEntity(entity);
+
+ if (expected_count != line_count) {
+ SCLogInfo("Warning: Line count is invalid: expected - %d actual - %d",
+ expected_count, line_count);
+ return -1;
+ }
+
+ return ret;
+}
+
static int MimeBase64DecodeTest01(void)
{
int ret = -1;
char *base64msg = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QU"
"VJTVFVWV1hZWjEyMzQ1Njc4OTBAIyQlXiYqKCktPV8rLC4vOydbXTw+Pzo=";
- uint8_t *dst = SCMalloc(strlen(msg)-1);
+ uint8_t *dst = SCMalloc(strlen(msg) + 1);
if (dst == NULL)
return 0;
ret = 0;
}
+ SCFree(dst);
+
return ret;
}
UtRegisterTest("MimeDecParseLineTest01", MimeDecParseLineTest01, 0);
UtRegisterTest("MimeDecParseLineTest02", MimeDecParseLineTest02, 0);
UtRegisterTest("MimeDecParseFullMsgTest01", MimeDecParseFullMsgTest01, 0);
+ UtRegisterTest("MimeDecParseFullMsgTest02", MimeDecParseFullMsgTest02, 0);
UtRegisterTest("MimeBase64DecodeTest01", MimeBase64DecodeTest01, 0);
UtRegisterTest("MimeIsExeURLTest01", MimeIsExeURLTest01, 0);
UtRegisterTest("MimeIsIpv4HostTest01", MimeIsIpv4HostTest01, 0);
#include "util-base64.h"
#include "util-debug.h"
-/* Header Flags */
-#define HDR_IS_LOGGED 1
-
/* Content Flags */
#define CTNT_IS_MSG 1
#define CTNT_IS_ENV 2
#define ANOM_MALFORMED_MSG 64 /* Misc msg format errors found */
#define ANOM_LONG_BOUNDARY 128 /* Boundary too long */
-/* Pubicly exposed size constants */
+/* Publicly exposed size constants */
#define DATA_CHUNK_SIZE 3072 /* Should be divisible by 3 */
#define LINEREM_SIZE 256
int decode_base64; /**< Decode base64 bodies */
int decode_quoted_printable; /**< Decode quoted-printable bodies */
int extract_urls; /**< Extract and store URLs in data structure */
+ int body_md5; /**< Compute md5 sum of body */
uint32_t header_value_depth; /**< Depth of which to store header values
(Default is 2000) */
} MimeDecConfig;
uint8_t bvremain[B64_BLOCK]; /**< Remainder from base64-decoded line */
uint8_t bvr_len; /**< Length of remainder from base64-decoded line */
uint8_t data_chunk[DATA_CHUNK_SIZE]; /**< Buffer holding data chunk */
+#ifdef HAVE_NSS
+ HASHContext *md5_ctx;
+ uint8_t md5[MD5_LENGTH];
+#endif
uint8_t state_flag; /**< Flag representing current state of parser */
uint32_t data_chunk_len; /**< Length of data chunk */
int found_child; /**< Flag indicating a child entity was found */
int body_begin; /**< Currently at beginning of body */
int body_end; /**< Currently at end of body */
+ uint8_t current_line_delimiter_len; /**< Length of line delimiter */
void *data; /**< Pointer to data specific to the caller */
int (*DataChunkProcessorFunc) (const uint8_t *chunk, uint32_t len,
struct MimeDecParseState *state); /**< Data chunk processing function callback */
/* List functions */
MimeDecField * MimeDecAddField(MimeDecEntity *entity);
MimeDecField * MimeDecFindField(const MimeDecEntity *entity, const char *name);
+int MimeDecFindFieldsForEach(const MimeDecEntity *entity, const char *name, int (*DataCallback)(const uint8_t *val, const size_t, void *data), void *data);
MimeDecEntity * MimeDecAddEntity(MimeDecEntity *parent);
/* Helper functions */
uint32_t len, MimeDecParseState *state));
void MimeDecDeInitParser(MimeDecParseState *state);
int MimeDecParseComplete(MimeDecParseState *state);
-int MimeDecParseLine(const uint8_t *line, const uint32_t len, MimeDecParseState *state);
+int MimeDecParseLine(const uint8_t *line, const uint32_t len, const uint8_t delim_len, MimeDecParseState *state);
MimeDecEntity * MimeDecParseFullMsg(const uint8_t *buf, uint32_t blen, void *data,
int (*DataChunkProcessorFunc)(const uint8_t *chunk, uint32_t len, MimeDecParseState *state));
+const char *MimeDecParseStateGetStatus(MimeDecParseState *state);
/* Test functions */
void MimeDecRegisterTests(void);
CASE_CODE (SC_ERR_IPPAIR_INIT);
CASE_CODE (SC_ERR_MT_NO_SELECTOR);
CASE_CODE (SC_ERR_MT_DUPLICATE_TENANT);
+ CASE_CODE (SC_ERR_NO_JSON_SUPPORT);
}
return "UNKNOWN_ERROR";
SC_ERR_IPPAIR_INIT,
SC_ERR_MT_NO_SELECTOR,
SC_ERR_MT_DUPLICATE_TENANT,
+ SC_ERR_NO_JSON_SUPPORT,
} SCError;
const char *SCErrorToString(SCError);
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux", "192.168.1.566", SC_HINFO_IS_IPV4) != -1) {
goto end;
}
- if (SCHInfoAddHostOSInfo("linux", "192.168.1", SC_HINFO_IS_IPV4 != -1)) {
+ if (SCHInfoAddHostOSInfo("linux", "192.168.1", SC_HINFO_IS_IPV4) != -1) {
goto end;
}
if (SCHInfoAddHostOSInfo("linux", "192.", SC_HINFO_IS_IPV4) != -1) {
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux", "2362:7322", SC_HINFO_IS_IPV6) != -1) {
goto end;
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux", "192.168.1.1", SC_HINFO_IS_IPV4) == -1) {
goto end;
SCHInfoCreateContextBackup();
struct in_addr in;
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux", "192.168.1.1", SC_HINFO_IS_IPV4) == -1) {
goto end;
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux",
"2351:2512:6211:6246:235A:6242:2352:62AD",
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux",
"2351:2512:6211:6246:235A:6242:2352:62AD",
SCHInfoCreateContextBackup();
struct in6_addr in6;
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux",
"2351:2512:6211:6246:235A:6242:2352:62AD",
{
SCHInfoCreateContextBackup();
- int result = 1;
+ int result = 0;
if (SCHInfoAddHostOSInfo("linux", "192.168.1.0", SC_HINFO_IS_IPV4) == -1) {
- goto end;
+ goto end;
}
if (SCHInfoAddHostOSInfo("windows", "192.192.1.2", SC_HINFO_IS_IPV4) == -1) {
goto end;
goto end;
}
- if (SCHInfoGetHostOSFlavour("192.168.1.100") ==
+ /* 192.168.1.100 should match "macos" as its more specific than
+ * "solaris". */
+ if (SCHInfoGetHostOSFlavour("192.168.1.100") !=
SCMapEnumNameToValue("macos", sc_hinfo_os_policy_map)) {
goto end;
}
+ /* Remove the 192.168.1.0/20 -> macos entry. */
bzero(&servaddr, sizeof(servaddr));
if (inet_pton(AF_INET, "192.168.0.0", &servaddr.sin_addr) <= 0) {
goto end;
}
SCRadixRemoveKeyIPV4Netblock((uint8_t *)&servaddr.sin_addr, sc_hinfo_tree, 20);
- if (SCHInfoGetHostOSFlavour("192.168.1.100") ==
+ if (SCHInfoGetHostOSFlavour("192.168.1.100") !=
SCMapEnumNameToValue("solaris", sc_hinfo_os_policy_map)) {
goto end;
}
+ /* Remove the 192.168.1.0/16 -> solaris entry. */
bzero(&servaddr, sizeof(servaddr));
if (inet_pton(AF_INET, "192.168.0.0", &servaddr.sin_addr) <= 0) {
goto end;
vista: [0.0.0.5]\n\
\n";
- int result = 1;
+ int result = 0;
SCHInfoCreateContextBackup();
vista: [0.0.0.5]\n\
\n";
- int result = 1;
+ int result = 0;
SCHInfoCreateContextBackup();
#include "util-logopenfile.h"
#include "util-logopenfile-tile.h"
+const char * redis_push_cmd = "LPUSH";
+const char * redis_publish_cmd = "PUBLISH";
+
/** \brief connect to the indicated local stream socket, logging any errors
* \param path filesystem path to connect to
* \param log_err, non-zero if connect failure should be logged.
return 0;
}
+
+#ifdef HAVE_LIBHIREDIS
+
+static void SCLogFileCloseRedis(LogFileCtx *log_ctx)
+{
+ if (log_ctx->redis) {
+ redisReply *reply;
+ int i;
+ for (i = 0; i < log_ctx->redis_setup.batch_count; i++) {
+ redisGetReply(log_ctx->redis, (void **)&reply);
+ if (reply)
+ freeReplyObject(reply);
+ }
+ redisFree(log_ctx->redis);
+ log_ctx->redis = NULL;
+ }
+ log_ctx->redis_setup.tried = 0;
+ log_ctx->redis_setup.batch_count = 0;
+}
+
+int SCConfLogOpenRedis(ConfNode *redis_node, LogFileCtx *log_ctx)
+{
+ const char *redis_server = NULL;
+ const char *redis_port = NULL;
+ const char *redis_mode = NULL;
+ const char *redis_key = NULL;
+
+ if (redis_node) {
+ redis_server = ConfNodeLookupChildValue(redis_node, "server");
+ redis_port = ConfNodeLookupChildValue(redis_node, "port");
+ redis_mode = ConfNodeLookupChildValue(redis_node, "mode");
+ redis_key = ConfNodeLookupChildValue(redis_node, "key");
+ }
+ if (!redis_server) {
+ redis_server = "127.0.0.1";
+ SCLogInfo("Using default redis server (127.0.0.1)");
+ }
+ if (!redis_port)
+ redis_port = "6379";
+ if (!redis_mode)
+ redis_mode = "list";
+ if (!redis_key)
+ redis_key = "suricata";
+ log_ctx->redis_setup.key = SCStrdup(redis_key);
+
+ if (!log_ctx->redis_setup.key) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key name");
+ exit(EXIT_FAILURE);
+ }
+
+ log_ctx->redis_setup.batch_size = 0;
+
+ ConfNode *pipelining = ConfNodeLookupChild(redis_node, "pipelining");
+ if (pipelining) {
+ int enabled = 0;
+ int ret;
+ intmax_t val;
+ ret = ConfGetChildValueBool(pipelining, "enabled", &enabled);
+ if (ret && enabled) {
+ ret = ConfGetChildValueInt(pipelining, "batch-size", &val);
+ if (ret) {
+ log_ctx->redis_setup.batch_size = val;
+ } else {
+ log_ctx->redis_setup.batch_size = 10;
+ }
+ }
+ }
+
+ if (!strcmp(redis_mode, "list")) {
+ log_ctx->redis_setup.command = redis_push_cmd;
+ if (!log_ctx->redis_setup.command) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command");
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ log_ctx->redis_setup.command = redis_publish_cmd;
+ if (!log_ctx->redis_setup.command) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command");
+ exit(EXIT_FAILURE);
+ }
+ }
+ redisContext *c = redisConnect(redis_server, atoi(redis_port));
+ if (c != NULL && c->err) {
+ SCLogError(SC_ERR_SOCKET, "Error connecting to redis server: %s", c->errstr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* store server params for reconnection */
+ log_ctx->redis_setup.server = SCStrdup(redis_server);
+ if (!log_ctx->redis_setup.server) {
+ SCLogError(SC_ERR_MEM_ALLOC, "Error allocating redis server string");
+ exit(EXIT_FAILURE);
+ }
+ log_ctx->redis_setup.port = atoi(redis_port);
+ log_ctx->redis_setup.tried = 0;
+
+ log_ctx->redis = c;
+
+ log_ctx->Close = SCLogFileCloseRedis;
+
+ return 0;
+}
+
+int SCConfLogReopenRedis(LogFileCtx *log_ctx)
+{
+ if (log_ctx->redis != NULL) {
+ redisFree(log_ctx->redis);
+ log_ctx->redis = NULL;
+ }
+
+ /* only try to reconnect once per second */
+ if (log_ctx->redis_setup.tried >= time(NULL)) {
+ return -1;
+ }
+
+ redisContext *c = redisConnect(log_ctx->redis_setup.server, log_ctx->redis_setup.port);
+ if (c != NULL && c->err) {
+ if (log_ctx->redis_setup.tried == 0) {
+ SCLogError(SC_ERR_SOCKET, "Error connecting to redis server: %s\n", c->errstr);
+ }
+ redisFree(c);
+ log_ctx->redis_setup.tried = time(NULL);
+ return -1;
+ }
+ log_ctx->redis = c;
+ log_ctx->redis_setup.tried = 0;
+ log_ctx->redis_setup.batch_count = 0;
+ return 0;
+}
+
+#endif
+
/** \brief LogFileNewCtx() Get a new LogFileCtx
* \retval LogFileCtx * pointer if succesful, NULL if error
* */
lf_ctx->Write = SCLogFileWrite;
lf_ctx->Close = SCLogFileClose;
+#ifdef HAVE_LIBHIREDIS
+ lf_ctx->redis_setup.batch_count = 0;
+#endif
+
return lf_ctx;
}
SCMutexUnlock(&lf_ctx->fp_mutex);
}
+#ifdef HAVE_LIBHIREDIS
+ if (lf_ctx->type == LOGFILE_TYPE_REDIS) {
+ if (lf_ctx->redis)
+ redisFree(lf_ctx->redis);
+ if (lf_ctx->redis_setup.server)
+ SCFree(lf_ctx->redis_setup.server);
+ if (lf_ctx->redis_setup.key)
+ SCFree(lf_ctx->redis_setup.key);
+ }
+#endif
+
SCMutexDestroy(&lf_ctx->fp_mutex);
if (lf_ctx->prefix != NULL)
if(lf_ctx->filename != NULL)
SCFree(lf_ctx->filename);
+ if (lf_ctx->sensor_name)
+ SCFree(lf_ctx->sensor_name);
+
OutputUnregisterFileRotationFlag(&lf_ctx->rotation_flag);
SCFree(lf_ctx);
SCReturnInt(1);
}
+
+#ifdef HAVE_LIBHIREDIS
+static int LogFileWriteRedis(LogFileCtx *file_ctx, char *string, size_t string_len)
+{
+ if (file_ctx->redis == NULL) {
+ SCConfLogReopenRedis(file_ctx);
+ if (file_ctx->redis == NULL) {
+ return -1;
+ } else {
+ SCLogInfo("Reconnected to redis server");
+ }
+ }
+ /* TODO go async here ? */
+ if (file_ctx->redis_setup.batch_size) {
+ redisAppendCommand(file_ctx->redis, "%s %s %s",
+ file_ctx->redis_setup.command,
+ file_ctx->redis_setup.key,
+ string);
+ if (file_ctx->redis_setup.batch_count == file_ctx->redis_setup.batch_size) {
+ redisReply *reply;
+ int i;
+ file_ctx->redis_setup.batch_count = 0;
+ for (i = 0; i <= file_ctx->redis_setup.batch_size; i++) {
+ if (redisGetReply(file_ctx->redis, (void **)&reply) == REDIS_OK) {
+ freeReplyObject(reply);
+ } else {
+ if (file_ctx->redis->err) {
+ SCLogInfo("Error when fetching reply: %s (%d)",
+ file_ctx->redis->errstr,
+ file_ctx->redis->err);
+ }
+ switch (file_ctx->redis->err) {
+ case REDIS_ERR_EOF:
+ case REDIS_ERR_IO:
+ SCLogInfo("Reopening connection to redis server");
+ SCConfLogReopenRedis(file_ctx);
+ if (file_ctx->redis) {
+ SCLogInfo("Reconnected to redis server");
+ return 0;
+ } else {
+ SCLogInfo("Unable to reconnect to redis server");
+ return 0;
+ }
+ break;
+ default:
+ SCLogWarning(SC_ERR_INVALID_VALUE,
+ "Unsupported error code %d",
+ file_ctx->redis->err);
+ return 0;
+ }
+ }
+ }
+ } else {
+ file_ctx->redis_setup.batch_count++;
+ }
+ } else {
+ redisReply *reply = redisCommand(file_ctx->redis, "%s %s %s",
+ file_ctx->redis_setup.command,
+ file_ctx->redis_setup.key,
+ string);
+
+ switch (reply->type) {
+ case REDIS_REPLY_ERROR:
+ SCLogWarning(SC_ERR_SOCKET, "Redis error: %s", reply->str);
+ SCConfLogReopenRedis(file_ctx);
+ break;
+ case REDIS_REPLY_INTEGER:
+ SCLogDebug("Redis integer %lld", reply->integer);
+ break;
+ default:
+ SCLogError(SC_ERR_INVALID_VALUE,
+ "Redis default triggered with %d", reply->type);
+ SCConfLogReopenRedis(file_ctx);
+ break;
+ }
+ freeReplyObject(reply);
+ }
+ return 0;
+}
+#endif
+
+int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
+{
+ if (file_ctx->type == LOGFILE_TYPE_SYSLOG) {
+ syslog(file_ctx->syslog_setup.alert_syslog_level, "%s",
+ (const char *)MEMBUFFER_BUFFER(buffer));
+ } else if (file_ctx->type == LOGFILE_TYPE_FILE ||
+ file_ctx->type == LOGFILE_TYPE_UNIX_DGRAM ||
+ file_ctx->type == LOGFILE_TYPE_UNIX_STREAM)
+ {
+ /* append \n for files only */
+ MemBufferWriteString(buffer, "\n");
+ SCMutexLock(&file_ctx->fp_mutex);
+ file_ctx->Write((const char *)MEMBUFFER_BUFFER(buffer),
+ MEMBUFFER_OFFSET(buffer), file_ctx);
+ SCMutexUnlock(&file_ctx->fp_mutex);
+ }
+#ifdef HAVE_LIBHIREDIS
+ else if (file_ctx->type == LOGFILE_TYPE_REDIS) {
+ SCMutexLock(&file_ctx->fp_mutex);
+ LogFileWriteRedis(file_ctx, (const char *)MEMBUFFER_BUFFER(buffer),
+ MEMBUFFER_OFFSET(buffer));
+ SCMutexUnlock(&file_ctx->fp_mutex);
+ }
+#endif
+
+ return 0;
+}
#include "conf.h" /* ConfNode */
#include "tm-modules.h" /* LogFileCtx */
+#include "util-buffer.h"
+
+#ifdef HAVE_LIBHIREDIS
+#include "hiredis/hiredis.h"
+#endif
typedef struct {
uint16_t fileno;
enum LogFileType { LOGFILE_TYPE_FILE,
LOGFILE_TYPE_SYSLOG,
LOGFILE_TYPE_UNIX_DGRAM,
- LOGFILE_TYPE_UNIX_STREAM };
+ LOGFILE_TYPE_UNIX_STREAM,
+ LOGFILE_TYPE_REDIS };
+
+typedef struct SyslogSetup_ {
+ int alert_syslog_level;
+} SyslogSetup;
+
+#ifdef HAVE_LIBHIREDIS
+enum RedisMode { REDIS_LIST, REDIS_CHANNEL };
+
+typedef struct RedisSetup_ {
+ enum RedisMode mode;
+ const char *command;
+ char *key;
+ int batch_size;
+ int batch_count;
+ char *server;
+ int port;
+ time_t tried;
+} RedisSetup;
+#endif
/** Global structure for Output Context */
typedef struct LogFileCtx_ {
union {
FILE *fp;
PcieFile *pcie_fp;
+#ifdef HAVE_LIBHIREDIS
+ redisContext *redis;
+#endif
+ };
+
+ union {
+ SyslogSetup syslog_setup;
+#ifdef HAVE_LIBHIREDIS
+ RedisSetup redis_setup;
+#endif
};
int (*Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp);
/** The name of the file */
char *filename;
+ /** Suricata sensor name */
+ char *sensor_name;
+
/** Handle auto-connecting / reconnecting sockets */
int is_sock;
int sock_type;
LogFileCtx *LogFileNewCtx(void);
int LogFileFreeCtx(LogFileCtx *);
+int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer);
int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *, const char *, int);
+int SCConfLogOpenRedis(ConfNode *conf, LogFileCtx *log_ctx);
int SCConfLogReopen(LogFileCtx *);
#endif /* __UTIL_LOGOPENFILE_H__ */
#ifdef PROFILING
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
/**
* Extra data for rule profiling.
*/
int profiling_rules_enabled = 0;
static char *profiling_file_name = "";
static const char *profiling_file_mode = "a";
+static int profiling_rule_json = 0;
/**
* Sort orders for dumping profiled rules.
profiling_output_to_file = 1;
}
+ if (ConfNodeChildValueIsTrue(conf, "json")) {
+#ifdef HAVE_LIBJANSSON
+ profiling_rule_json = 1;
+#else
+ SCLogWarning(SC_ERR_NO_JSON_SUPPORT, "no json support compiled in, using plain output");
+#endif
+ }
}
}
}
return s0->max > s1->max ? -1 : 1;
}
+#ifdef HAVE_LIBJANSSON
+
+static void DumpJson(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64_t total_ticks)
+{
+ char timebuf[64];
+ uint32_t i;
+ struct timeval tval;
+
+ json_t *js = json_object();
+ if (js == NULL)
+ return;
+ json_t *jsa = json_array();
+ if (jsa == NULL) {
+ json_decref(js);
+ return;
+ }
+
+ gettimeofday(&tval, NULL);
+ CreateIsoTimeString(&tval, timebuf, sizeof(timebuf));
+ json_object_set_new(js, "timestamp", json_string(timebuf));
+
+ for (i = 0; i < count; i++) {
+ /* Stop dumping when we hit our first rule with 0 checks. Due
+ * to sorting this will be the beginning of all the rules with
+ * 0 checks. */
+ if (summary[i].checks == 0)
+ break;
+
+ json_t *jsm = json_object();
+ if (jsm) {
+ json_object_set_new(jsm, "signature_id", json_integer(summary[i].sid));
+ json_object_set_new(jsm, "gid", json_integer(summary[i].gid));
+ json_object_set_new(jsm, "rev", json_integer(summary[i].rev));
+
+ json_object_set_new(jsm, "checks", json_integer(summary[i].checks));
+ json_object_set_new(jsm, "matches", json_integer(summary[i].matches));
+
+ json_object_set_new(jsm, "ticks_total", json_integer(summary[i].ticks));
+ json_object_set_new(jsm, "ticks_max", json_integer(summary[i].max));
+ json_object_set_new(jsm, "ticks_avg", json_integer(summary[i].avgticks));
+ json_object_set_new(jsm, "ticks_avg_match", json_integer(summary[i].avgticks_match));
+ json_object_set_new(jsm, "ticks_avg_nomatch", json_integer(summary[i].avgticks_no_match));
+
+ double percent = (long double)summary[i].ticks /
+ (long double)total_ticks * 100;
+ json_object_set_new(jsm, "percent", json_integer(percent));
+ json_array_append(jsa, jsm);
+ }
+ }
+ json_object_set_new(js, "rules", jsa);
+
+ char *js_s = json_dumps(js,
+ JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
+#ifdef JSON_ESCAPE_SLASH
+ JSON_ESCAPE_SLASH
+#else
+ 0
+#endif
+ );
+
+ if (unlikely(js_s == NULL))
+ return;
+ fprintf(fp, "%s", js_s);
+ free(js_s);
+ json_decref(js);
+}
+
+#endif /* HAVE_LIBJANSSON */
+
+static void DumpText(FILE *fp, SCProfileSummary *summary, uint32_t count, uint64_t total_ticks)
+{
+ uint32_t i;
+ struct timeval tval;
+ struct tm *tms;
+ gettimeofday(&tval, NULL);
+ struct tm local_tm;
+ tms = SCLocalTime(tval.tv_sec, &local_tm);
+
+ fprintf(fp, " ----------------------------------------------"
+ "----------------------------\n");
+ fprintf(fp, " Date: %" PRId32 "/%" PRId32 "/%04d -- "
+ "%02d:%02d:%02d\n", tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900,
+ tms->tm_hour,tms->tm_min, tms->tm_sec);
+ fprintf(fp, " ----------------------------------------------"
+ "----------------------------\n");
+ fprintf(fp, " %-8s %-12s %-8s %-8s %-12s %-6s %-8s %-8s %-11s %-11s %-11s %-11s\n", "Num", "Rule", "Gid", "Rev", "Ticks", "%", "Checks", "Matches", "Max Ticks", "Avg Ticks", "Avg Match", "Avg No Match");
+ fprintf(fp, " -------- "
+ "------------ "
+ "-------- "
+ "-------- "
+ "------------ "
+ "------ "
+ "-------- "
+ "-------- "
+ "----------- "
+ "----------- "
+ "----------- "
+ "-------------- "
+ "\n");
+ for (i = 0; i < MIN(count, profiling_rules_limit); i++) {
+
+ /* Stop dumping when we hit our first rule with 0 checks. Due
+ * to sorting this will be the beginning of all the rules with
+ * 0 checks. */
+ if (summary[i].checks == 0)
+ break;
+
+ double percent = (long double)summary[i].ticks /
+ (long double)total_ticks * 100;
+ fprintf(fp,
+ " %-8"PRIu32" %-12u %-8"PRIu32" %-8"PRIu32" %-12"PRIu64" %-6.2f %-8"PRIu64" %-8"PRIu64" %-11"PRIu64" %-11.2f %-11.2f %-11.2f\n",
+ i + 1,
+ summary[i].sid,
+ summary[i].gid,
+ summary[i].rev,
+ summary[i].ticks,
+ percent,
+ summary[i].checks,
+ summary[i].matches,
+ summary[i].max,
+ summary[i].avgticks,
+ summary[i].avgticks_match,
+ summary[i].avgticks_no_match);
+ }
+
+ fprintf(fp,"\n");
+}
+
/**
* \brief Dump rule profiling information to file
*
if (rules_ctx == NULL)
return;
- struct timeval tval;
- struct tm *tms;
if (profiling_output_to_file == 1) {
fp = fopen(profiling_file_name, profiling_file_mode);
SCProfileSummarySortByAvgTicksNoMatch);
break;
}
-
- gettimeofday(&tval, NULL);
- struct tm local_tm;
- tms = SCLocalTime(tval.tv_sec, &local_tm);
-
- fprintf(fp, " ----------------------------------------------"
- "----------------------------\n");
- fprintf(fp, " Date: %" PRId32 "/%" PRId32 "/%04d -- "
- "%02d:%02d:%02d\n", tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900,
- tms->tm_hour,tms->tm_min, tms->tm_sec);
- fprintf(fp, " ----------------------------------------------"
- "----------------------------\n");
- fprintf(fp, " %-8s %-12s %-8s %-8s %-12s %-6s %-8s %-8s %-11s %-11s %-11s %-11s\n", "Num", "Rule", "Gid", "Rev", "Ticks", "%", "Checks", "Matches", "Max Ticks", "Avg Ticks", "Avg Match", "Avg No Match");
- fprintf(fp, " -------- "
- "------------ "
- "-------- "
- "-------- "
- "------------ "
- "------ "
- "-------- "
- "-------- "
- "----------- "
- "----------- "
- "----------- "
- "-------------- "
- "\n");
- for (i = 0; i < MIN(count, profiling_rules_limit); i++) {
-
- /* Stop dumping when we hit our first rule with 0 checks. Due
- * to sorting this will be the beginning of all the rules with
- * 0 checks. */
- if (summary[i].checks == 0)
- break;
-
- double percent = (long double)summary[i].ticks /
- (long double)total_ticks * 100;
- fprintf(fp,
- " %-8"PRIu32" %-12u %-8"PRIu32" %-8"PRIu32" %-12"PRIu64" %-6.2f %-8"PRIu64" %-8"PRIu64" %-11"PRIu64" %-11.2f %-11.2f %-11.2f\n",
- i + 1,
- summary[i].sid,
- summary[i].gid,
- summary[i].rev,
- summary[i].ticks,
- percent,
- summary[i].checks,
- summary[i].matches,
- summary[i].max,
- summary[i].avgticks,
- summary[i].avgticks_match,
- summary[i].avgticks_no_match);
+#ifdef HAVE_LIBJANSSON
+ if (profiling_rule_json) {
+ DumpJson(fp, summary, count, total_ticks);
+ } else
+#endif
+ {
+ DumpText(fp, summary, count, total_ticks);
}
- fprintf(fp,"\n");
if (fp != stdout)
fclose(fp);
SCFree(summary);
for (ldev = 0; ldev < nlive; ldev++) {
char *live_dev_c = NULL;
- if (live_dev != NULL) {
+ if ((nlive <= 1) && (live_dev != NULL)) {
aconf = ConfigParser(live_dev);
live_dev_c = SCStrdup(live_dev);
if (unlikely(live_dev_c == NULL)) {
} \
} while(0)
+#define DEBUG_VALIDATE_BUG_ON(exp) BUG_ON((exp))
+
#else /* DEBUG_VALIDATE */
#define DEBUG_ASSERT_FLOW_LOCKED(f)
#define DEBUG_VALIDATE_FLOW(f)
#define DEBUG_VALIDATE_PACKET(p)
+#define DEBUG_VALIDATE_BUG_ON(exp)
#endif /* DEBUG_VALIDATE */
# user: suri
# group: suri
+# Some logging module will use that name in event as identifier. The default
+# value is the hostname
+#sensor-name: suricata
+
# Default pid file.
# Will use this file if no --pidfile in command options.
-#pid-file: /var/run/suricata.pid
+#pid-file: @e_rundir@suricata.pid
# Daemon working directory
# Suricata will change directory to this one if provided
# Extensible Event Format (nicknamed EVE) event log in JSON format
- eve-log:
enabled: yes
- filetype: regular #regular|syslog|unix_dgram|unix_stream
+ filetype: regular #regular|syslog|unix_dgram|unix_stream|redis
filename: eve.json
#prefix: "@cee: " # prefix to prepend to each log entry
# the following are valid when type: syslog above
#facility: local5
#level: Info ## possible levels: Emergency, Alert, Critical,
## Error, Warning, Notice, Info, Debug
+ #redis:
+ # server: 127.0.0.1
+ # port: 6379
+ # mode: list ## possible values: list (default), channel
+ # key: suricata ## key or channel to use (default to suricata)
+ # Redis pipelining set up. This will enable to only do a query every
+ # 'batch-size' events. This should lower the latency induced by network
+ # connection at the cost of some memory. There is no flushing implemented
+ # so this setting as to be reserved to high traffic suricata.
+ # pipelining:
+ # enabled: yes ## set enable to yes to enable query pipelining
+ # batch-size: 10 ## number of entry to keep in buffer
types:
- alert:
# payload: yes # enable dumping payload in Base64
# http: yes # enable dumping of http fields
# tls: yes # enable dumping of tls fields
# ssh: yes # enable dumping of ssh fields
+ # smtp: yes # enable dumping of smtp fields
# HTTP X-Forwarded-For support by adding an extra field or overwriting
# the source or destination IP address (depending on flow direction)
force-md5: no # force logging of md5 checksums
#- drop:
# alerts: no # log alerts that caused drops
- - smtp
+ - smtp:
+ #extended: yes # enable this for extended logging information
+ # this includes: bcc, message-id, subject, x_mailer, user-agent
+ # custom fields logging from the list:
+ # reply-to, bcc, message-id, subject, x-mailer, user-agent, received,
+ # x-originating-ip, in-reply-to, references, importance, priority,
+ # sensitivity, organization, content-md5, date
+ #custom: [received, x-mailer, x-originating-ip, relays, reply-to, bcc]
+ # output md5 of fields: body, subject
+ # for the body you need to set app-layer.protocols.smtp.mime.body-md5
+ # to yes
+ #md5: [body, subject]
+
- ssh
- stats:
totals: yes # stats for all threads merged together
# Sensor ID field of unified2 alerts.
#sensor-id: 0
+ # Include payload of packets related to alerts. Defaults to true, set to
+ # false if payload is not required.
+ #payload: yes
+
# HTTP X-Forwarded-For support by adding the unified2 extra header or
# overwriting the source or destination IP address (depending on flow
# direction) with the one reported in the X-Forwarded-For HTTP header.
# type: json
- file:
enabled: no
- filename: /var/log/suricata.log
+ filename: @e_logdir@suricata.log
# type: json
- syslog:
enabled: no
# Extract URLs and save in state data structure
extract-urls: yes
+ # Set to yes to compute the md5 of the mail body. You will then
+ # be able to journalize it.
+ body-md5: no
# Configure inspected-tracker for file_data keyword
inspected-tracker:
content-limit: 1000
# Sort options: ticks, avgticks, checks, matches, maxticks
sort: avgticks
- # Limit the number of items printed at exit.
+ # Limit the number of items printed at exit (ignored for json).
limit: 100
+ # output to json
+ json: true
+
# per keyword profiling
keywords:
enabled: yes
#!/bin/bash
+
+# setenv.sh
+#
+#
+# Copyright 2015, Yunify, Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
export GERRITROOT="$(pwd)"
export ONOSROOT=$GERRITROOT/framework/src/onos/
export BUILDROOT=$GERRITROOT/framework/build