DNS_RRTYPE_MAX,
} DnsRRTypes;
+typedef enum {
+ DNS_VERSION_1 = 1,
+ DNS_VERSION_2
+} DnsVersion;
+
static struct {
const char *config_rrtype;
uint64_t flags;
LogFileCtx *file_ctx;
uint64_t flags; /** Store mode */
bool include_metadata;
+ DnsVersion version;
} LogDnsFileCtx;
typedef struct LogDnsLogThread_ {
SCFree(output_ctx);
}
-static void JsonDnsLogInitFilters(LogDnsFileCtx *dnslog_ctx, ConfNode *conf)
+static void JsonDnsLogParseConfig(LogDnsFileCtx *dnslog_ctx, ConfNode *conf,
+ const char *query_key, const char *answer_key,
+ const char *answer_types_key)
{
- dnslog_ctx->flags = ~0UL;
+ const char *query = ConfNodeLookupChildValue(conf, query_key);
+ if (query != NULL) {
+ if (ConfValIsTrue(query)) {
+ dnslog_ctx->flags |= LOG_QUERIES;
+ } else {
+ dnslog_ctx->flags &= ~LOG_QUERIES;
+ }
+ } else {
+ if (dnslog_ctx->version == DNS_VERSION_2) {
+ dnslog_ctx->flags |= LOG_QUERIES;
+ }
+ }
- if (conf) {
- const char *query = ConfNodeLookupChildValue(conf, "query");
- if (query != NULL) {
- if (ConfValIsTrue(query)) {
- dnslog_ctx->flags |= LOG_QUERIES;
- } else {
- dnslog_ctx->flags &= ~LOG_QUERIES;
- }
+ const char *response = ConfNodeLookupChildValue(conf, answer_key);
+ if (response != NULL) {
+ if (ConfValIsTrue(response)) {
+ dnslog_ctx->flags |= LOG_ANSWERS;
+ } else {
+ dnslog_ctx->flags &= ~LOG_ANSWERS;
}
- const char *response = ConfNodeLookupChildValue(conf, "answer");
- if (response != NULL) {
- if (ConfValIsTrue(response)) {
- dnslog_ctx->flags |= LOG_ANSWERS;
- } else {
- dnslog_ctx->flags &= ~LOG_ANSWERS;
- }
+ } else {
+ if (dnslog_ctx->version == DNS_VERSION_2) {
+ dnslog_ctx->flags |= LOG_ANSWERS;
}
- ConfNode *custom;
- if ((custom = ConfNodeLookupChild(conf, "custom")) != NULL) {
- dnslog_ctx->flags &= ~LOG_ALL_RRTYPES;
- ConfNode *field;
- TAILQ_FOREACH(field, &custom->head, next)
+ }
+
+ ConfNode *custom;
+ if ((custom = ConfNodeLookupChild(conf, answer_types_key)) != NULL) {
+ dnslog_ctx->flags &= ~LOG_ALL_RRTYPES;
+ ConfNode *field;
+ TAILQ_FOREACH(field, &custom->head, next)
+ {
+ if (field != NULL)
{
- if (field != NULL)
+ DnsRRTypes f;
+ for (f = DNS_RRTYPE_A; f < DNS_RRTYPE_MAX; f++)
{
- DnsRRTypes f;
- for (f = DNS_RRTYPE_A; f < DNS_RRTYPE_MAX; f++)
+ if (strcasecmp(dns_rrtype_fields[f].config_rrtype,
+ field->val) == 0)
{
- if (strcasecmp(dns_rrtype_fields[f].config_rrtype,
- field->val) == 0)
- {
- dnslog_ctx->flags |= dns_rrtype_fields[f].flags;
- break;
- }
+ dnslog_ctx->flags |= dns_rrtype_fields[f].flags;
+ break;
}
}
}
}
+ } else {
+ if (dnslog_ctx->version == DNS_VERSION_2) {
+ dnslog_ctx->flags |= LOG_ALL_RRTYPES;
+ }
+ }
+}
+
+static void JsonDnsLogInitFilters(LogDnsFileCtx *dnslog_ctx, ConfNode *conf)
+{
+ dnslog_ctx->flags = ~0UL;
+
+ if (conf) {
+ intmax_t version;
+ int ret = ConfGetChildValueInt(conf, "version", &version);
+ if (ret) {
+ switch(version) {
+ case 1:
+ dnslog_ctx->version = DNS_VERSION_1;
+ break;
+ case 2:
+ dnslog_ctx->version = DNS_VERSION_2;
+ break;
+ default:
+ SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+ "Invalid version option: %ji, "
+ "forcing it to version 1", version);
+ dnslog_ctx->version = DNS_VERSION_1;
+ break;
+ }
+ } else {
+ SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+ "Version not found, forcing it to version 1");
+ dnslog_ctx->version = DNS_VERSION_1;
+ }
+
+ if (dnslog_ctx->version == DNS_VERSION_1) {
+ JsonDnsLogParseConfig(dnslog_ctx, conf, "query", "answer", "custom");
+ } else {
+ JsonDnsLogParseConfig(dnslog_ctx, conf, "requests", "responses", "types");
+ }
}
}
static OutputInitResult JsonDnsLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx)
{
OutputInitResult result = { NULL, false };
+ const char *enabled = ConfNodeLookupChildValue(conf, "enabled");
+ if (enabled != NULL && !ConfValIsTrue(enabled)) {
+ return result;
+ }
+
OutputJsonCtx *ojc = parent_ctx->data;
LogDnsFileCtx *dnslog_ctx = SCMalloc(sizeof(LogDnsFileCtx));
static OutputInitResult JsonDnsLogInitCtx(ConfNode *conf)
{
OutputInitResult result = { NULL, false };
+ const char *enabled = ConfNodeLookupChildValue(conf, "enabled");
+ if (enabled != NULL && !ConfValIsTrue(enabled)) {
+ return result;
+ }
+
LogFileCtx *file_ctx = LogFileNewCtx();
if(file_ctx == NULL) {
# the example below adds three additional fields when uncommented
#custom: [Accept-Encoding, Accept-Language, Authorization]
- dns:
- # control logging of queries and answers
- # default yes, no to disable
- query: yes # enable logging of DNS queries
- answer: yes # enable logging of DNS answers
- # control which RR types are logged
- # all enabled if custom not specified
- #custom: [a, aaaa, cname, mx, ns, ptr, txt]
+ # This configuration uses the new DNS logging format,
+ # the old configuration is still available:
+ # http://suricata.readthedocs.io/en/latest/configuration/suricata-yaml.html#eve-extensible-event-format
+ # Use version 2 logging with the new format:
+ # dns answers will be logged in one single event
+ # rather than an event for each of it.
+ # Without setting a version the version
+ # will fallback to 1 for backwards compatibility.
+ version: 2
+
+ # Enable/disable this logger. Default: enabled.
+ #enabled: no
+
+ # Control logging of requests and responses:
+ # - requests: enable logging of DNS queries
+ # - responses: enable logging of DNS answers
+ # By default both requests and responses are logged.
+ #requests: no
+ #responses: no
+
+ # Format of answer logging:
+ # - detailed: array item per answer
+ # - grouped: answers aggregated by type
+ # Default: all
+ #formats: [detailed, grouped]
+
+ # Answer types to log.
+ # Default: all
+ #types: [a, aaaa, cname, mx, ns, ptr, txt]
- tls:
extended: yes # enable this for extended logging information
# output TLS transaction where the session is resumed using a