# HG changeset patch # User Carl Byington # Date 1368811932 25200 # Node ID 400b1de6e1c613bbd37c765343dca5af30cc1ee6 # Parent 964c1127ae652ec0ac68d92c7c013444cd99a349 allow multiple config contexts diff -r 964c1127ae65 -r 400b1de6e1c6 ChangeLog --- a/ChangeLog Wed May 15 13:31:12 2013 -0700 +++ b/ChangeLog Fri May 17 10:32:12 2013 -0700 @@ -1,3 +1,5 @@ +1.1 2013-05-17 + Allow multiple config contexts. + 1.0 2013-05-15 Initial release. - diff -r 964c1127ae65 -r 400b1de6e1c6 NEWS --- a/NEWS Wed May 15 13:31:12 2013 -0700 +++ b/NEWS Fri May 17 10:32:12 2013 -0700 @@ -1,1 +1,2 @@ +1.1 2013-05-17 allow multiple config contexts 1.0 2013-05-15 Initial release. diff -r 964c1127ae65 -r 400b1de6e1c6 configure.in --- a/configure.in Wed May 15 13:31:12 2013 -0700 +++ b/configure.in Fri May 17 10:32:12 2013 -0700 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(wflogs-daemon,1.0,carl@five-ten-sg.com) +AC_INIT(wflogs-daemon,1.1,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h]) diff -r 964c1127ae65 -r 400b1de6e1c6 src/wflogs-config.cpp --- a/src/wflogs-config.cpp Wed May 15 13:31:12 2013 -0700 +++ b/src/wflogs-config.cpp Fri May 17 10:32:12 2013 -0700 @@ -1,6 +1,6 @@ /* -Copyright (c) 2007 Carl Byington - 510 Software Group, released under +Copyright (c) 2013 Carl Byington - 510 Software Group, released under the GPL version 3 or any later version at your choice available at http://www.gnu.org/licenses/gpl-3.0.txt @@ -34,13 +34,11 @@ //////////////////////////////////////////////// // -CONFIG::CONFIG() { - reference_count = 0; +CONTEXT::CONTEXT(const char *nam) { + name = nam; fd = -1; len = 0; fdo = -1; - generation = 0; - load_time = 0; period = 120; versions = 3; output = NULL; @@ -51,25 +49,25 @@ } -CONFIG::~CONFIG() { +CONTEXT::~CONTEXT() { + free_all(); } -void CONFIG::sleep(int duration, time_t &previous) { - ::sleep(duration); - time_t now = time(NULL); - previous = now; +void CONTEXT::dump() { + printf("context %s {\n", name); + printf(" period %d; \n", period); + printf(" versions %d; \n", versions); + printf(" output \"%s\";\n", output); + printf(" tempin \"%s\";\n", tempin); + printf(" wflogs \"%s\";\n", wflogs); + printf(" file \"%s\";\n", fn); + printf(" pattern \"%s\";\n", pattern); + printf("};\n\n"); } -void CONFIG::free_all() { - regfree(&re); - close(); - closeo(); -} - - -void CONFIG::openo(bool msg) { +void CONTEXT::openo(bool msg) { open_time = time(NULL); fdo = ::creat(tempin, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fdo == -1) { @@ -82,7 +80,7 @@ } -void CONFIG::open(bool msg) { +void CONTEXT::open(bool msg) { fd = ::open(fn, O_RDONLY); len = 0; if (fd == -1) { @@ -103,8 +101,8 @@ snprintf(buf, sizeof(buf), "syslog file %s cannot stat after open", fn); tokp->token_error(buf); } - // specify that this fd gets closed on exec, so that selinux - // won't complain about iptables trying to read log files. + // specify that this fd gets closed on exec, so that wflogs + // won't have access to it. int oldflags = fcntl(fd, F_GETFD, 0); if (oldflags >= 0) { fcntl(fd, F_SETFD, oldflags | FD_CLOEXEC); @@ -113,7 +111,7 @@ } -bool CONFIG::write(char *p) { +bool CONTEXT::write(char *p) { // p points to \0 at end of buf, may be destroyed if (failedo()) { openo(false); @@ -124,7 +122,7 @@ } -bool CONFIG::read() { +bool CONTEXT::read() { if (failed()) { open(false); if (failed()) return false; @@ -164,13 +162,13 @@ } -void CONFIG::closeo() { +void CONTEXT::closeo() { if (fdo != -1) ::close(fdo); fdo = -1; } -void CONFIG::close() { +void CONTEXT::close() { if (debug_syslog > 1) { snprintf(buf, sizeof(buf), "syslog file %s closed", fn); my_syslog(buf); @@ -180,7 +178,7 @@ } -void CONFIG::process(char *p) { +void CONTEXT::process(char *p) { // p points to \0 at end of buf, may be destroyed if (pattern) { if (0 == regexec(&re, buf, 0, NULL, 0)) { @@ -193,7 +191,7 @@ } -void CONFIG::check_wflog() { +void CONTEXT::check_wflog() { time_t now = time(NULL); if ((fdo != -1) && (open_time + period < now)) { closeo(); @@ -216,19 +214,58 @@ } +void CONTEXT::free_all() { + regfree(&re); + close(); + closeo(); +} + + +//////////////////////////////////////////////// +// +CONFIG::CONFIG() { + reference_count = 0; + generation = 0; + load_time = 0; +} + + +CONFIG::~CONFIG() { + for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { + CONTEXT *c = *i; + delete c; + } +} + + void CONFIG::dump() { - int level = 0; - char indent[maxlen]; - int i = min(maxlen-1, level*4); - memset(indent, ' ', i); - indent[i] = '\0'; - printf("%s period %d; \n", indent, period); - printf("%s versions %d; \n", indent, versions); - printf("%s output \"%s\";\n", indent, output); - printf("%s tempin \"%s\";\n", indent, tempin); - printf("%s wflogs \"%s\";\n", indent, wflogs); - printf("%s file \"%s\";\n", indent, fn); - printf("%s pattern \"%s\";\n", indent, pattern); + for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { + CONTEXTP c = *i; + c->dump(); + } +} + + +bool CONFIG::read() { + bool rc = false; + for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { + CONTEXT *c = *i; + rc |= c->read(); + } +} + +void CONFIG::sleep(int duration, time_t &previous) { + ::sleep(duration); + time_t now = time(NULL); + previous = now; +} + + +void CONFIG::free_all() { + for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { + CONTEXT *c = *i; + c->free_all(); + } } @@ -283,67 +320,102 @@ //////////////////////////////////////////////// -// parse a config file // -bool load_conf(CONFIG &dc, const char *fn) { - TOKEN tok(fn, &dc.config_files); - dc.set_token(tok); +bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent); +bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent) { + const char *name = tok.next(); + if (!tsa(tok, token_lbrace)) return false; + CONTEXTP con = new CONTEXT(name); + con->set_token(tok); while (true) { const char *have = tok.next(); if (!have) break; + if (have == token_rbrace) break; // done if (have == token_period) { have = tok.next(); - dc.set_period(atoi(have)); + con->set_period(atoi(have)); if (!tsa(tok, token_semi)) return false; } else if (have == token_versions) { have = tok.next(); - dc.set_versions(atoi(have)); + con->set_versions(atoi(have)); if (!tsa(tok, token_semi)) return false; } else if (have == token_output) { - dc.set_output(tok.next()); + con->set_output(tok.next()); if (!tsa(tok, token_semi)) return false; } else if (have == token_tempin) { - dc.set_tempin(tok.next()); + con->set_tempin(tok.next()); if (!tsa(tok, token_semi)) return false; } else if (have == token_wflogs) { - dc.set_wflogs(tok.next()); + con->set_wflogs(tok.next()); if (!tsa(tok, token_semi)) return false; } else if (have == token_file) { - dc.set_file(tok.next()); + con->set_file(tok.next()); if (!tsa(tok, token_semi)) return false; } else if (have == token_pattern) { - dc.pattern = tok.next(); - int rc = regcomp(&dc.re, dc.pattern, REG_ICASE | REG_EXTENDED); + con->pattern = tok.next(); + int rc = regcomp(&con->re, con->pattern, REG_ICASE | REG_EXTENDED); if (rc) { char bu[maxlen]; - regerror(rc, &dc.re, bu, maxlen); + regerror(rc, &con->re, bu, maxlen); char buf[maxlen]; - snprintf(buf, sizeof(buf), "pattern %s not valid - %s", dc.pattern, bu); + snprintf(buf, sizeof(buf), "pattern %s not valid - %s", con->pattern, bu); tok.token_error(buf); - dc.pattern = NULL; + con->pattern = NULL; } if (!tsa(tok, token_semi)) return false; } else { - tok.token_error("statement", have); + tok.token_error("period/versions/output/tempin/wflogs/file/pattern", have); return false; } } + if (!tsa(tok, token_semi)) { + delete con; + return false; + } + dc.add_context(con); return true; } //////////////////////////////////////////////// +// parse a config file +// +bool load_conf(CONFIG &dc, const char *fn) { + int count = 0; + TOKEN tok(fn, &dc.config_files); + while (true) { + const char *have = tok.next(); + if (!have) break; + if (have == token_context) { + if (!parse_context(tok, dc, NULL)) { + tok.token_error("load_conf() failed to parse context"); + return false; + } + else count++; + } + else { + tok.token_error(token_context, have); + return false; + } + } + tok.token_error("load_conf() found %d contexts in %s", count, fn); + return (!dc.contexts.empty()); +} + + +//////////////////////////////////////////////// // init the tokens // void token_init() { + token_context = register_string("context"); token_file = register_string("file"); token_include = register_string("include"); token_lbrace = register_string("{"); diff -r 964c1127ae65 -r 400b1de6e1c6 src/wflogs-config.h --- a/src/wflogs-config.h Wed May 15 13:31:12 2013 -0700 +++ b/src/wflogs-config.h Fri May 17 10:32:12 2013 -0700 @@ -1,6 +1,6 @@ /* -Copyright (c) 2007 Carl Byington - 510 Software Group, released under +Copyright (c) 2013 Carl Byington - 510 Software Group, released under the GPL version 3 or any later version at your choice available at http://www.gnu.org/licenses/gpl-3.0.txt @@ -20,10 +20,9 @@ const int buflen = 1024; -class CONFIG { +class CONTEXT { public: - // the only mutable stuff once it has been loaded from the config file - int reference_count; // protected by the global config_mutex + const char * name; // name of this context // input side int fd; // input fn syslog file struct stat openfdstat; @@ -32,10 +31,6 @@ // output side int fdo; // output tempin wflogs file time_t open_time; // time when fdo opened - // all the rest is constant after loading from the config file - int generation; - time_t load_time; - string_set config_files; TOKEN *tokp; // our data int period; // in seconds @@ -48,8 +43,8 @@ const char * pattern; // regex to filter lines regex_t re; // internal regex to filter lines - CONFIG(); - ~CONFIG(); + CONTEXT(const char *nam); + ~CONTEXT(); void set_token(TOKEN &tok) { tokp = &tok; }; void set_period(int p) { period = p; }; void set_versions(int v) { versions = v; }; @@ -61,15 +56,36 @@ bool failedo() { return (fdo == -1); }; bool failed() { return (fd == -1); }; void dump(); + void openo(bool msg); void open(bool msg); - void openo(bool msg); + bool write(char *p); bool read(); - bool write(char *p); + void closeo(); + void close(); void process(char *p); - void close(); - void closeo(); + void check_wflog(); // time to call it? + void free_all(); +}; +typedef CONTEXT * CONTEXTP; +typedef list context_list; + + +class CONFIG { +public: + // the only mutable stuff once it has been loaded from the config file + int reference_count; // protected by the global config_mutex + // all the rest is constant after loading from the config file + int generation; + time_t load_time; + string_set config_files; + context_list contexts; + + CONFIG(); + ~CONFIG(); + void add_context(CONTEXTP con) {contexts.push_back(con);} ; + void dump(); + bool read(); void sleep(int duration, time_t &previous); - void check_wflog(); // time to call it? void free_all(); }; @@ -77,11 +93,11 @@ const char* register_string(string_set &s, const char *name); const char* register_string(const char *name); void clear_strings(); -int ip_address(const char *have); bool load_conf(CONFIG &dc, const char *fn); void token_init(); +extern const char *token_context; extern const char *token_file; extern const char *token_include; extern const char *token_lbrace; diff -r 964c1127ae65 -r 400b1de6e1c6 wflogs-daemon.conf --- a/wflogs-daemon.conf Wed May 15 13:31:12 2013 -0700 +++ b/wflogs-daemon.conf Fri May 17 10:32:12 2013 -0700 @@ -1,7 +1,30 @@ -period 120; -versions 20; -output "/var/www/html/firewall.%d.html"; -tempin "/tmp/wflogs.input"; -wflogs "wflogs -i all -o html /tmp/wflogs.input >%s"; -file "/var/log/messages"; -pattern "vyatta kernel"; +context fast-response { + period 120; + versions 20; + output "/var/www/html/firewall.0fast.%d.html"; + tempin "/tmp/wflogs.fast.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.fast.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +}; + +context daily { + period 86400; + versions 7; + output "/var/www/html/firewall.1daily.%d.html"; + tempin "/tmp/wflogs.daily.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.daily.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +}; + +context weekly { + period 604800; + versions 4; + output "/var/www/html/firewall.2weekly.%d.html"; + tempin "/tmp/wflogs.weekly.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.weekly.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +}; + diff -r 964c1127ae65 -r 400b1de6e1c6 wflogs-daemon.spec.in --- a/wflogs-daemon.spec.in Wed May 15 13:31:12 2013 -0700 +++ b/wflogs-daemon.spec.in Fri May 17 10:32:12 2013 -0700 @@ -67,5 +67,8 @@ %changelog +* Fri May 17 2013 Carl Byington - 1.1-1 +- allow multiple config contexts + * Wed May 15 2013 Carl Byington - 1.0-1 - initial revision diff -r 964c1127ae65 -r 400b1de6e1c6 xml/wflogs-daemon.in --- a/xml/wflogs-daemon.in Wed May 15 13:31:12 2013 -0700 +++ b/xml/wflogs-daemon.in Fri May 17 10:32:12 2013 -0700 @@ -19,7 +19,7 @@ - 2013-05-15 + 2013-05-17 @@ -128,7 +128,7 @@ - 2013-05-15 + 2013-05-17 @@ -157,7 +157,8 @@ Sample %s"; -file "/var/log/messages"; -pattern "vyatta kernel";]]> +context fast-response { + period 120; + versions 20; + output "/var/www/html/firewall.0fast.%d.html"; + tempin "/tmp/wflogs.fast.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.fast.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +}; + +context daily { + period 86400; + versions 7; + output "/var/www/html/firewall.1daily.%d.html"; + tempin "/tmp/wflogs.daily.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.daily.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +}; + +context weekly { + period 604800; + versions 4; + output "/var/www/html/firewall.2weekly.%d.html"; + tempin "/tmp/wflogs.weekly.input"; + wflogs "nice wflogs -i all -o html /tmp/wflogs.weekly.input >%s &"; + file "/var/log/messages"; + pattern "vyatta kernel"; +};]]>