2019-10-17 09:10:33 -04:00
|
|
|
#include "config.h"
|
|
|
|
|
#include "util/module.h"
|
|
|
|
|
#include "util/config_file.h"
|
|
|
|
|
#include "dynlibmod/dynlibmod.h"
|
|
|
|
|
|
|
|
|
|
#if HAVE_WINDOWS_H
|
|
|
|
|
#include <windows.h>
|
2019-10-21 08:20:33 -04:00
|
|
|
#define __DYNMOD HMODULE
|
2019-10-17 09:10:33 -04:00
|
|
|
#define __DYNSYM FARPROC
|
|
|
|
|
#define __LOADSYM GetProcAddress
|
|
|
|
|
void log_dlerror() {
|
|
|
|
|
DWORD dwLastError = GetLastError();
|
|
|
|
|
LPSTR MessageBuffer;
|
|
|
|
|
DWORD dwBufferLength;
|
|
|
|
|
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM ;
|
|
|
|
|
if(dwBufferLength = FormatMessageA(
|
|
|
|
|
dwFormatFlags,
|
|
|
|
|
NULL, // module to get message from (NULL == system)
|
|
|
|
|
dwLastError,
|
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
|
|
|
|
|
(LPSTR) &MessageBuffer,
|
|
|
|
|
0,
|
|
|
|
|
NULL
|
|
|
|
|
))
|
|
|
|
|
{
|
|
|
|
|
DWORD dwBytesWritten;
|
2019-10-21 08:20:33 -04:00
|
|
|
log_err("dynlibmod: %s (%ld)", MessageBuffer, dwLastError);
|
2019-10-17 09:10:33 -04:00
|
|
|
LocalFree(MessageBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2019-10-21 08:20:33 -04:00
|
|
|
HMODULE open_library(const char* fname) {
|
|
|
|
|
return LoadLibrary(fname);
|
|
|
|
|
}
|
2019-10-17 09:10:33 -04:00
|
|
|
#else
|
|
|
|
|
#include <dlfcn.h>
|
2019-10-21 08:20:33 -04:00
|
|
|
#define __DYNMOD void*
|
2019-10-17 09:10:33 -04:00
|
|
|
#define __DYNSYM void*
|
|
|
|
|
#define __LOADSYM dlsym
|
|
|
|
|
void log_dlerror() {
|
|
|
|
|
log_err("dynlibmod: %s", dlerror());
|
|
|
|
|
}
|
2019-10-21 08:20:33 -04:00
|
|
|
void* open_library(const char* fname) {
|
|
|
|
|
return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL);
|
|
|
|
|
}
|
2019-10-17 09:10:33 -04:00
|
|
|
#endif
|
|
|
|
|
|
2019-10-21 08:20:33 -04:00
|
|
|
|
2019-10-17 09:10:33 -04:00
|
|
|
/**
|
|
|
|
|
* Global state for the module.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-10-21 08:20:33 -04:00
|
|
|
typedef void (*func_init_t)(struct module_env*, int);
|
|
|
|
|
typedef void (*func_deinit_t)(struct module_env*, int);
|
|
|
|
|
typedef void (*func_operate_t)(struct module_qstate*, enum module_ev, int, struct outbound_entry*);
|
|
|
|
|
typedef void (*func_inform_t)(struct module_qstate*, int, struct module_qstate*);
|
|
|
|
|
typedef void (*func_clear_t)(struct module_qstate*, int);
|
|
|
|
|
typedef size_t (*func_get_mem_t)(struct module_env*, int);
|
|
|
|
|
|
2019-10-17 09:10:33 -04:00
|
|
|
struct dynlibmod_env {
|
|
|
|
|
|
|
|
|
|
/** Dynamic library filename. */
|
|
|
|
|
const char* fname;
|
|
|
|
|
|
|
|
|
|
/** Module init function */
|
|
|
|
|
func_init_t func_init;
|
|
|
|
|
/** Module deinit function */
|
|
|
|
|
func_deinit_t func_deinit;
|
|
|
|
|
/** Module operate function */
|
|
|
|
|
func_operate_t func_operate;
|
|
|
|
|
/** Module super_inform function */
|
|
|
|
|
func_inform_t func_inform;
|
2019-10-21 08:20:33 -04:00
|
|
|
/** Module clear function */
|
|
|
|
|
func_clear_t func_clear;
|
|
|
|
|
/** Module get_mem function */
|
|
|
|
|
func_get_mem_t func_get_mem;
|
2019-10-17 09:10:33 -04:00
|
|
|
|
|
|
|
|
/** Module qstate. */
|
|
|
|
|
struct module_qstate* qstate;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** dynlib module init */
|
|
|
|
|
int dynlibmod_init(struct module_env* env, int id) {
|
|
|
|
|
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
2019-10-21 08:20:33 -04:00
|
|
|
__DYNMOD dynamic_library;
|
2019-10-17 09:10:33 -04:00
|
|
|
if (!de)
|
|
|
|
|
{
|
|
|
|
|
log_err("dynlibmod: malloc failure");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
env->modinfo[id] = (void*) de;
|
|
|
|
|
|
|
|
|
|
de->fname = env->cfg->dynlib_file;
|
|
|
|
|
if (de->fname == NULL || de->fname[0] == 0) {
|
|
|
|
|
log_err("dynlibmod: no dynamic library given.");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2019-10-21 08:20:33 -04:00
|
|
|
verbose(VERB_ALGO, "dynlibmod: Trying to load library %s", de->fname);
|
|
|
|
|
dynamic_library = open_library(de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
if (dynamic_library == NULL) {
|
|
|
|
|
log_dlerror();
|
2019-10-21 08:20:33 -04:00
|
|
|
log_err("dynlibmod: unable to load dynamic library \"%s\".", de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
__DYNSYM initializer = __LOADSYM(dynamic_library,"init");
|
|
|
|
|
if (initializer == NULL) {
|
2019-10-21 08:20:33 -04:00
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load init procedure from dynamic library \"%s\".", de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_init = (func_init_t) initializer;
|
|
|
|
|
}
|
|
|
|
|
__DYNSYM deinitializer = __LOADSYM(dynamic_library,"deinit");
|
|
|
|
|
if (deinitializer == NULL) {
|
2019-10-21 08:20:33 -04:00
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load deinit procedure from dynamic library \"%s\".", de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_deinit = (func_deinit_t) deinitializer;
|
|
|
|
|
}
|
|
|
|
|
__DYNSYM operate = __LOADSYM(dynamic_library,"operate");
|
|
|
|
|
if (operate == NULL) {
|
2019-10-21 08:20:33 -04:00
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load operate procedure from dynamic library \"%s\".", de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_operate = (func_operate_t) operate;
|
|
|
|
|
}
|
|
|
|
|
__DYNSYM inform = __LOADSYM(dynamic_library,"inform_super");
|
|
|
|
|
if (inform == NULL) {
|
2019-10-21 08:20:33 -04:00
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load inform_super procedure from dynamic library \"%s\".", de->fname);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_inform = (func_inform_t) inform;
|
|
|
|
|
}
|
2019-10-21 08:20:33 -04:00
|
|
|
__DYNSYM clear = __LOADSYM(dynamic_library,"clear");
|
|
|
|
|
if (clear == NULL) {
|
|
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load clear procedure from dynamic library \"%s\".", de->fname);
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_clear = (func_clear_t) clear;
|
|
|
|
|
}
|
|
|
|
|
__DYNSYM get_mem = __LOADSYM(dynamic_library,"get_mem");
|
|
|
|
|
if (get_mem == NULL) {
|
|
|
|
|
log_dlerror();
|
|
|
|
|
log_err("dynlibmod: unable to load get_mem procedure from dynamic library \"%s\".", de->fname);
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
de->func_get_mem = (func_get_mem_t) get_mem;
|
|
|
|
|
}
|
2019-10-17 09:10:33 -04:00
|
|
|
}
|
2019-10-21 08:20:33 -04:00
|
|
|
de->func_init(env, id);
|
2019-10-17 09:10:33 -04:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** dynlib module deinit */
|
|
|
|
|
void dynlibmod_deinit(struct module_env* env, int id) {
|
|
|
|
|
struct dynlibmod_env* de = env->modinfo[id];
|
|
|
|
|
if(de == NULL)
|
|
|
|
|
return;
|
2019-10-21 08:20:33 -04:00
|
|
|
de->func_deinit(env, id);
|
2019-10-17 09:10:33 -04:00
|
|
|
de->fname = NULL;
|
|
|
|
|
free(de);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** dynlib module operate on a query */
|
|
|
|
|
void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
|
|
|
|
|
int id, struct outbound_entry* outbound) {
|
|
|
|
|
struct dynlibmod_env* de = qstate->env->modinfo[id];
|
|
|
|
|
|
2019-10-21 08:20:33 -04:00
|
|
|
de->func_operate(qstate, event, id, outbound);
|
2019-10-17 09:10:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** dynlib module */
|
|
|
|
|
void dynlibmod_inform_super(struct module_qstate* qstate, int id,
|
|
|
|
|
struct module_qstate* super) {
|
|
|
|
|
struct dynlibmod_env* de = qstate->env->modinfo[id];
|
|
|
|
|
|
2019-10-21 08:20:33 -04:00
|
|
|
de->func_inform(qstate, id, super);
|
2019-10-17 09:10:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** dynlib module cleanup query state */
|
|
|
|
|
void dynlibmod_clear(struct module_qstate* qstate, int id) {
|
2019-10-21 08:20:33 -04:00
|
|
|
struct dynlibmod_env* de = qstate->env->modinfo[id];
|
2019-10-17 09:10:33 -04:00
|
|
|
|
2019-10-21 08:20:33 -04:00
|
|
|
de->func_clear(qstate, id);
|
2019-10-17 09:10:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** dynlib module alloc size routine */
|
|
|
|
|
size_t dynlibmod_get_mem(struct module_env* env, int id) {
|
|
|
|
|
struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id];
|
|
|
|
|
verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de);
|
|
|
|
|
if(!de)
|
|
|
|
|
return 0;
|
2019-10-21 08:20:33 -04:00
|
|
|
|
|
|
|
|
size_t size = de->func_get_mem(env, id);
|
|
|
|
|
return size + sizeof(*de);
|
2019-10-17 09:10:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The module function block
|
|
|
|
|
*/
|
|
|
|
|
static struct module_func_block dynlibmod_block = {
|
|
|
|
|
"dynlib",
|
|
|
|
|
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
|
|
|
|
|
&dynlibmod_clear, &dynlibmod_get_mem
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct module_func_block* dynlibmod_get_funcblock(void)
|
|
|
|
|
{
|
|
|
|
|
return &dynlibmod_block;
|
|
|
|
|
}
|