Alex 'AdUser' Z
9 years ago
2 changed files with 171 additions and 0 deletions
@ -0,0 +1,148 @@
|
||||
#include "common.h" |
||||
#include "filter.h" |
||||
|
||||
#define REGEX_LINE_MAX 256 |
||||
#define HOST_TOKEN "<HOST>" |
||||
#define FILTER_LIBRARY_PARAM "load" |
||||
|
||||
static bool |
||||
f2b_filter_load_file(f2b_filter_t *filter, const char *path) { |
||||
FILE *f = NULL; |
||||
size_t linenum = 0; |
||||
char line[REGEX_LINE_MAX] = ""; |
||||
char *p, *q; |
||||
|
||||
if ((f = fopen(path, "r")) == NULL) { |
||||
f2b_log_msg(log_error, "can't open regex list '%s': %s", path, strerror(errno)); |
||||
return false; |
||||
} |
||||
|
||||
while (1) { |
||||
p = fgets(line, sizeof(line), f); |
||||
if (!p && (feof(f) || ferror(f))) |
||||
break; |
||||
linenum++; |
||||
/* strip leading spaces */ |
||||
while (isblank(*p)) |
||||
p++; |
||||
/* strip trailing spaces */ |
||||
if ((q = strchr(p, '\r')) || (q = strchr(p, '\n'))) { |
||||
while(q > p && isspace(*q)) { |
||||
*q = '\0'; |
||||
q--; |
||||
} |
||||
} |
||||
switch(*p) { |
||||
case '\r': |
||||
case '\n': |
||||
case '\0': |
||||
/* empty line */ |
||||
break; |
||||
case ';': |
||||
case '#': |
||||
/* comment line */ |
||||
break; |
||||
default: |
||||
if (strstr(p, HOST_TOKEN) == NULL) { |
||||
f2b_log_msg(log_warn, "pattern at %s:%d don't have '%s' marker, ignored", HOST_TOKEN); |
||||
continue; |
||||
} |
||||
if (!filter->append(filter->cfg, p)) { |
||||
f2b_log_msg(log_warn, "can't create regex from pattern at %s:%d: %s", path, linenum, p); |
||||
continue; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
f2b_filter_t * |
||||
f2b_filter_create(f2b_config_section_t *config, const char *file) { |
||||
f2b_config_param_t *param = NULL; |
||||
f2b_filter_t *filter = NULL; |
||||
int flags = RTLD_NOW | RTLD_LOCAL; |
||||
const char *dlerr = NULL; |
||||
|
||||
assert(config != NULL); |
||||
assert(config->type == t_filter); |
||||
|
||||
param = f2b_config_param_find(config->param, FILTER_LIBRARY_PARAM); |
||||
if (!param) { |
||||
f2b_log_msg(log_error, "can't find '%s' param in filter config", FILTER_LIBRARY_PARAM); |
||||
return NULL; |
||||
} |
||||
|
||||
if ((filter = calloc(1, sizeof(f2b_filter_t))) == NULL) |
||||
return NULL; |
||||
|
||||
if ((filter->h = dlopen(param->value, flags)) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->create) = dlsym(filter->h, "create")) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->config) = dlsym(filter->h, "config")) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->append) = dlsym(filter->h, "append")) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->ready) = dlsym(filter->h, "ready")) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->match) = dlsym(filter->h, "match")) == NULL) |
||||
goto cleanup; |
||||
if ((*(void **) (&filter->destroy) = dlsym(filter->h, "destroy")) == NULL) |
||||
goto cleanup; |
||||
|
||||
/* TODO: do we need id? */ |
||||
if ((filter->cfg = filter->create("")) == NULL) { |
||||
f2b_log_msg(log_error, "filter create config failed"); |
||||
goto cleanup; |
||||
} |
||||
|
||||
/* try init */ |
||||
for (param = config->param; param != NULL; param = param->next) { |
||||
if (strcmp(param->name, FILTER_LIBRARY_PARAM) == 0) |
||||
continue; |
||||
if (filter->config(filter->cfg, param->name, param->value)) |
||||
continue; |
||||
f2b_log_msg(log_warn, "param pair not accepted by filter '%s': %s=%s", |
||||
config->name, param->name, param->value); |
||||
} |
||||
|
||||
if (!f2b_filter_load_file(filter, file)) |
||||
goto cleanup; |
||||
|
||||
if (filter->ready(filter->cfg)) |
||||
return filter; |
||||
|
||||
/* still not ready */ |
||||
f2b_log_msg(log_error, "filter '%s' not fully configured", config->name); |
||||
|
||||
cleanup: |
||||
dlerr = dlerror(); |
||||
if (dlerr) |
||||
f2b_log_msg(log_error, "filter load error: %s", dlerr); |
||||
if (filter->h) { |
||||
if (filter->cfg && filter->destroy) |
||||
filter->destroy(filter->cfg); |
||||
dlclose(filter->h); |
||||
} |
||||
free(filter); |
||||
return NULL; |
||||
} |
||||
|
||||
void |
||||
f2b_filter_destroy(f2b_filter_t *filter) { |
||||
assert(filter != NULL); |
||||
filter->destroy(filter->cfg); |
||||
dlclose(filter->h); |
||||
free(filter); |
||||
} |
||||
|
||||
bool |
||||
f2b_filter_match(f2b_filter_t *filter, const char *line, char *buf, size_t buf_size) { |
||||
assert(filter != NULL); |
||||
assert(line != NULL); |
||||
assert(buf != NULL); |
||||
|
||||
return filter->match(filter->cfg, line, buf, buf_size); |
||||
} |
@ -0,0 +1,23 @@
|
||||
#ifndef FILTER_H_ |
||||
#define FILTER_H_ |
||||
|
||||
#include "config.h" |
||||
#include "log.h" |
||||
|
||||
typedef struct f2b_filter_t { |
||||
void *h; |
||||
void *cfg; |
||||
void *(*create) (const char *id); |
||||
bool (*config) (void *cfg, const char *key, const char *value); |
||||
bool (*append) (void *cfg, const char *pattern); |
||||
bool (*ready) (void *cfg); |
||||
bool (*match) (void *cfg, const char *line, char *buf, size_t buf_size); |
||||
void (*destroy) (void *cfg); |
||||
} f2b_filter_t; |
||||
|
||||
f2b_filter_t * f2b_filter_create (f2b_config_section_t *config, const char *id); |
||||
void f2b_filter_destroy(f2b_filter_t *b); |
||||
|
||||
bool f2b_filter_match(f2b_filter_t *b, const char *line, char *buf, size_t buf_size); |
||||
|
||||
#endif /* FILTER_H_ */ |
Loading…
Reference in new issue