>From 40606056820f4abb2840e8f505918d621f807351 Mon Sep 17 00:00:00 2001
From: Balint Kovacs <blint@balabit.hu>
Date: Mon, 3 Jan 2011 02:15:19 +0100
Subject: [PATCH] afmongodb: added support for inserting all dynamic values within the log message with the tags(auto_nvpairs) option

---
 lib/nvtable.c                          |   30 +++++++++++++++++++++++
 lib/nvtable.h                          |    2 +
 modules/afmongodb/afmongodb-grammar.ym |    8 ++++++
 modules/afmongodb/afmongodb-parser.c   |    1 +
 modules/afmongodb/afmongodb.c          |   41 ++++++++++++++++++++++++++++++++
 5 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/lib/nvtable.c b/lib/nvtable.c
index 6c5b602..30db7ed 100644
--- a/lib/nvtable.c
+++ b/lib/nvtable.c
@@ -578,6 +578,14 @@ nv_table_foreach(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, g
 }
 
 gboolean
+nv_table_foreach_dynamic(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, gpointer user_data)
+{
+  gpointer data[4] = { self, registry, func, user_data };
+
+  return nv_table_foreach_dynentry(self, nv_table_call_foreach, data);
+}
+
+gboolean
 nv_table_foreach_entry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data)
 {
   guint32 *dyn_entries;
@@ -609,6 +617,28 @@ nv_table_foreach_entry(NVTable *self, NVTableForeachEntryFunc func, gpointer use
   return FALSE;
 }
 
+gboolean
+nv_table_foreach_dynentry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data)
+{
+  guint32 *dyn_entries;
+  NVEntry *entry;
+  gint i;
+
+  dyn_entries = nv_table_get_dyn_entries(self);
+  for (i = 0; i < self->num_dyn_entries; i++)
+    {
+      entry = nv_table_get_entry_at_ofs(self, NV_TABLE_DYNVALUE_OFS(dyn_entries[i]));
+
+      if (!entry)
+        continue;
+
+      if (func(NV_TABLE_DYNVALUE_HANDLE(dyn_entries[i]), entry, user_data))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 void
 nv_table_clear(NVTable *self)
 {
diff --git a/lib/nvtable.h b/lib/nvtable.h
index 6024f97..9deeb4d 100644
--- a/lib/nvtable.h
+++ b/lib/nvtable.h
@@ -185,7 +185,9 @@ gboolean nv_table_add_value(NVTable *self, NVHandle handle, const gchar *name, g
 gboolean nv_table_add_value_indirect(NVTable *self, NVHandle handle, const gchar *name, gsize name_len, NVHandle ref_handle, guint8 type, guint16 ofs, guint16 len, gboolean *new_entry);
 
 gboolean nv_table_foreach(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, gpointer user_data);
+gboolean nv_table_foreach_dynamic(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, gpointer user_data);
 gboolean nv_table_foreach_entry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data);
+gboolean nv_table_foreach_dynentry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data);
 
 void nv_table_clear(NVTable *self);
 NVTable *nv_table_new(gint num_static_values, gint num_dyn_values, gint init_length);
diff --git a/modules/afmongodb/afmongodb-grammar.ym b/modules/afmongodb/afmongodb-grammar.ym
index c7a291b..2508562 100644
--- a/modules/afmongodb/afmongodb-grammar.ym
+++ b/modules/afmongodb/afmongodb-grammar.ym
@@ -45,6 +45,7 @@
 %token KW_MONGODB
 %token KW_COLLECTION
 %token KW_KEYS
+%type   <num> dest_afmongodb_flags
 
 %%
 
@@ -70,8 +71,15 @@ afmongodb_option
 	| KW_KEYS '(' string_list ')'		{ afmongodb_dd_set_keys((*afmongodb_dd_instance), $3); }
 	| KW_USERNAME '(' string ')'		{ afmongodb_dd_set_user((*afmongodb_dd_instance), $3); free($3); }
 	| KW_PASSWORD '(' string ')'		{ afmongodb_dd_set_password((*afmongodb_dd_instance), $3); free($3); }
+        | KW_FLAGS '(' dest_afmongodb_flags ')' { afmongodb_dd_set_flags((*afmongodb_dd_instance), $3); }
         ;
 
+dest_afmongodb_flags
+        : string dest_afmongodb_flags           { $$ = afmongodb_dd_lookup_flag($1) | $2; free($1); }
+        |                                       { $$ = 0; }
+        ;
+
+
 /* INCLUDE_RULES */
 
 %%
diff --git a/modules/afmongodb/afmongodb-parser.c b/modules/afmongodb/afmongodb-parser.c
index e7b8c64..f2fb3c5 100644
--- a/modules/afmongodb/afmongodb-parser.c
+++ b/modules/afmongodb/afmongodb-parser.c
@@ -38,6 +38,7 @@ static CfgLexerKeyword afmongodb_keywords[] = {
   { "values",			KW_VALUES },
   { "username",			KW_USERNAME },
   { "password",			KW_PASSWORD },
+  { "flags",                    KW_FLAGS },
   { NULL }
 };
 
diff --git a/modules/afmongodb/afmongodb.c b/modules/afmongodb/afmongodb.c
index ede5b86..9fe64d0 100644
--- a/modules/afmongodb/afmongodb.c
+++ b/modules/afmongodb/afmongodb.c
@@ -29,6 +29,7 @@
 #include "messages.h"
 #include "misc.h"
 #include "stats.h"
+#include "nvtable.h"
 
 #include "bson.h"
 #include "mongo.h"
@@ -40,6 +41,8 @@ typedef struct
   LogTemplate *value;
 } MongoDBField;
 
+#define AFMONGODB_DDF_AUTO_NVPAIRS   0x0001
+
 typedef struct
 {
   LogDriver super;
@@ -52,6 +55,7 @@ typedef struct
 
   GList *keys;
   GList *values;
+  gint  flags;
 
   gint num_fields;
   MongoDBField *fields;
@@ -140,6 +144,14 @@ afmongodb_dd_set_values(LogDriver *d, GList *values)
   self->values = values;
 }
 
+void
+afmongodb_dd_set_flags(LogDriver *s, gint flags)
+{
+  MongoDBDestDriver *self = (MongoDBDestDriver *) s;
+
+  self->flags = flags;
+}
+
 /*
  * Init, shutdown & queue
  */
@@ -301,6 +313,17 @@ afmongodb_dd_free(LogPipe *d)
   log_drv_free(d);
 }
 
+gboolean
+afmongodb_dd_set_autovalues(NVHandle handle, const gchar *name, const gchar *value, gssize length, gpointer user_data)
+{
+  if (value)
+    {
+      msg_debug("Addig name-value pair", evt_tag_str("name", name), NULL);
+      bson_append_string(user_data, name, value);
+    }
+  return FALSE;
+}
+
 static void
 afmongodb_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options)
 {
@@ -346,6 +369,12 @@ afmongodb_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_optio
 	bson_append_string(&buf, self->fields[i].name, value->str);
     }
 
+  if (self->flags & AFMONGODB_DDF_AUTO_NVPAIRS)
+    {
+      msg_debug("Flag auto_nvpairs specified, iterating over dynamic values", NULL);
+      nv_table_foreach_dynamic(msg->payload, logmsg_registry, afmongodb_dd_set_autovalues, &buf);
+    }
+
   bson_from_buffer(&b, &buf);
 
   MONGO_TRY_GENERIC(&self->mongo_conn)
@@ -439,6 +468,18 @@ afmongodb_dd_new(void)
 
 extern CfgParser afmongodb_dd_parser;
 
+gint
+afmongodb_dd_lookup_flag(const gchar *flag)
+{
+  if (strcmp(flag, "auto_nvpairs") == 0)
+    return AFMONGODB_DDF_AUTO_NVPAIRS;
+  else
+    msg_warning("Unknown MongoDB flag",
+                evt_tag_str("flag", flag),
+                NULL);
+  return 0;
+}
+
 static Plugin afmongodb_plugin =
 {
   .type = LL_CONTEXT_DESTINATION,
-- 
1.7.1


