3 * This file contains the dynamic library module for Unbound.
4 * This loads a dynamic library (.dll, .so) and calls that for the
8 #include "util/module.h"
9 #include "util/config_file.h"
10 #include "dynlibmod/dynlibmod.h"
14 #define __DYNMOD HMODULE
15 #define __DYNSYM FARPROC
16 #define __LOADSYM GetProcAddress
18 DWORD dwLastError = GetLastError();
21 DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
22 FORMAT_MESSAGE_IGNORE_INSERTS |
23 FORMAT_MESSAGE_FROM_SYSTEM ;
24 if((dwBufferLength = FormatMessageA(
26 NULL, // module to get message from (NULL == system)
28 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
29 (LPSTR) &MessageBuffer,
34 log_err("dynlibmod: %s (%ld)", MessageBuffer, dwLastError);
35 LocalFree(MessageBuffer);
40 HMODULE open_library(const char* fname) {
41 return LoadLibrary(fname);
44 void close_library(const char* fname, __DYNMOD handle) {
50 #define __DYNMOD void*
51 #define __DYNSYM void*
52 #define __LOADSYM dlsym
54 log_err("dynlibmod: %s", dlerror());
57 void* open_library(const char* fname) {
58 return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL);
61 void close_library(const char* fname, __DYNMOD handle) {
63 if(dlclose(handle) != 0) {
64 log_err("dlclose %s: %s", fname, strerror(errno));
69 /** module counter for multiple dynlib modules */
70 static int dynlib_mod_count = 0;
72 /** dynlib module init */
73 int dynlibmod_init(struct module_env* env, int id) {
74 int dynlib_mod_idx = dynlib_mod_count++;
75 struct config_strlist* cfg_item = env->cfg->dynlib_file;
76 struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
77 __DYNMOD dynamic_library;
80 log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
84 env->modinfo[id] = (void*) de;
87 for(int i = dynlib_mod_idx;
88 i != 0 && cfg_item != NULL;
89 i--, cfg_item = cfg_item->next) {}
91 if (cfg_item == NULL || cfg_item->str == NULL || cfg_item->str[0] == 0) {
92 log_err("dynlibmod[%d]: no dynamic library given.", dynlib_mod_idx);
95 de->fname = cfg_item->str;
97 verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname);
98 dynamic_library = open_library(de->fname);
99 de->dynamic_library = (void*)dynamic_library;
100 if (dynamic_library == NULL) {
102 log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname);
105 __DYNSYM initializer;
106 __DYNSYM deinitializer;
111 initializer = __LOADSYM(dynamic_library,"init");
112 if (initializer == NULL) {
114 log_err("dynlibmod[%d]: unable to load init procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
117 de->func_init = (func_init_t)(void*)initializer;
119 deinitializer = __LOADSYM(dynamic_library,"deinit");
120 if (deinitializer == NULL) {
122 log_err("dynlibmod[%d]: unable to load deinit procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
125 de->func_deinit = (func_deinit_t)(void*)deinitializer;
127 operate = __LOADSYM(dynamic_library,"operate");
128 if (operate == NULL) {
130 log_err("dynlibmod[%d]: unable to load operate procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
133 de->func_operate = (func_operate_t)(void*)operate;
135 inform = __LOADSYM(dynamic_library,"inform_super");
136 if (inform == NULL) {
138 log_err("dynlibmod[%d]: unable to load inform_super procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
141 de->func_inform = (func_inform_t)(void*)inform;
143 clear = __LOADSYM(dynamic_library,"clear");
146 log_err("dynlibmod[%d]: unable to load clear procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
149 de->func_clear = (func_clear_t)(void*)clear;
151 get_mem = __LOADSYM(dynamic_library,"get_mem");
152 if (get_mem == NULL) {
154 log_err("dynlibmod[%d]: unable to load get_mem procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
157 de->func_get_mem = (func_get_mem_t)(void*)get_mem;
160 de->inplace_cb_delete_wrapped = &inplace_cb_delete_wrapped;
161 de->inplace_cb_register_wrapped = &inplace_cb_register_wrapped;
162 return de->func_init(env, id);
165 /** dynlib module deinit */
166 void dynlibmod_deinit(struct module_env* env, int id) {
167 struct dynlibmod_env* de = env->modinfo[id];
170 de->func_deinit(env, id);
171 close_library(de->fname, (__DYNMOD)de->dynamic_library);
177 /** dynlib module operate on a query */
178 void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
179 int id, struct outbound_entry* outbound) {
180 struct dynlibmod_env* de = qstate->env->modinfo[id];
182 de->func_operate(qstate, event, id, outbound);
186 void dynlibmod_inform_super(struct module_qstate* qstate, int id,
187 struct module_qstate* super) {
188 struct dynlibmod_env* de = qstate->env->modinfo[id];
190 de->func_inform(qstate, id, super);
193 /** dynlib module cleanup query state */
194 void dynlibmod_clear(struct module_qstate* qstate, int id) {
195 struct dynlibmod_env* de = qstate->env->modinfo[id];
197 de->func_clear(qstate, id);
200 /** dynlib module alloc size routine */
201 size_t dynlibmod_get_mem(struct module_env* env, int id) {
202 struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id];
204 verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de);
208 size = de->func_get_mem(env, id);
209 return size + sizeof(*de);
212 int dynlib_inplace_cb_reply_generic(struct query_info* qinfo,
213 struct module_qstate* qstate, struct reply_info* rep, int rcode,
214 struct edns_data* edns, struct edns_option** opt_list_out,
215 struct comm_reply* repinfo, struct regional* region, int id,
217 struct cb_pair* cb_pair = (struct cb_pair*) callback;
218 return ((inplace_cb_reply_func_type*) cb_pair->cb)(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, region, id, cb_pair->cb_arg);
221 int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags,
222 struct module_qstate* qstate, struct sockaddr_storage* addr,
223 socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region,
224 int id, void* callback) {
225 struct cb_pair* cb_pair = (struct cb_pair*) callback;
226 return ((inplace_cb_query_func_type*) cb_pair->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, id, cb_pair->cb_arg);
229 int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate,
230 int id, void* cb_args) {
231 struct cb_pair* cb_pair = (struct cb_pair*) cb_args;
232 return ((inplace_cb_edns_back_parsed_func_type*) cb_pair->cb)(qstate, id, cb_pair->cb_arg);
235 int dynlib_inplace_cb_query_response(struct module_qstate* qstate,
236 struct dns_msg* response, int id, void* cb_args) {
237 struct cb_pair* cb_pair = (struct cb_pair*) cb_args;
238 return ((inplace_cb_query_response_func_type*) cb_pair->cb)(qstate, response, id, cb_pair->cb_arg);
242 inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg,
243 struct module_env* env, int id) {
244 struct cb_pair* cb_pair = malloc(sizeof(struct cb_pair));
245 if(cb_pair == NULL) {
246 log_err("dynlibmod[%d]: malloc failure", id);
250 cb_pair->cb_arg = cbarg;
251 if(type >= inplace_cb_reply && type <= inplace_cb_reply_servfail) {
252 return inplace_cb_register(&dynlib_inplace_cb_reply_generic, type, (void*) cb_pair, env, id);
253 } else if(type == inplace_cb_query) {
254 return inplace_cb_register(&dynlib_inplace_cb_query_generic, type, (void*) cb_pair, env, id);
255 } else if(type == inplace_cb_query_response) {
256 return inplace_cb_register(&dynlib_inplace_cb_query_response, type, (void*) cb_pair, env, id);
257 } else if(type == inplace_cb_edns_back_parsed) {
258 return inplace_cb_register(&dynlib_inplace_cb_edns_back_parsed, type, (void*) cb_pair, env, id);
266 inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type,
268 struct inplace_cb* temp = env->inplace_cb_lists[type];
269 struct inplace_cb* prev = NULL;
274 env->inplace_cb_lists[type] = temp->next;
277 temp = env->inplace_cb_lists[type];
280 prev->next = temp->next;
295 * The module function block
297 static struct module_func_block dynlibmod_block = {
299 &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
300 &dynlibmod_clear, &dynlibmod_get_mem
303 struct module_func_block* dynlibmod_get_funcblock(void)
305 return &dynlibmod_block;