Merge in SNORT/snort3 from ~OSHUMEIK/snort3:extr_json to master
Squashed commit of the following:
commit
2bd2c95c4d5ab3b10dc1600f79e77e0c5fe2ab9e
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Wed Sep 4 09:56:08 2024 +0300
extractor: mention a field in initialization list
Despite that initialization order is defined by class fields only,
an explicit initializer in the list will add cross-validation.
commit
7eeaf9b8814aab9331a0e6d507c7e356ee8a9582
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Tue Sep 3 13:50:18 2024 +0300
extractor: add unit tests for enum types
commit
08928ef3bddf3f61878fe2a936d6be96f2a410e1
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Tue Sep 3 10:49:41 2024 +0300
extractor: remove unused headers
commit
4a6f42fd87d00ce27d5b8b27add094921c85fd5e
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Wed Aug 28 12:13:52 2024 +0300
extractor: add json logger
commit
b783608bc41247bd3d45e8acedfc87c5dea445c2
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Wed Aug 28 12:00:25 2024 +0300
extractor: fix local variable
Declare a local variable to be static to not interfere at linking stage.
commit
077f8133e94079ec86ee5e053b96f2b45afa71de
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Wed Aug 28 11:55:23 2024 +0300
extractor: take a note of FIXIT-P in key points
commit
08ed77f484fa19a4cd384af4ee62565a5ea81976
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Wed Aug 28 11:47:49 2024 +0300
extractor: add field name to logging function
Field order is not preset for all formattings.
Thus, a caller must pass a field name for proper logging.
commit
7a81360468ffe1431c4f93d384b295f659c7b93e
Author: Oleksii Shumeiko <oshumeik@cisco.com>
Date: Tue Aug 27 15:21:38 2024 +0300
extractor: fix guard-macro names
extractor_csv_logger.h
extractor_event_handlers.h
extractor_http_event_handler.cc
+ extractor_json_logger.cc
+ extractor_json_logger.h
extractor_logger.cc
extractor_logger.h
extractor_service.cc
static const Parameter s_params[] =
{
- { "formatting", Parameter::PT_ENUM, "csv", "csv",
+ { "formatting", Parameter::PT_ENUM, "csv | json", "csv",
"output format for extractor" },
{ "output", Parameter::PT_ENUM, "stdout", "stdout",
#include "extractor_csv_logger.h"
-#include <algorithm>
#include <cassert>
+#include <string>
-THREAD_LOCAL bool first_write;
+static THREAD_LOCAL bool first_write;
void CsvExtractorLogger::add_header()
{
writer->unlock();
}
-void CsvExtractorLogger::add_field(const snort::Value& v)
+void CsvExtractorLogger::add_field(const char*, const snort::Value& v)
{
switch (v.get_type())
{
//--------------------------------------------------------------------------
// csv_logger.h author Anna Norokh <anorokh@cisco.com>
-#ifndef CSV_LOGGER_H
-#define CSV_LOGGER_H
+#ifndef EXTRACTOR_CSV_LOGGER_H
+#define EXTRACTOR_CSV_LOGGER_H
#include "framework/value.h"
~CsvExtractorLogger() override;
void add_header() override;
- void add_field(const snort::Value&) override;
+ void add_field(const char*, const snort::Value&) override;
void open_record() override;
void close_record() override;
using namespace snort;
+// FIXIT-P: inspector's data passes many functions before getting to the logger
typedef Value* (*GetFunc) (DataEvent*, Packet*, Flow*);
logger.open_record();
for (const auto& field : fields)
{
+ // FIXIT-P: this is way too slow (a map with a string key type)
auto val = std::unique_ptr<Value>(event_getters[field](&event, p, flow));
- logger.add_field(*val.get());
+ logger.add_field(field.c_str(), *val.get());
}
logger.close_record();
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2024-2024 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.
+//--------------------------------------------------------------------------
+// json_logger.cc author Cisco
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "extractor_json_logger.h"
+
+#include <cassert>
+
+void JsonExtractorLogger::open_record()
+{
+ oss.str("");
+ js.open();
+}
+
+void JsonExtractorLogger::close_record()
+{
+ js.close();
+
+ writer->lock();
+ writer->write(oss.str().c_str());
+ writer->unlock();
+}
+
+void JsonExtractorLogger::add_field(const char* f, const snort::Value& v)
+{
+ switch (v.get_type())
+ {
+ case snort::Value::ValueType::VT_UNUM:
+ js.uput(f, v.get_uint64());
+ break;
+
+ case snort::Value::ValueType::VT_STR:
+ js.put(f, v.get_string());
+ break;
+
+ case snort::Value::ValueType::VT_BOOL: // fallthrough
+ case snort::Value::ValueType::VT_NUM: // fallthrough
+ case snort::Value::ValueType::VT_REAL: // fallthrough
+ default:
+ assert(false);
+ break;
+ }
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2024-2024 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.
+//--------------------------------------------------------------------------
+// json_logger.h author Cisco
+
+#ifndef EXTRACTOR_JSON_LOGGER_H
+#define EXTRACTOR_JSON_LOGGER_H
+
+#include <sstream>
+
+#include "framework/value.h"
+#include "helpers/json_stream.h"
+
+#include "extractor_logger.h"
+#include "extractor_writer.h"
+
+class JsonExtractorLogger : public ExtractorLogger
+{
+public:
+ JsonExtractorLogger(OutputType o_type, const std::vector<std::string>& fields)
+ : ExtractorLogger(fields), writer(ExtractorWriter::make_writer(o_type)), oss(), js(oss)
+ { }
+
+ ~JsonExtractorLogger() override
+ { delete writer; }
+
+ void add_field(const char*, const snort::Value&) override;
+ void open_record() override;
+ void close_record() override;
+
+private:
+ ExtractorWriter* const writer;
+ std::ostringstream oss;
+ snort::JsonStream js;
+
+};
+
+#endif
#include <cassert>
#include "extractor_csv_logger.h"
+#include "extractor_json_logger.h"
ExtractorLogger* ExtractorLogger::make_logger(FormatType f_type, OutputType o_type,
const std::vector<std::string>& fields)
case FormatType::CSV:
logger = new CsvExtractorLogger(o_type, fields);
break;
+ case FormatType::JSON:
+ logger = new JsonExtractorLogger(o_type, fields);
+ break;
+ case FormatType::MAX: // fallthrough
+ default:
+ break;
}
assert(logger);
return logger;
}
+
+#ifdef UNIT_TEST
+
+#include "catch/snort_catch.h"
+
+#include <memory.h>
+
+using namespace snort;
+
+TEST_CASE("Format Type", "[extractor]")
+{
+ SECTION("to string")
+ {
+ FormatType csv = FormatType::CSV;
+ FormatType json = FormatType::JSON;
+ FormatType max = FormatType::MAX;
+
+ CHECK_FALSE(strcmp("csv", csv.c_str()));
+ CHECK_FALSE(strcmp("json", json.c_str()));
+ CHECK_FALSE(strcmp("(not set)", max.c_str()));
+ }
+}
+
+#endif
public:
enum Value : uint8_t
{
- CSV
+ CSV,
+ JSON,
+ MAX
};
FormatType() = default;
{
case CSV:
return "csv";
+ case JSON:
+ return "json";
+ case MAX: // fallthrough
default:
return "(not set)";
}
virtual void add_header() {}
virtual void add_footer() {}
- virtual void add_field(const snort::Value&) {}
+ // FIXIT-P: replace Value type designed for parsing with a better type
+ virtual void add_field(const char*, const snort::Value&) {}
virtual void open_record() {}
virtual void close_record() {}
}
}
}
+
+#ifdef UNIT_TEST
+
+#include "catch/snort_catch.h"
+
+#include <memory.h>
+
+using namespace snort;
+
+TEST_CASE("Service Type", "[extractor]")
+{
+ SECTION("to string")
+ {
+ ServiceType http = ServiceType::HTTP;
+ ServiceType undef = ServiceType::UNDEFINED;
+ ServiceType max = ServiceType::MAX;
+
+ CHECK_FALSE(strcmp("http", http.c_str()));
+ CHECK_FALSE(strcmp("(not set)", undef.c_str()));
+ CHECK_FALSE(strcmp("(not set)", max.c_str()));
+ }
+}
+
+#endif
//--------------------------------------------------------------------------
// extractor_service.h author Maya Dagon <mdagon@cisco.com>
-#ifndef EXTRACTOR_SERVICES_H
-#define EXTRACTOR_SERVICES_H
+#ifndef EXTRACTOR_SERVICE_H
+#define EXTRACTOR_SERVICE_H
#include <algorithm>
#include <string>
std::vector<std::string> supported_fields;
};
+// FIXIT-P: make a template with Logger and Writer as parameters
class ExtractorService
{
public:
return nullptr;
}
}
+
+#ifdef UNIT_TEST
+
+#include "catch/snort_catch.h"
+
+#include <memory.h>
+
+using namespace snort;
+
+TEST_CASE("Output Type", "[extractor]")
+{
+ SECTION("to string")
+ {
+ OutputType std = OutputType::STD;
+ OutputType max = OutputType::MAX;
+
+ CHECK_FALSE(strcmp("stdout", std.c_str()));
+ CHECK_FALSE(strcmp("(not set)", max.c_str()));
+ }
+}
+
+#endif