A list of common fields which are logged:
* ts (timestamp)
+ * uid (connection id)
* id.orig_h (client IP address)
* id.orig_p (client TCP port)
* id.resp_h (server IP address)
for (const auto& p : extractor_config.protocols)
{
if (p.tenant_id == service_config.tenant_id and p.service == service_config.service)
- {
- ParseError("%s service got multiple configurations", service_config.service.c_str());
- break;
- }
+ ParseWarning(WARN_CONF_STRICT, "%s service got multiple configurations", service_config.service.c_str());
}
extractor_config.protocols.push_back(service_config);
bool ExtractorModule::end(const char* fqn, int idx, SnortConfig*)
{
- if (idx > 0 && !strcmp(fqn, "extractor.protocols"))
+ if (!idx or strcmp(fqn, "extractor.protocols"))
+ return true;
+
+ if (service_config.fields.empty())
{
- if (service_config.fields.empty())
- {
- ParseError("Can't initialize extractor without protocols.fields");
- return false;
- }
- commit_config();
+ ParseError("can't initialize extractor without protocols.fields");
+ return false;
}
+ commit_config();
+
return true;
}
//--------------------------------------------------------------------------
// csv_logger.cc author Anna Norokh <anorokh@cisco.com>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "extractor_csv_logger.h"
#include <algorithm>
public:
CsvExtractorLogger(OutputType o_type, const std::vector<std::string>& fields)
: ExtractorLogger(fields), writer(ExtractorWriter::make_writer(o_type))
- { CsvExtractorLogger::add_header(); }
+ {
+ if (writer)
+ CsvExtractorLogger::add_header();
+ }
+
~CsvExtractorLogger() override;
void add_header() override;
#ifndef EXTRACTOR_EVENT_HANDLERS_H
#define EXTRACTOR_EVENT_HANDLERS_H
+#include "flow/flow_key.h"
#include "framework/data_bus.h"
#include "extractor.h"
class ExtractorEvent
{
+public:
+ static FlowHashKeyOps& get_hash()
+ {
+ static thread_local FlowHashKeyOps flow_key_ops(0);
+ return flow_key_ops;
+ }
+
protected:
ExtractorEvent(uint32_t tid, const std::vector<std::string>& flds, ExtractorLogger& l)
: tenant_id(tid), fields(flds), logger(l) {}
Value* get_ip_src_port(DataEvent*, Packet*, Flow*);
Value* get_ip_dst_port(DataEvent*, Packet*, Flow*);
Value* get_pkt_num(DataEvent*, Packet*, Flow*);
+Value* get_uid(DataEvent*, Packet*, Flow*);
static void field_to_string(const Field& field, std::string& value)
{
return new Value(p->context->packet_number);
}
+Value* get_uid(DataEvent*, Packet*, Flow* f)
+{
+ unsigned key = ExtractorEvent::get_hash().do_hash((const unsigned char*)f->key, 0);
+
+ return new Value((uint64_t)key);
+}
+
static std::map<std::string, GetFunc> event_getters =
{
{"ts", get_timestamp},
+ {"uid", get_uid},
{"id.orig_h", get_ip_src},
{"id.resp_h", get_ip_dst},
{"id.orig_p", get_ip_src_port},
//--------------------------------------------------------------------------
// extractor_logger.cc author Anna Norokh <anorokh@cisco.com>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "extractor_logger.h"
+#include <cassert>
+
#include "extractor_csv_logger.h"
ExtractorLogger* ExtractorLogger::make_logger(FormatType f_type, OutputType o_type,
const std::vector<std::string>& fields)
{
+ if (fields.empty())
+ return nullptr;
+
+ ExtractorLogger* logger = nullptr;
+
switch (f_type)
{
case FormatType::CSV:
- return new CsvExtractorLogger(o_type, fields);
+ logger = new CsvExtractorLogger(o_type, fields);
+ break;
}
- return nullptr;
+ assert(logger);
+
+ return logger;
}
std::vector<std::string> ExtractorService::common_fields =
{
"ts",
+ "uid",
"id.orig_h",
"id.orig_p",
"id.resp_h",
{
add_fields(srv_fields);
add_events(srv_events);
-
logger = ExtractorLogger::make_logger(f_type, o_type, get_fields());
}
if (find_event(val))
events.push_back(val);
else
- ParseError("Invalid protocols.on_events value %s", val.c_str());
+ ParseWarning(WARN_CONF_STRICT, "unsupported '%s' event in protocols.on_events", val.c_str());
}
}
if (find_field(val))
fields.push_back(val);
else
- ParseError("Invalid protocols.fields value %s", val.c_str());
+ ParseWarning(WARN_CONF_STRICT, "unsupported '%s' field in protocols.fields", val.c_str());
}
}
ExtractorService* ExtractorService::make_service(const ServiceConfig& cfg, FormatType f_type, OutputType o_type)
{
if (cfg.on_events.empty())
+ {
ParseError("%s service misses on_events field", cfg.service.c_str());
+ return nullptr;
+ }
+
+ ExtractorService* srv = nullptr;
switch (cfg.service)
{
- case ServiceType::HTTP:
- return new HttpExtractorService(cfg.tenant_id, cfg.fields, cfg.on_events, cfg.service, f_type, o_type);
+ case ServiceType::HTTP:
+ srv = new HttpExtractorService(cfg.tenant_id, cfg.fields, cfg.on_events, cfg.service, f_type, o_type);
+ break;
- case ServiceType::UNDEFINED:
- ParseError("%s service is not supported", cfg.service.c_str());
- break;
-
- default:
- return nullptr;
+ case ServiceType::UNDEFINED: // fallthrough
+ default:
+ ParseError("'%s' service is not supported", cfg.service.c_str());
}
- return nullptr;
+
+ return srv;
}
bool ExtractorService::find_event(const std::string& event) const
const std::vector<std::string>& srv_events, ServiceType s_type, FormatType f_type, OutputType o_type)
: ExtractorService(tenant, srv_fields, srv_events, blueprint, s_type, f_type, o_type)
{
+ if (!logger)
+ return;
+
for (const auto& event : get_events())
{
if (!strcmp("eot", event.c_str()))
}
}
}
-
enum Value : uint8_t
{
HTTP,
- UNDEFINED
+ UNDEFINED,
+ MAX
};
ServiceType() = default;
{
switch (v)
{
- case UNDEFINED:
- return "(not set)";
case HTTP:
return "http";
+ case UNDEFINED: // fallthrough
+ case MAX: // fallthrough
default:
return "(not set)";
}
const uint32_t tenant_id;
std::vector<std::string> fields;
std::vector<std::string> events;
- ExtractorLogger* logger;
- const ServiceBlueprint& sbp;
+ ExtractorLogger* logger = nullptr;
+
+ const ServiceBlueprint& sbp;
const ServiceType type;
};
//--------------------------------------------------------------------------
// extractor_writer.cc author Anna Norokh <anorokh@cisco.com>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "extractor_writer.h"
ExtractorWriter* ExtractorWriter::make_writer(OutputType o_type)
{
case OutputType::STD:
return new StdExtractorWriter();
+ case OutputType::MAX: // fallthrough
+ default:
+ return nullptr;
}
-
- return nullptr;
}
public:
enum Value : uint8_t
{
- STD
+ STD,
+ MAX
};
OutputType() = default;
{
case STD:
return "stdout";
+ case MAX: // fallthrough
default:
return "(not set)";
}