[PATCH (3.4)] value-pairs: Implement key transformation functions.
This is the implementation of the rekey() mechanism, a way to transform the keys of a value-pairs() set. The intended usage is as follows: value-pairs( scope("everything") rekey( shift(".sdata.*" 1) add-prefix(".classification.*" "syslog-ng") replace("." "_") ) ); This would transform keys beginning with ".sdata." by shifting them one char, getting rid of the dot. Then it would add a "syslog-ng" prefix to every key that begins with ".classification.", so ".classification.rule_id" would become "syslog-ng.classification.rule_id". Finally, it will replace the leading dot with an underscore on all remaining keys. Whenever he value-pairs stuff puts a key into the final set, it will pipe them through the list of registered transformations. Each transformator needs to have a ->match method, which determines whether a given key should be transformed or not. If it should be, then the key will be given to the ->transform function, and the result will be used as the key, whatever it may be. Once all keys are inserted, the ->reset function will be called, if it exists. And when the value-pairs object is deinitializing, that will call the transformators' ->destroy function aswell. These functions are mandatory (except for reset), and they're part of the ValuePairsTransform struct. All transform functions derive from this one, and extend it with their own state variables. Currently, three transformation functions exist: the three mentioned in the example above. shift() will take a string and an integer, and shift the string by the given amount of characters (if the amount is 0 or negative, it will just return the original). add-prefix() will prepend a prefix. And replace() will replace the given string with another, but only if the key begins with the original string-part. It will not replace patterns inside the key name, only at the beginning. Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- lib/Makefile.am | 4 +- lib/cfg-grammar.y | 17 +++ lib/cfg-parser.c | 4 + lib/value-pairs.c | 56 ++++++++- lib/value-pairs.h | 2 + lib/vptransform.c | 292 +++++++++++++++++++++++++++++++++++++++++ lib/vptransform.h | 40 ++++++ tests/unit/test_value_pairs.c | 44 +++++-- 8 files changed, 443 insertions(+), 16 deletions(-) create mode 100644 lib/vptransform.c create mode 100644 lib/vptransform.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 26c9461..1a95fc2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -77,7 +77,8 @@ pkginclude_HEADERS = \ tlscontext.h \ tlstransport.h \ utils.h \ - value-pairs.h + value-pairs.h \ + vptransform.h # this is intentionally formatted so conflicts are less likely to arise. one name in every line. libsyslog_ng_la_SOURCES = \ @@ -137,6 +138,7 @@ libsyslog_ng_la_SOURCES = \ timeutils.c \ utils.c \ value-pairs.c \ + vptransform.c \ \ cfg-lex.l \ cfg-grammar.y \ diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y index 994713e..5f032d5 100644 --- a/lib/cfg-grammar.y +++ b/lib/cfg-grammar.y @@ -276,6 +276,10 @@ %token KW_PAIR 10503 %token KW_KEY 10504 %token KW_SCOPE 10505 +%token KW_SHIFT 10506 +%token KW_REKEY 10507 +%token KW_ADD_PREFIX 10508 +%token KW_REPLACE 10509 /* END_DECLS */ @@ -851,6 +855,7 @@ vp_option } | KW_EXCLUDE '(' string ')' { value_pairs_add_exclude_glob(last_value_pairs, $3); free($3); } | KW_SCOPE '(' vp_scope_list ')' + | KW_REKEY '(' vp_rekey_options ')' ; vp_scope_list @@ -858,6 +863,18 @@ vp_scope_list | ; +vp_rekey_options + : vp_rekey_option vp_rekey_options + | + ; + +vp_rekey_option + : KW_SHIFT '(' string LL_NUMBER ')' { value_pairs_add_transform(last_value_pairs, value_pairs_new_transform_shift($3, $4)); free($3); } + | KW_SHIFT '(' string ':' LL_NUMBER ')' { value_pairs_add_transform(last_value_pairs, value_pairs_new_transform_shift($3, $5)); free($3); } + | KW_ADD_PREFIX '(' string string ')' { value_pairs_add_transform(last_value_pairs, value_pairs_new_transform_add_prefix($3, $4)); free($3); free($4); } + | KW_REPLACE '(' string string ')' { value_pairs_add_transform(last_value_pairs, value_pairs_new_transform_replace($3, $4)); free($3); free($4); } + ; + /* END_RULES */ diff --git a/lib/cfg-parser.c b/lib/cfg-parser.c index 589206a..bd5c76d 100644 --- a/lib/cfg-parser.c +++ b/lib/cfg-parser.c @@ -60,6 +60,10 @@ static CfgLexerKeyword main_keywords[] = { { "pair", KW_PAIR, 0x0303 }, { "key", KW_KEY, 0x0303 }, { "scope", KW_SCOPE, 0x0303 }, + { "rekey", KW_REKEY, 0x0303 }, + { "shift", KW_SHIFT, 0x0303 }, + { "add_prefix", KW_ADD_PREFIX, 0x0303 }, + { "replace", KW_REPLACE, 0x0303 }, /* option items */ { "flags", KW_FLAGS }, diff --git a/lib/value-pairs.c b/lib/value-pairs.c index 484cb58..4f4ddc5 100644 --- a/lib/value-pairs.c +++ b/lib/value-pairs.c @@ -23,6 +23,7 @@ */ #include "value-pairs.h" +#include "vptransform.h" #include "logmsg.h" #include "templates.h" #include "cfg-parser.h" @@ -30,11 +31,11 @@ #include <string.h> - struct _ValuePairs { GPatternSpec **excludes; GHashTable *vpairs; + GList *transforms; /* guint32 as CfgFlagHandler only supports 32 bit integers */ guint32 scopes; @@ -141,6 +142,26 @@ value_pairs_add_pair(ValuePairs *vp, GlobalConfig *cfg, const gchar *key, const g_hash_table_insert(vp->vpairs, g_strdup(key), t); } +static gchar * +vp_transform_apply (ValuePairs *vp, gchar *key) +{ + GList *l; + gchar *ckey = key; + + if (!vp->transforms) + return ckey; + + l = vp->transforms; + while (l) + { + ValuePairsTransform *t = (ValuePairsTransform *)l->data; + ckey = value_pairs_transform_apply(t, ckey); + l = g_list_next (l); + } + + return ckey; +} + /* runs over the name-value pairs requested by the user (e.g. with value_pairs_add_pair) */ static void vp_pairs_foreach(gpointer key, gpointer value, gpointer user_data) @@ -157,7 +178,7 @@ vp_pairs_foreach(gpointer key, gpointer value, gpointer user_data) if (!vp->res->str[0]) return; - g_hash_table_insert(scope_set, key, vp->res->str); + g_hash_table_insert(scope_set, vp_transform_apply (vp, key), vp->res->str); g_string_steal(vp->res); } @@ -183,7 +204,7 @@ vp_msg_nvpairs_foreach(NVHandle handle, gchar *name, } /* NOTE: the key is a borrowed reference in the hash, and value is freed */ - g_hash_table_insert(scope_set, name, g_strndup(value, value_len)); + g_hash_table_insert(scope_set, vp_transform_apply(vp, name), g_strndup(value, value_len)); } return FALSE; @@ -231,7 +252,7 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32 seq_num, ValuePairSpec *set if (!vp->res->str[0]) continue; - g_hash_table_insert(dest, set[i].name, vp->res->str); + g_hash_table_insert(dest, vp_transform_apply(vp, set[i].name), vp->res->str); g_string_steal(vp->res); } } @@ -274,6 +295,17 @@ value_pairs_foreach (ValuePairs *vp, VPForeachFunc func, g_hash_table_foreach(scope_set, (GHFunc)func, user_data); g_hash_table_destroy(scope_set); + + if (vp->transforms) + { + GList *l = vp->transforms; + + do + { + value_pairs_transform_reset((ValuePairsTransform *)l->data); + } + while ((l = g_list_next (l)) != NULL); + } } @@ -349,6 +381,7 @@ void value_pairs_free (ValuePairs *vp) { gint i; + GList *l; g_hash_table_destroy(vp->vpairs); @@ -356,9 +389,24 @@ value_pairs_free (ValuePairs *vp) g_pattern_spec_free(vp->excludes[i]); g_free(vp->excludes); g_string_free(vp->res, TRUE); + + l = vp->transforms; + while (l) + { + value_pairs_transform_free((ValuePairsTransform *)l->data); + + l = g_list_delete_link (l, l); + } + g_free(vp); } +void +value_pairs_add_transform(ValuePairs *vp, gpointer *vpt) +{ + vp->transforms = g_list_append(vp->transforms, vpt); +} + /* parse a value-pair specification from a command-line like environment */ static gboolean vp_cmdline_parse_scope(const gchar *option_name, const gchar *value, diff --git a/lib/value-pairs.h b/lib/value-pairs.h index da26763..0a10423 100644 --- a/lib/value-pairs.h +++ b/lib/value-pairs.h @@ -35,6 +35,8 @@ gboolean value_pairs_add_scope(ValuePairs *vp, const gchar *scope); void value_pairs_add_exclude_glob(ValuePairs *vp, const gchar *pattern); void value_pairs_add_pair(ValuePairs *vp, GlobalConfig *cfg, const gchar *key, const gchar *value); +void value_pairs_add_transform(ValuePairs *vp, gpointer *vpt); + void value_pairs_foreach(ValuePairs *vp, VPForeachFunc func, LogMessage *msg, gint32 seq_num, gpointer user_data); diff --git a/lib/vptransform.c b/lib/vptransform.c new file mode 100644 index 0000000..1309092 --- /dev/null +++ b/lib/vptransform.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2002-2011 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011 Gergely Nagy <algernon@balabit.hu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#include "value-pairs.h" +#include "vptransform.h" +#include "templates.h" +#include "cfg-parser.h" +#include "misc.h" + +#include <string.h> + +typedef gboolean (*VPTransMatchFunc)(ValuePairsTransform *t, gchar *name); +typedef gchar *(*VPTransFunc)(ValuePairsTransform *t, gchar *name); +typedef void (*VPTransResetFunc)(ValuePairsTransform *t); +typedef void (*VPTransDestroyFunc)(ValuePairsTransform *t); + +struct _ValuePairsTransform +{ + VPTransMatchFunc match; + VPTransFunc transform; + VPTransResetFunc reset; + VPTransDestroyFunc destroy; +}; + +typedef struct +{ + ValuePairsTransform super; + + GPatternSpec *pattern; + gint amount; +} VPTransShift; + +typedef struct +{ + ValuePairsTransform super; + + GPatternSpec *pattern; + gchar *prefix; + + GHashTable *cache; +} VPTransAddPrefix; + +typedef struct +{ + ValuePairsTransform super; + + gchar *old_prefix; + gchar *new_prefix; + gint new_prefix_len; + gint old_prefix_len; + + GHashTable *cache; +} VPTransReplace; + +static void +vp_trans_init(ValuePairsTransform *t, + VPTransMatchFunc match, VPTransFunc trans, + VPTransResetFunc reset, VPTransDestroyFunc dest) +{ + if (!t) + return; + + t->match = match; + t->transform = trans; + t->reset = reset; + t->destroy = dest; +} + +void +value_pairs_transform_reset(ValuePairsTransform *t) +{ + if (t->reset) + t->reset(t); +} + +void +value_pairs_transform_free(ValuePairsTransform *t) +{ + if (t->destroy) + t->destroy(t); + g_free(t); +} + +gchar * +value_pairs_transform_apply(ValuePairsTransform *t, gchar *key) +{ + if (t->match(t, key)) + return t->transform(t, key); + return key; +} + +/* add_prefix() */ + +static gchar * +vp_trans_add_prefix(ValuePairsTransform *t, gchar *name) +{ + VPTransAddPrefix *self = (VPTransAddPrefix *)t; + gpointer r; + + r = g_hash_table_lookup(self->cache, name); + if (!r) + { + r = (gpointer)g_strconcat(self->prefix, name, NULL); + g_hash_table_insert(self->cache, g_strdup(name), r); + } + return r; +} + +static void +vp_trans_add_prefix_destroy(ValuePairsTransform *t) +{ + VPTransAddPrefix *self = (VPTransAddPrefix *)t; + + g_pattern_spec_free(self->pattern); + g_hash_table_destroy(self->cache); + g_free(self->prefix); +} + +static gboolean +vp_trans_add_prefix_match(ValuePairsTransform *t, gchar *key) +{ + VPTransAddPrefix *self = (VPTransAddPrefix *)t; + + return g_pattern_match_string(self->pattern, key); +} + +static void +vp_trans_add_prefix_reset(ValuePairsTransform *t) +{ + VPTransAddPrefix *self = (VPTransAddPrefix *)t; + + if (self->cache) + g_hash_table_destroy(self->cache); + + self->cache = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); +} + +ValuePairsTransform * +value_pairs_new_transform_add_prefix (const gchar *glob, const gchar *prefix) +{ + VPTransAddPrefix *vpt; + + vpt = g_new(VPTransAddPrefix, 1); + vp_trans_init((ValuePairsTransform *)vpt, + vp_trans_add_prefix_match, vp_trans_add_prefix, + vp_trans_add_prefix_reset, vp_trans_add_prefix_destroy); + vpt->pattern = g_pattern_spec_new(glob); + vpt->prefix = g_strdup(prefix); + vpt->cache = NULL; + + vp_trans_add_prefix_reset((ValuePairsTransform *)vpt); + + return (ValuePairsTransform *)vpt; +} + +/* shift() */ + +static gchar * +vp_trans_shift(ValuePairsTransform *t, gchar* name) +{ + VPTransShift *self = (VPTransShift *)t; + + if (self->amount <= 0) + return name; + return name + self->amount; +} + +static void +vp_trans_shift_destroy(ValuePairsTransform *t) +{ + VPTransShift *self = (VPTransShift *)t; + + g_pattern_spec_free(self->pattern); +} + +static gboolean +vp_trans_shift_match(ValuePairsTransform *t, gchar *key) +{ + VPTransShift *self = (VPTransShift *)t; + + return g_pattern_match_string(self->pattern, key); +} + +ValuePairsTransform * +value_pairs_new_transform_shift (const gchar *glob, gint amount) +{ + VPTransShift *vpt; + + vpt = g_new(VPTransShift, 1); + vp_trans_init((ValuePairsTransform *)vpt, + vp_trans_shift_match, vp_trans_shift, + NULL, vp_trans_shift_destroy); + + vpt->pattern = g_pattern_spec_new(glob); + vpt->amount = amount; + + return (ValuePairsTransform *)vpt; +} + +/* replace() */ + +static gchar * +vp_trans_replace(ValuePairsTransform *t, gchar *name) +{ + VPTransReplace *self = (VPTransReplace *)t; + gpointer r; + + r = g_hash_table_lookup(self->cache, name); + if (!r) + { + r = g_malloc(strlen(name) - self->old_prefix_len + self->new_prefix_len + 1); + + memcpy (r, self->new_prefix, self->new_prefix_len); + memcpy (r + self->new_prefix_len, name + self->old_prefix_len, + strlen(name) - self->old_prefix_len + 1); + g_hash_table_insert(self->cache, g_strdup(name), r); + } + return r; +} + +static void +vp_trans_replace_destroy(ValuePairsTransform *t) +{ + VPTransReplace *self = (VPTransReplace *)t; + + g_hash_table_destroy(self->cache); + g_free(self->old_prefix); + g_free(self->new_prefix); +} + +static void +vp_trans_replace_reset(ValuePairsTransform *t) +{ + VPTransReplace *self = (VPTransReplace *)t; + + if (self->cache) + g_hash_table_destroy(self->cache); + self->cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); +} + +static gboolean +vp_trans_replace_match(ValuePairsTransform *t, gchar *key) +{ + VPTransReplace *self = (VPTransReplace *)t; + + if (strncmp (self->old_prefix, key, self->old_prefix_len) == 0) + return TRUE; + return FALSE; +} + +ValuePairsTransform * +value_pairs_new_transform_replace(const gchar *prefix, const gchar *new_prefix) +{ + VPTransReplace *vpt; + + vpt = g_new(VPTransReplace, 1); + vp_trans_init((ValuePairsTransform *)vpt, + vp_trans_replace_match, vp_trans_replace, + vp_trans_replace_reset, vp_trans_replace_destroy); + + vpt->old_prefix = g_strdup(prefix); + vpt->old_prefix_len = strlen(prefix); + vpt->new_prefix = g_strdup(new_prefix); + vpt->new_prefix_len = strlen(vpt->new_prefix); + vpt->cache = NULL; + + vp_trans_replace_reset ((ValuePairsTransform *)vpt); + + return (ValuePairsTransform *)vpt; +} diff --git a/lib/vptransform.h b/lib/vptransform.h new file mode 100644 index 0000000..6ede457 --- /dev/null +++ b/lib/vptransform.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2011 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011 Gergely Nagy <algernon@balabit.hu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As an additional exemption you are allowed to compile & link against the + * OpenSSL libraries as published by the OpenSSL project. See the file + * COPYING for details. + * + */ + +#ifndef VPTRANSFORM_INCLUDED +#define VPTRANSFORM_INCLUDED 1 + +#include "value-pairs.h" + +typedef struct _ValuePairsTransform ValuePairsTransform; + +ValuePairsTransform *value_pairs_new_transform_add_prefix (const gchar *glob, const gchar *prefix); +ValuePairsTransform *value_pairs_new_transform_shift (const gchar *glob, gint amount); +ValuePairsTransform *value_pairs_new_transform_replace(const gchar *prefix, const gchar *new_prefix); + +void value_pairs_transform_free(ValuePairsTransform *t); +gchar *value_pairs_transform_apply(ValuePairsTransform *t, gchar *key); +void value_pairs_transform_reset(ValuePairsTransform *t); + +#endif diff --git a/tests/unit/test_value_pairs.c b/tests/unit/test_value_pairs.c index 67f933a..aeb1f32 100644 --- a/tests/unit/test_value_pairs.c +++ b/tests/unit/test_value_pairs.c @@ -1,4 +1,5 @@ #include "value-pairs.h" +#include "vptransform.h" #include "logmsg.h" #include "apphook.h" #include "cfg.h" @@ -46,7 +47,7 @@ create_message(void) } void -testcase(const gchar *scope, const gchar *exclude, const gchar *expected) +testcase(const gchar *scope, const gchar *exclude, const gchar *expected, GPtrArray *transformers) { ValuePairs *vp; GList *vp_keys_list = NULL; @@ -63,6 +64,14 @@ testcase(const gchar *scope, const gchar *exclude, const gchar *expected) value_pairs_add_exclude_glob(vp, exclude); value_pairs_add_pair(vp, configuration, "test.key", "$MESSAGE"); + if (transformers) + { + gint i; + + for (i = 0; i < transformers->len; i++) + value_pairs_add_transform(vp, g_ptr_array_index(transformers, i)); + } + args[0] = &vp_keys_list; args[1] = &test_key_found; value_pairs_foreach(vp, vp_keys_foreach, msg, 11, args); @@ -88,6 +97,8 @@ testcase(const gchar *scope, const gchar *exclude, const gchar *expected) int main(int argc, char *argv[]) { + GPtrArray *transformers; + app_startup(); putenv("TZ=MET-1METDST"); tzset(); @@ -98,26 +109,37 @@ main(int argc, char *argv[]) msg_format_options_init(&parse_options, configuration); parse_options.flags |= LP_SYSLOG_PROTOCOL; - testcase("rfc3164", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM"); - testcase("rfc5424", NULL, "DATE,FACILITY,HOST,MESSAGE,MSGID,PID,PRIORITY,PROGRAM"); - testcase("selected-macros", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM,SEQNUM,SOURCEIP,TAGS"); + testcase("rfc3164", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); + testcase("rfc5424", NULL, "DATE,FACILITY,HOST,MESSAGE,MSGID,PID,PRIORITY,PROGRAM", NULL); + testcase("selected-macros", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM,SEQNUM,SOURCEIP,TAGS", NULL); - testcase("nv-pairs", NULL, "HOST,MESSAGE,MSGID,PID,PROGRAM"); - testcase("dot-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip"); + testcase("nv-pairs", NULL, "HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); + testcase("dot-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip", NULL); - testcase("sdata", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip"); + testcase("sdata", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip", NULL); - testcase("all-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,HOST,MESSAGE,MSGID,PID,PROGRAM"); + testcase("all-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); - testcase("everything", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,BSDTAG,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY"); + testcase("everything", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,BSDTAG,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY", NULL); - testcase("nv-pairs", ".SDATA.*", "HOST,MESSAGE,MSGID,PID,PROGRAM"); + testcase("nv-pairs", ".SDATA.*", "HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); /* tests that the exclude patterns do not affect explicitly added * keys. The testcase function adds a "test.key" and then checks if * it is indeed present. Even if it would be excluded it still has * to be in the result set. */ - testcase("rfc3164", "test.*", "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM"); + testcase("rfc3164", "test.*", "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); + + /* test the value-pair transformators */ + transformers = g_ptr_array_new(); + g_ptr_array_add(transformers, value_pairs_new_transform_add_prefix("S_*", "__")); + g_ptr_array_add(transformers, value_pairs_new_transform_shift("__*", 2)); + g_ptr_array_add(transformers, value_pairs_new_transform_replace("S_", "_PRIV_SOURCE_")); + g_ptr_array_add(transformers, value_pairs_new_transform_replace("R_", "_PRIV_REMOTE_")); + + testcase("everything", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,BSDTAG,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY,_PRIV_REMOTE_DATE,_PRIV_REMOTE_DAY,_PRIV_REMOTE_FULLDATE,_PRIV_REMOTE_HOUR,_PRIV_REMOTE_ISODATE,_PRIV_REMOTE_MIN,_PRIV_REMOTE_MONTH,_PRIV_REMOTE_MONTH_ABBREV,_PRIV_REMOTE_MONTH_NAME,_PRIV_REMOTE_MONTH_WEEK,_PRIV_REMOTE_SEC,_PRIV_REMOTE_STAMP,_PRIV_REMOTE_TZ,_PRIV_REMOTE_TZOFFSET,_PRIV_REMOTE_UNIXTIME,_PRIV_REMOTE_WEEK,_PRIV_REMOTE_WEEKDAY,_PRIV_REMOTE_WEEK_DAY,_PRIV_REMOTE_WEEK_DAY_ABBREV,_PRIV_REMOTE_WEEK_DAY_NAME,_PRIV_REMOTE_YEAR,_PRIV_REMOTE_YEAR_DAY,_PRIV_SOURCE_DATE,_PRIV_SOURCE_DAY,_PRIV_SOURCE_FULLDATE,_PRIV _SOURCE_HOUR,_PRIV_SOURCE_ISODATE,_PRIV_SOURCE_MIN,_PRIV_SOURCE_MONTH,_PRIV_SOURCE_MONTH_ABBREV,_PRIV_SOURCE_MONTH_NAME,_PRIV_SOURCE_MONTH_WEEK,_PRIV_SOURCE_SEC,_PRIV_SOURCE_STAMP,_PRIV_SOURCE_TZ,_PRIV_SOURCE_TZOFFSET,_PRIV_SOURCE_UNIXTIME,_PRIV_SOURCE_WEEK,_PRIV_SOURCE_WEEKDAY,_PRIV_SOURCE_WEEK_DAY,_PRIV_SOURCE_WEEK_DAY_ABBREV,_PRIV_SOURCE_WEEK_DAY_NAME,_PRIV_SOURCE_YEAR,_PRIV_SOURCE_YEAR_DAY", transformers); + + g_ptr_array_free(transformers, FALSE); app_shutdown(); if (success) -- 1.7.0.4
Gergely Nagy <algernon@balabit.hu> writes:
This is the implementation of the rekey() mechanism, a way to transform the keys of a value-pairs() set. [..snip..]
I'm submitting this because after a few nights of staring at the code, I'm reasonably happy with it, and it has enough features for a review. While I talked about a regexp() transformation function earlier, I decided against it for now, until a need for it arises. PCRE does not have built-in replace functionality, so I'd have to code that myself, which seemed like too much effort for very little gain. The three functions available now are enough for my needs, I can do everything I want with them for now. We can always add more, reasonably easily, if there's demand. The code is available on the integration/value-pairs/rekey branch of my git tree[1] aswell, and also on value-pairs/rekey - the former is a rebase on top of master, pulling all the commits into one big, clean one, while the latter is where development happened, with all the silly design mistakes I made during the process. [1]: git://git.balabit.hu/algernon/syslog-ng-3.4.git -- |8]
participants (1)
-
Gergely Nagy