diff --git a/src/filters/filter.c b/src/filters/filter.c new file mode 100644 index 0000000..7b49226 --- /dev/null +++ b/src/filters/filter.c @@ -0,0 +1,36 @@ +/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +static void +logcb_stub(enum loglevel lvl, const char *str) { + assert(str != NULL); + (void)(lvl); + (void)(str); +} + +__attribute__ ((format (printf, 3, 4))) +static void +log_msg(const cfg_t *cfg, enum loglevel lvl, const char *format, ...) { + char buf[4096] = ""; + va_list args; + size_t len; + + len = snprintf(buf, sizeof(buf), "filter/%s ", MODNAME); + va_start(args, format); + vsnprintf(buf + len, sizeof(buf) - len, format, args); + va_end(args); + + cfg->logcb(lvl, buf); +} + +void +logcb(cfg_t *cfg, void (*cb)(enum loglevel lvl, const char *msg)) { + assert(cfg != NULL); + assert(cb != NULL); + + cfg->logcb = cb; +} diff --git a/src/filters/filter.h b/src/filters/filter.h index 1d7ab1d..1cdeb9d 100644 --- a/src/filters/filter.h +++ b/src/filters/filter.h @@ -11,10 +11,20 @@ #include #include #include +#include #include #include "../strlcpy.h" +enum loglevel { + debug = 0, + info = 1, + notice = 2, + warn = 3, + error = 4, + fatal = 5, +}; /* see log.h */ + /** * @file * This header describes module API of type 'filter' @@ -31,16 +41,14 @@ * f2b => filter [label="config(cfg, param, value)"]; * f2b << filter [label="true"]; * f2b => filter [label="config(cfg, param, value)"]; + * f2b <<= filter [label="logcb(level, char *msg)"]; * f2b << filter [label="false"]; - * f2b => filter [label="error(cfg)"]; - * f2b << filter [label="const char *error"]; * --- [label="filter is ready for append()"]; * f2b => filter [label="append(cfg, pattern)"]; * f2b << filter [label="true"]; * f2b => filter [label="append(cfg, pattern)"]; + * f2b <<= filter [label="logcb(level, char *msg)"]; * f2b << filter [label="false"]; - * f2b => filter [label="error(cfg)"]; - * f2b << filter [label="const char *error"]; * ||| [label="more calls of append()"]; * f2b => filter [label="ready(cfg)"]; * f2b << filter [label="true"]; @@ -92,27 +100,19 @@ typedef struct _config cfg_t; * @returns Opaque module handler or NULL on failure */ extern cfg_t *create(const char *id); -/** - * @brief Returns last error description - * @param cfg Module handler - * @returns Pointer to string with description of last error - * @note Returned pointer not marked with const, because libdl complains, - * but contents on pointer should not be modified or written in any way - */ -extern const char *error(cfg_t *cfg); /** * @brief Contigure module instance * @param cfg Module handler * @param key Parameter name * @param value Parameter value - * @returns true on success, false on error with setting intenal error buffer + * @returns true on success, false on error */ extern bool config(cfg_t *cfg, const char *key, const char *value); /** * @brief Add match pattern * @param cfg Module handler * @param pattern Regex expression - * @returns true on success, false on error with setting intenal error buffer + * @returns true on success, false on error */ extern bool append(cfg_t *cfg, const char *pattern); /** @@ -121,6 +121,13 @@ extern bool append(cfg_t *cfg, const char *pattern); * @returns true if ready, false if not */ extern bool ready(cfg_t *cfg); +/** + * @brief Sets the log callback + * @param cfg Module handler + * @param cb Logging callback + * @note Optional, if this function is not called, warnings/errors of module will be suppressed + */ +extern void logcb(cfg_t *cfg, void (*cb)(enum loglevel l, const char *msg)); /** * @brief Fetch match stats by-pattern * @param cfg Module handler diff --git a/src/filters/pcre.c b/src/filters/pcre.c index f93e3bf..fc0f367 100644 --- a/src/filters/pcre.c +++ b/src/filters/pcre.c @@ -4,10 +4,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include "filter.h" - #include +#include "filter.h" +#define MODNAME "pcre" #define HOST_REGEX "(?[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})" typedef struct f2b_regex_t { @@ -20,7 +20,7 @@ typedef struct f2b_regex_t { struct _config { char id[ID_MAX]; - char error[256]; + void (*logcb)(enum loglevel lvl, const char *msg); bool icase; bool study; bool usejit; @@ -28,6 +28,8 @@ struct _config { f2b_regex_t *statp; }; +#include "filter.c" + cfg_t * create(const char *id) { cfg_t *cfg = NULL; @@ -36,6 +38,7 @@ create(const char *id) { return NULL; strlcpy(cfg->id, id, sizeof(cfg->id)); + cfg->logcb = &logcb_stub; return cfg; } @@ -58,7 +61,7 @@ config(cfg_t *cfg, const char *key, const char *value) { #ifndef PCRE_CONFIG_JIT if (cfg->usejit) { cfg->usejit = false; - strlcpy(cfg->error, "seems like your pcre library doesn't support jit") + log_msg(cfg, error, "seems like your pcre library doesn't support jit"); return false; } #endif @@ -99,7 +102,7 @@ append(cfg_t *cfg, const char *pattern) { return false; if ((regex->regex = pcre_compile(buf, flags, &errptr, &erroffset, NULL)) == NULL) { - snprintf(cfg->error, sizeof(cfg->error), "regex compilation failed at %d: %s", erroffset, errptr); + log_msg(cfg, error, "regex compilation failed at %d: %s", erroffset, errptr); free(regex); return false; } @@ -111,7 +114,7 @@ append(cfg_t *cfg, const char *pattern) { flags |= PCRE_STUDY_JIT_COMPILE; #endif if ((regex->data = pcre_study(regex->regex, 0, &errptr)) == NULL) { - snprintf(cfg->error, sizeof(cfg->error), "regex learn failed: %s", errptr); + log_msg(cfg, error, "regex learn failed: %s", errptr); pcre_free(regex->regex); free(regex); return false; @@ -149,13 +152,6 @@ stats(cfg_t *cfg, int *matches, char **pattern, bool reset) { return false; } -const char * -error(cfg_t *cfg) { - assert(cfg != NULL); - - return cfg->error; -} - bool match(cfg_t *cfg, const char *line, char *buf, size_t buf_size) { f2b_regex_t *r = NULL; @@ -173,7 +169,7 @@ match(cfg_t *cfg, const char *line, char *buf, size_t buf_size) { if (rc < 0 && rc == PCRE_ERROR_NOMATCH) continue; if (rc < 0) { - snprintf(cfg->error, sizeof(cfg->error), "matched failed with error: %d", rc); + log_msg(cfg, error, "matched failed with error: %d", rc); continue; } /* matched */ @@ -181,7 +177,7 @@ match(cfg_t *cfg, const char *line, char *buf, size_t buf_size) { sc = (rc) ? rc : OVECSIZE / 3; rc = pcre_copy_named_substring(r->regex, line, ovector, sc, "host", buf, buf_size); if (rc < 0) { - snprintf(cfg->error, sizeof(cfg->error), "can't copy matched string: %d", rc); + log_msg(cfg, error, "can't copy matched string: %d", rc); continue; } return true; diff --git a/src/filters/preg.c b/src/filters/preg.c index ad9fb91..57b8b59 100644 --- a/src/filters/preg.c +++ b/src/filters/preg.c @@ -4,10 +4,11 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include "filter.h" - #include +#include "filter.h" + +#define MODNAME "preg" /* draft */ #define HOST_REGEX "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})" @@ -20,12 +21,14 @@ typedef struct f2b_regex_t { struct _config { char id[ID_MAX]; - char error[256]; bool icase; + void (*logcb)(enum loglevel lvl, const char *msg); f2b_regex_t *regexps; f2b_regex_t *statp; }; +#include "filter.c" + cfg_t * create(const char *id) { cfg_t *cfg = NULL; @@ -34,6 +37,7 @@ create(const char *id) { return NULL; strlcpy(cfg->id, id, sizeof(cfg->id)); + cfg->logcb = &logcb_stub; return cfg; } @@ -58,6 +62,7 @@ append(cfg_t *cfg, const char *pattern) { size_t bufsize; char *buf = NULL; char *token = NULL; + int ret; assert(pattern != NULL); @@ -79,11 +84,15 @@ append(cfg_t *cfg, const char *pattern) { if ((regex = calloc(1, sizeof(f2b_regex_t))) == NULL) return false; - if (regcomp(®ex->regex, buf, flags) == 0) { + if ((ret = regcomp(®ex->regex, buf, flags)) == 0) { regex->next = cfg->regexps; cfg->regexps = regex; strlcpy(regex->pattern, pattern, sizeof(regex->pattern)); return true; + } else { + char buf[256] = ""; + regerror(ret, ®ex->regex, buf, sizeof(buf)); + log_msg(cfg, error, "regex compile error: %s", buf); } free(regex); @@ -115,13 +124,6 @@ stats(cfg_t *cfg, int *matches, char **pattern, bool reset) { return false; } -const char * -error(cfg_t *cfg) { - assert(cfg != NULL); - - return cfg->error; -} - bool match(cfg_t *cfg, const char *line, char *buf, size_t buf_size) { f2b_regex_t *r = NULL;