From: Russ Combs (rucombs) Date: Wed, 2 Mar 2016 18:25:51 +0000 (-0500) Subject: Merge pull request #309 in SNORT/snort3 from host_tracker_stats3 to master X-Git-Tag: 3.0.0-233~564 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c93eecf565baf56cd72bd9afc914600a011d2d81;p=thirdparty%2Fsnort3.git Merge pull request #309 in SNORT/snort3 from host_tracker_stats3 to master Squashed commit of the following: commit abba8b36baa782641691a4fd1186611e5f3f21da Author: Steve Chew Date: Tue Mar 1 16:51:02 2016 -0500 Made target_link_libraries more readable. commit ca7389694b473b71b96849cb5927c55c35d54aaa Author: Steve Chew Date: Tue Mar 1 16:42:33 2016 -0500 Fix finding of library for host_tracker test in ccmake. commit 86a969c109a40ada599c6a591afe1a605e71b207 Author: Steve Chew Date: Mon Feb 29 15:04:42 2016 -0500 Updates baesd on reviews. commit 81f126cbc8e5eb55be2a675a97e05a823a0d0d9d Author: Steve Chew Date: Fri Feb 26 13:40:30 2016 -0500 Fixes based on reviews. commit e8e49232e68581003fc9c5215e7a5c5971e4b1ab Author: Steve Chew Date: Fri Feb 19 13:31:29 2016 -0500 Add statistics counters to host_tracker module. --- diff --git a/src/host_tracker/CMakeLists.txt b/src/host_tracker/CMakeLists.txt index fc3d43ef0..2d5d29b39 100644 --- a/src/host_tracker/CMakeLists.txt +++ b/src/host_tracker/CMakeLists.txt @@ -4,5 +4,6 @@ add_library( host_tracker STATIC host_cache.h host_module.cc host_module.h + host_tracker.cc host_tracker.h ) diff --git a/src/host_tracker/Makefile.am b/src/host_tracker/Makefile.am index 317c6ec37..9a2460fe8 100644 --- a/src/host_tracker/Makefile.am +++ b/src/host_tracker/Makefile.am @@ -6,6 +6,7 @@ host_cache.cc \ host_cache.h \ host_module.cc \ host_module.h \ +host_tracker.cc \ host_tracker.h if BUILD_UNIT_TESTS diff --git a/src/host_tracker/host_cache.h b/src/host_tracker/host_cache.h index 3655afeac..6cea2fcb3 100644 --- a/src/host_tracker/host_cache.h +++ b/src/host_tracker/host_cache.h @@ -29,23 +29,28 @@ #include "hash/lru_cache_shared.h" #include "main/snort_types.h" + struct HostIpKey { static const int key_size = 16; - uint8_t ip_addr[key_size] { 0 }; // Holds either IPv4 or IPv6 addr + union host_ip_addr + { + uint8_t ip8[key_size]; + uint64_t ip64[key_size/8]; + } ip_addr = {{0}}; // Holds either IPv4 or IPv6 addr HostIpKey() { } - HostIpKey(uint8_t ip[key_size]) + HostIpKey(const uint8_t ip[key_size]) { - memcpy(ip_addr, ip, key_size); + memcpy(&ip_addr, ip, key_size); } inline bool operator==(const HostIpKey& rhs) const { - return !memcmp(ip_addr, rhs.ip_addr, key_size); + return !memcmp(&ip_addr, &rhs.ip_addr, key_size); } }; @@ -54,8 +59,8 @@ struct HashHostIpKey { size_t operator()(const HostIpKey& ip) const { - return std::hash() (*((long long*)&ip.ip_addr[0])) ^ - std::hash() (*((long long*)&ip.ip_addr[8])); + return std::hash() (ip.ip_addr.ip64[0]) ^ + std::hash() (ip.ip_addr.ip64[1]); } }; diff --git a/src/host_tracker/host_module.cc b/src/host_tracker/host_module.cc index eefdaa50a..dae6157ee 100644 --- a/src/host_tracker/host_module.cc +++ b/src/host_tracker/host_module.cc @@ -24,6 +24,14 @@ #include "stream/stream_api.h" #include "target_based/snort_protocols.h" +const PegInfo host_tracker_pegs[] = +{ + { "service adds", "host service adds" }, + { "service finds", "host service finds" }, + { "service removes", "host service removes" }, + { nullptr, nullptr }, +}; + const Parameter HostTrackerModule::service_params[] = { { "name", Parameter::PT_STRING, nullptr, nullptr, @@ -108,3 +116,9 @@ bool HostTrackerModule::end(const char* fqn, int idx, SnortConfig*) return true; } +const PegInfo* HostTrackerModule::get_pegs() const +{ return host_tracker_pegs; } + +PegCount* HostTrackerModule::get_counts() const +{ return (PegCount*)&host_tracker_stats; } + diff --git a/src/host_tracker/host_module.h b/src/host_tracker/host_module.h index fc6f90755..61f31d837 100644 --- a/src/host_tracker/host_module.h +++ b/src/host_tracker/host_module.h @@ -47,6 +47,9 @@ public: assert(!host); } + const PegInfo* get_pegs() const override; + PegCount* get_counts() const override; + bool set(const char*, Value&, SnortConfig*) override; bool begin(const char*, int, SnortConfig*) override; bool end(const char*, int, SnortConfig*) override; diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc new file mode 100644 index 000000000..862fb0cd7 --- /dev/null +++ b/src/host_tracker/host_tracker.cc @@ -0,0 +1,24 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// host_tracker.cc author Steve Chew + +#include "host_tracker/host_tracker.h" + +THREAD_LOCAL struct HostTrackerStats host_tracker_stats; + diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index c56f23c41..3d10b4dfb 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -32,6 +32,8 @@ #include #include "sfip/sfip_t.h" +#include "framework/counts.h" +#include "main/thread.h" // FIXIT-H -- For now this emulates the Snort++ attribute table. Need // to add in sfrnaincludes/host_tracker.h data eventually. @@ -40,6 +42,15 @@ typedef uint16_t Port; typedef uint16_t Protocol; typedef uint8_t Policy; +struct HostTrackerStats +{ + PegCount service_adds; + PegCount service_finds; + PegCount service_removes; +}; + +extern THREAD_LOCAL struct HostTrackerStats host_tracker_stats; + struct HostApplicationEntry { Port port = 0; @@ -127,6 +138,8 @@ public: // false if entry exists already, and true if entry was added. bool add_service(const HostApplicationEntry& app_entry) { + host_tracker_stats.service_adds++; + std::lock_guard lck(host_tracker_lock); auto iter = std::find(services.begin(), services.end(), app_entry); @@ -141,6 +154,8 @@ public: // replace the previous entry with the new entry. void add_or_replace_service(const HostApplicationEntry& app_entry) { + host_tracker_stats.service_adds++; + std::lock_guard lck(host_tracker_lock); auto iter = std::find(services.begin(), services.end(), app_entry); @@ -155,6 +170,7 @@ public: bool find_service(Protocol ipproto, Port port, HostApplicationEntry& app_entry) { HostApplicationEntry tmp_entry(ipproto, port, HostApplicationEntry::UNKNOWN_PROTOCOL); + host_tracker_stats.service_finds++; std::lock_guard lck(host_tracker_lock); @@ -173,6 +189,7 @@ public: bool remove_service(Protocol ipproto, Port port) { HostApplicationEntry tmp_entry(ipproto, port, HostApplicationEntry::UNKNOWN_PROTOCOL); + host_tracker_stats.service_removes++; std::lock_guard lck(host_tracker_lock); diff --git a/src/host_tracker/test/CMakeLists.txt b/src/host_tracker/test/CMakeLists.txt new file mode 100644 index 000000000..83ed281f3 --- /dev/null +++ b/src/host_tracker/test/CMakeLists.txt @@ -0,0 +1,12 @@ + + +add_cpputest(host_cache_test host_tracker) +add_cpputest(host_module_test host_tracker) +add_cpputest(host_tracker_test host_tracker) + +target_link_libraries(host_module_test + ${CMAKE_BINARY_DIR}/src/framework/libframework.a + ${CMAKE_BINARY_DIR}/src/catch/libcatch_tests.a + ${CMAKE_BINARY_DIR}/src/sfip/libsfip.a + ${DNET_LIBRARIES}) + diff --git a/src/host_tracker/test/Makefile.am b/src/host_tracker/test/Makefile.am index fd435224f..a0c5a01a6 100644 --- a/src/host_tracker/test/Makefile.am +++ b/src/host_tracker/test/Makefile.am @@ -2,14 +2,17 @@ AM_DEFAULT_SOURCE_EXT = .cc check_PROGRAMS = \ +host_module_test \ host_cache_test \ host_tracker_test TESTS = $(check_PROGRAMS) +host_module_test_CPPFLAGS = @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@ host_cache_test_CPPFLAGS = @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@ host_tracker_test_CPPFLAGS = @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@ -host_cache_test_LDADD = ../host_cache.o @CPPUTEST_LDFLAGS@ -host_tracker_test_LDADD = @CPPUTEST_LDFLAGS@ +host_module_test_LDADD = ../host_module.o ../host_cache.o ../host_tracker.o ../../framework/libframework.a ../../catch/libcatch_tests.a ../../sfip/libsfip.a ../../utils/libutils.a @CPPUTEST_LDFLAGS@ +host_cache_test_LDADD = ../host_cache.o ../host_tracker.o @CPPUTEST_LDFLAGS@ +host_tracker_test_LDADD = ../host_tracker.o @CPPUTEST_LDFLAGS@ diff --git a/src/host_tracker/test/host_cache_test.cc b/src/host_tracker/test/host_cache_test.cc index f8054ad1e..d37eb8050 100644 --- a/src/host_tracker/test/host_cache_test.cc +++ b/src/host_tracker/test/host_cache_test.cc @@ -43,7 +43,7 @@ TEST(host_cache, host_ip_key_test) uint8_t expected_hk[16] = { 0xde,0xad,0xbe,0xef,0xab,0xcd,0xef,0x01,0x23,0x34,0x56,0x78,0x90,0xab,0xcd,0xef }; - memset(zeroed_hk.ip_addr, 0, sizeof(zeroed_hk.ip_addr)); + memset(&zeroed_hk.ip_addr, 0, sizeof(zeroed_hk.ip_addr)); HostIpKey hkey1; CHECK(hkey1 == zeroed_hk); diff --git a/src/host_tracker/test/host_module_test.cc b/src/host_tracker/test/host_module_test.cc new file mode 100644 index 000000000..0d76e50db --- /dev/null +++ b/src/host_tracker/test/host_module_test.cc @@ -0,0 +1,162 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// host_module_test.cc author Steve Chew +// unit tests for the host module APIs + +#include "host_tracker/host_module.h" + +#include +#include + +#include "host_tracker/host_cache.h" +#include "sfip/sf_ip.h" + +// Fake AddProtocolReference to avoid bringing in a ton of dependencies. +int16_t AddProtocolReference(const char* protocol) +{ + if (!strcmp("servicename", protocol)) + return 3; + if (!strcmp("tcp", protocol)) + return 2; + return 1; +} + +// Fake show_stats to avoid bringing in a ton of dependencies. +void show_stats( + PegCount* , const PegInfo* , unsigned , const char* ) +{ +} + +#define FRAG_POLICY 33 +#define STREAM_POLICY 100 + +sfip_t expected_addr; + +TEST_GROUP(host_module) +{ + void setup() + { + Value ip_val("10.23.45.56"); + Value frag_val((double)FRAG_POLICY); + Value tcp_val((double)STREAM_POLICY); + Value name_val("servicename"); + Value proto_val("udp"); + Value port_val((double)2112); + Parameter ip_param = { "ip", Parameter::PT_ADDR, nullptr, "0.0.0.0/32", "addr/cidr"}; + Parameter frag_param = { "frag_policy", Parameter::Parameter::PT_ENUM, "linux | bsd", nullptr, "frag policy"}; + Parameter tcp_param = { "tcp_policy", Parameter::PT_ENUM, "linux | bsd", nullptr, "tcp policy"}; + Parameter name_param = {"name", Parameter::PT_STRING, nullptr, nullptr, "name"}; + Parameter proto_param = {"proto", Parameter::PT_ENUM, "tcp | udp", "tcp", "ip proto"}; + Parameter port_param = {"port", Parameter::PT_PORT, nullptr, nullptr, "port num"}; + HostTrackerModule module; + const PegInfo *ht_pegs = module.get_pegs(); + const PegCount *ht_stats = module.get_counts(); + + CHECK(!strcmp(ht_pegs[0].name, "service adds")); + CHECK(!strcmp(ht_pegs[1].name, "service finds")); + CHECK(!strcmp(ht_pegs[2].name, "service removes")); + CHECK(!ht_pegs[3].name); + + CHECK(ht_stats[0] == 0); + CHECK(ht_stats[1] == 0); + CHECK(ht_stats[2] == 0); + + ip_val.set(&ip_param); + frag_val.set(&frag_param); + tcp_val.set(&tcp_param); + name_val.set(&name_param); + proto_val.set(&proto_param); + port_val.set(&port_param); + + // Change IP from string to integer representation. + ip_param.validate(ip_val); + + // Set up the module values and add a service. + module.begin("host_tracker", 1, nullptr); + module.set(nullptr, ip_val, nullptr); + module.set(nullptr, frag_val, nullptr); + module.set(nullptr, tcp_val, nullptr); + module.set(nullptr, name_val, nullptr); + module.set(nullptr, proto_val, nullptr); + module.set(nullptr, port_val, nullptr); + module.end("host_tracker.services", 1, nullptr); + module.end("host_tracker", 1, nullptr); + + ip_val.get_addr(expected_addr); + } + + void teardown() + { + memset(&host_tracker_stats, 0, sizeof(host_tracker_stats)); + host_cache.clear(); // Free HostTracker objects + } +}; + +// Test that HostModules variables are set correctly. +TEST(host_module, host_module_test_values) +{ + sfip_t cached_addr; + + HostIpKey host_ip_key(expected_addr.ip8); + std::shared_ptr ht; + + bool ret = host_cache.find(host_ip_key, ht); + CHECK(ret == true); + + cached_addr = ht->get_ip_addr(); + CHECK(sfip_fast_equals_raw(&cached_addr, &expected_addr) == 1); + + Policy policy = ht->get_stream_policy(); + CHECK(policy == STREAM_POLICY + 1); + + policy = ht->get_frag_policy(); + CHECK(policy == FRAG_POLICY + 1); +} + + +// Test that HostModules statistics are correct. +TEST(host_module, host_module_test_stats) +{ + HostIpKey host_ip_key(expected_addr.ip8); + std::shared_ptr ht; + + bool ret = host_cache.find(host_ip_key, ht); + CHECK(ret == true); + + HostApplicationEntry app; + ret = ht->find_service(1, 2112, app); + CHECK(ret == true); + CHECK(app.protocol == 3); + CHECK(app.ipproto == 1); + CHECK(app.port == 2112); + + ret = ht->remove_service(1, 2112); + CHECK(ret == true); + + // Verify counts are correct. The add was done during setup. + CHECK(host_tracker_stats.service_adds == 1); + CHECK(host_tracker_stats.service_finds == 1); + CHECK(host_tracker_stats.service_removes == 1); +} + +int main(int argc, char** argv) +{ + return CommandLineTestRunner::RunAllTests(argc, argv); +} +