125039b37SCy Schubert /** 225039b37SCy Schubert * \file 325039b37SCy Schubert * This file contains the dynamic library module for Unbound. 425039b37SCy Schubert * This loads a dynamic library (.dll, .so) and calls that for the 525039b37SCy Schubert * module actions. 625039b37SCy Schubert */ 725039b37SCy Schubert #include "config.h" 8f44e67d1SCy Schubert #include "dynlibmod/dynlibmod.h" 925039b37SCy Schubert #include "util/module.h" 1025039b37SCy Schubert #include "util/config_file.h" 1125039b37SCy Schubert 1225039b37SCy Schubert #if HAVE_WINDOWS_H 1325039b37SCy Schubert #include <windows.h> 1425039b37SCy Schubert #define __DYNMOD HMODULE 1525039b37SCy Schubert #define __DYNSYM FARPROC 1625039b37SCy Schubert #define __LOADSYM GetProcAddress 17f44e67d1SCy Schubert static void log_dlerror() { 1825039b37SCy Schubert DWORD dwLastError = GetLastError(); 1925039b37SCy Schubert LPSTR MessageBuffer; 2025039b37SCy Schubert DWORD dwBufferLength; 2125039b37SCy Schubert DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | 2225039b37SCy Schubert FORMAT_MESSAGE_IGNORE_INSERTS | 2325039b37SCy Schubert FORMAT_MESSAGE_FROM_SYSTEM ; 2425039b37SCy Schubert if((dwBufferLength = FormatMessageA( 2525039b37SCy Schubert dwFormatFlags, 2625039b37SCy Schubert NULL, // module to get message from (NULL == system) 2725039b37SCy Schubert dwLastError, 2825039b37SCy Schubert MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language 2925039b37SCy Schubert (LPSTR) &MessageBuffer, 3025039b37SCy Schubert 0, 3125039b37SCy Schubert NULL 3225039b37SCy Schubert ))) 3325039b37SCy Schubert { 3425039b37SCy Schubert log_err("dynlibmod: %s (%ld)", MessageBuffer, dwLastError); 3525039b37SCy Schubert LocalFree(MessageBuffer); 3625039b37SCy Schubert } 3725039b37SCy Schubert 3825039b37SCy Schubert } 3925039b37SCy Schubert 40f44e67d1SCy Schubert static HMODULE open_library(const char* fname) { 4125039b37SCy Schubert return LoadLibrary(fname); 4225039b37SCy Schubert } 4325039b37SCy Schubert 44f44e67d1SCy Schubert static void close_library(const char* fname, __DYNMOD handle) { 4525039b37SCy Schubert (void)fname; 4625039b37SCy Schubert (void)handle; 4725039b37SCy Schubert } 4825039b37SCy Schubert #else 4925039b37SCy Schubert #include <dlfcn.h> 5025039b37SCy Schubert #define __DYNMOD void* 5125039b37SCy Schubert #define __DYNSYM void* 5225039b37SCy Schubert #define __LOADSYM dlsym 53f44e67d1SCy Schubert static void log_dlerror() { 5425039b37SCy Schubert log_err("dynlibmod: %s", dlerror()); 5525039b37SCy Schubert } 5625039b37SCy Schubert 57f44e67d1SCy Schubert static void* open_library(const char* fname) { 5825039b37SCy Schubert return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL); 5925039b37SCy Schubert } 6025039b37SCy Schubert 61f44e67d1SCy Schubert static void close_library(const char* fname, __DYNMOD handle) { 6225039b37SCy Schubert if(!handle) return; 6325039b37SCy Schubert if(dlclose(handle) != 0) { 6425039b37SCy Schubert log_err("dlclose %s: %s", fname, strerror(errno)); 6525039b37SCy Schubert } 6625039b37SCy Schubert } 6725039b37SCy Schubert #endif 6825039b37SCy Schubert 6925039b37SCy Schubert /** module counter for multiple dynlib modules */ 7025039b37SCy Schubert static int dynlib_mod_count = 0; 7125039b37SCy Schubert 7225039b37SCy Schubert /** dynlib module init */ 7325039b37SCy Schubert int dynlibmod_init(struct module_env* env, int id) { 7425039b37SCy Schubert int dynlib_mod_idx = dynlib_mod_count++; 7525039b37SCy Schubert struct config_strlist* cfg_item = env->cfg->dynlib_file; 7625039b37SCy Schubert struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env)); 7725039b37SCy Schubert __DYNMOD dynamic_library; 78103ba509SCy Schubert int i; 7925039b37SCy Schubert if (!de) 8025039b37SCy Schubert { 8125039b37SCy Schubert log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx); 8225039b37SCy Schubert return 0; 8325039b37SCy Schubert } 8425039b37SCy Schubert 8525039b37SCy Schubert env->modinfo[id] = (void*) de; 8625039b37SCy Schubert 8725039b37SCy Schubert de->fname = NULL; 88103ba509SCy Schubert for(i = dynlib_mod_idx; 8925039b37SCy Schubert i != 0 && cfg_item != NULL; 9025039b37SCy Schubert i--, cfg_item = cfg_item->next) {} 9125039b37SCy Schubert 9225039b37SCy Schubert if (cfg_item == NULL || cfg_item->str == NULL || cfg_item->str[0] == 0) { 9325039b37SCy Schubert log_err("dynlibmod[%d]: no dynamic library given.", dynlib_mod_idx); 9425039b37SCy Schubert return 0; 9525039b37SCy Schubert } else { 9625039b37SCy Schubert de->fname = cfg_item->str; 9725039b37SCy Schubert } 9825039b37SCy Schubert verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname); 9925039b37SCy Schubert dynamic_library = open_library(de->fname); 10025039b37SCy Schubert de->dynamic_library = (void*)dynamic_library; 10125039b37SCy Schubert if (dynamic_library == NULL) { 10225039b37SCy Schubert log_dlerror(); 10325039b37SCy Schubert log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname); 10425039b37SCy Schubert return 0; 10525039b37SCy Schubert } else { 10625039b37SCy Schubert __DYNSYM initializer; 10725039b37SCy Schubert __DYNSYM deinitializer; 10825039b37SCy Schubert __DYNSYM operate; 10925039b37SCy Schubert __DYNSYM inform; 11025039b37SCy Schubert __DYNSYM clear; 11125039b37SCy Schubert __DYNSYM get_mem; 11225039b37SCy Schubert initializer = __LOADSYM(dynamic_library,"init"); 11325039b37SCy Schubert if (initializer == NULL) { 11425039b37SCy Schubert log_dlerror(); 11525039b37SCy Schubert log_err("dynlibmod[%d]: unable to load init procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 11625039b37SCy Schubert return 0; 11725039b37SCy Schubert } else { 11825039b37SCy Schubert de->func_init = (func_init_t)(void*)initializer; 11925039b37SCy Schubert } 12025039b37SCy Schubert deinitializer = __LOADSYM(dynamic_library,"deinit"); 12125039b37SCy Schubert if (deinitializer == NULL) { 12225039b37SCy Schubert log_dlerror(); 12325039b37SCy Schubert log_err("dynlibmod[%d]: unable to load deinit procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 12425039b37SCy Schubert return 0; 12525039b37SCy Schubert } else { 12625039b37SCy Schubert de->func_deinit = (func_deinit_t)(void*)deinitializer; 12725039b37SCy Schubert } 12825039b37SCy Schubert operate = __LOADSYM(dynamic_library,"operate"); 12925039b37SCy Schubert if (operate == NULL) { 13025039b37SCy Schubert log_dlerror(); 13125039b37SCy Schubert log_err("dynlibmod[%d]: unable to load operate procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 13225039b37SCy Schubert return 0; 13325039b37SCy Schubert } else { 13425039b37SCy Schubert de->func_operate = (func_operate_t)(void*)operate; 13525039b37SCy Schubert } 13625039b37SCy Schubert inform = __LOADSYM(dynamic_library,"inform_super"); 13725039b37SCy Schubert if (inform == NULL) { 13825039b37SCy Schubert log_dlerror(); 13925039b37SCy Schubert log_err("dynlibmod[%d]: unable to load inform_super procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 14025039b37SCy Schubert return 0; 14125039b37SCy Schubert } else { 14225039b37SCy Schubert de->func_inform = (func_inform_t)(void*)inform; 14325039b37SCy Schubert } 14425039b37SCy Schubert clear = __LOADSYM(dynamic_library,"clear"); 14525039b37SCy Schubert if (clear == NULL) { 14625039b37SCy Schubert log_dlerror(); 14725039b37SCy Schubert log_err("dynlibmod[%d]: unable to load clear procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 14825039b37SCy Schubert return 0; 14925039b37SCy Schubert } else { 15025039b37SCy Schubert de->func_clear = (func_clear_t)(void*)clear; 15125039b37SCy Schubert } 15225039b37SCy Schubert get_mem = __LOADSYM(dynamic_library,"get_mem"); 15325039b37SCy Schubert if (get_mem == NULL) { 15425039b37SCy Schubert log_dlerror(); 15525039b37SCy Schubert log_err("dynlibmod[%d]: unable to load get_mem procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); 15625039b37SCy Schubert return 0; 15725039b37SCy Schubert } else { 15825039b37SCy Schubert de->func_get_mem = (func_get_mem_t)(void*)get_mem; 15925039b37SCy Schubert } 16025039b37SCy Schubert } 16125039b37SCy Schubert de->inplace_cb_delete_wrapped = &inplace_cb_delete_wrapped; 16225039b37SCy Schubert de->inplace_cb_register_wrapped = &inplace_cb_register_wrapped; 16325039b37SCy Schubert return de->func_init(env, id); 16425039b37SCy Schubert } 16525039b37SCy Schubert 16625039b37SCy Schubert /** dynlib module deinit */ 16725039b37SCy Schubert void dynlibmod_deinit(struct module_env* env, int id) { 16825039b37SCy Schubert struct dynlibmod_env* de = env->modinfo[id]; 16925039b37SCy Schubert if(de == NULL) 17025039b37SCy Schubert return; 17125039b37SCy Schubert de->func_deinit(env, id); 17225039b37SCy Schubert close_library(de->fname, (__DYNMOD)de->dynamic_library); 17325039b37SCy Schubert dynlib_mod_count--; 17425039b37SCy Schubert de->fname = NULL; 17525039b37SCy Schubert free(de); 17625039b37SCy Schubert } 17725039b37SCy Schubert 17825039b37SCy Schubert /** dynlib module operate on a query */ 17925039b37SCy Schubert void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event, 18025039b37SCy Schubert int id, struct outbound_entry* outbound) { 18125039b37SCy Schubert struct dynlibmod_env* de = qstate->env->modinfo[id]; 18225039b37SCy Schubert 18325039b37SCy Schubert de->func_operate(qstate, event, id, outbound); 18425039b37SCy Schubert } 18525039b37SCy Schubert 18625039b37SCy Schubert /** dynlib module */ 18725039b37SCy Schubert void dynlibmod_inform_super(struct module_qstate* qstate, int id, 18825039b37SCy Schubert struct module_qstate* super) { 18925039b37SCy Schubert struct dynlibmod_env* de = qstate->env->modinfo[id]; 19025039b37SCy Schubert 19125039b37SCy Schubert de->func_inform(qstate, id, super); 19225039b37SCy Schubert } 19325039b37SCy Schubert 19425039b37SCy Schubert /** dynlib module cleanup query state */ 19525039b37SCy Schubert void dynlibmod_clear(struct module_qstate* qstate, int id) { 19625039b37SCy Schubert struct dynlibmod_env* de = qstate->env->modinfo[id]; 19725039b37SCy Schubert 19825039b37SCy Schubert de->func_clear(qstate, id); 19925039b37SCy Schubert } 20025039b37SCy Schubert 20125039b37SCy Schubert /** dynlib module alloc size routine */ 20225039b37SCy Schubert size_t dynlibmod_get_mem(struct module_env* env, int id) { 20325039b37SCy Schubert struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id]; 20425039b37SCy Schubert size_t size; 20525039b37SCy Schubert verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de); 20625039b37SCy Schubert if(!de) 20725039b37SCy Schubert return 0; 20825039b37SCy Schubert 20925039b37SCy Schubert size = de->func_get_mem(env, id); 21025039b37SCy Schubert return size + sizeof(*de); 21125039b37SCy Schubert } 21225039b37SCy Schubert 21325039b37SCy Schubert int dynlib_inplace_cb_reply_generic(struct query_info* qinfo, 21425039b37SCy Schubert struct module_qstate* qstate, struct reply_info* rep, int rcode, 21525039b37SCy Schubert struct edns_data* edns, struct edns_option** opt_list_out, 216f44e67d1SCy Schubert struct comm_reply* repinfo, struct regional* region, 217f44e67d1SCy Schubert struct timeval* start_time, int id, void* callback) { 21825039b37SCy Schubert struct cb_pair* cb_pair = (struct cb_pair*) callback; 219f44e67d1SCy Schubert return ((inplace_cb_reply_func_type*) cb_pair->cb)(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, region, start_time, id, cb_pair->cb_arg); 22025039b37SCy Schubert } 22125039b37SCy Schubert 22225039b37SCy Schubert int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags, 22325039b37SCy Schubert struct module_qstate* qstate, struct sockaddr_storage* addr, 22425039b37SCy Schubert socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region, 22525039b37SCy Schubert int id, void* callback) { 22625039b37SCy Schubert struct cb_pair* cb_pair = (struct cb_pair*) callback; 22725039b37SCy Schubert return ((inplace_cb_query_func_type*) cb_pair->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, id, cb_pair->cb_arg); 22825039b37SCy Schubert } 22925039b37SCy Schubert 23025039b37SCy Schubert int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate, 23125039b37SCy Schubert int id, void* cb_args) { 23225039b37SCy Schubert struct cb_pair* cb_pair = (struct cb_pair*) cb_args; 23325039b37SCy Schubert return ((inplace_cb_edns_back_parsed_func_type*) cb_pair->cb)(qstate, id, cb_pair->cb_arg); 23425039b37SCy Schubert } 23525039b37SCy Schubert 23625039b37SCy Schubert int dynlib_inplace_cb_query_response(struct module_qstate* qstate, 23725039b37SCy Schubert struct dns_msg* response, int id, void* cb_args) { 23825039b37SCy Schubert struct cb_pair* cb_pair = (struct cb_pair*) cb_args; 23925039b37SCy Schubert return ((inplace_cb_query_response_func_type*) cb_pair->cb)(qstate, response, id, cb_pair->cb_arg); 24025039b37SCy Schubert } 24125039b37SCy Schubert 24225039b37SCy Schubert int 24325039b37SCy Schubert inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg, 24425039b37SCy Schubert struct module_env* env, int id) { 24525039b37SCy Schubert struct cb_pair* cb_pair = malloc(sizeof(struct cb_pair)); 246c0caa2e2SCy Schubert if(cb_pair == NULL) { 247c0caa2e2SCy Schubert log_err("dynlibmod[%d]: malloc failure", id); 248c0caa2e2SCy Schubert return 0; 249c0caa2e2SCy Schubert } 25025039b37SCy Schubert cb_pair->cb = cb; 25125039b37SCy Schubert cb_pair->cb_arg = cbarg; 25225039b37SCy Schubert if(type >= inplace_cb_reply && type <= inplace_cb_reply_servfail) { 25325039b37SCy Schubert return inplace_cb_register(&dynlib_inplace_cb_reply_generic, type, (void*) cb_pair, env, id); 25425039b37SCy Schubert } else if(type == inplace_cb_query) { 25525039b37SCy Schubert return inplace_cb_register(&dynlib_inplace_cb_query_generic, type, (void*) cb_pair, env, id); 25625039b37SCy Schubert } else if(type == inplace_cb_query_response) { 25725039b37SCy Schubert return inplace_cb_register(&dynlib_inplace_cb_query_response, type, (void*) cb_pair, env, id); 25825039b37SCy Schubert } else if(type == inplace_cb_edns_back_parsed) { 25925039b37SCy Schubert return inplace_cb_register(&dynlib_inplace_cb_edns_back_parsed, type, (void*) cb_pair, env, id); 26025039b37SCy Schubert } else { 261c0caa2e2SCy Schubert free(cb_pair); 26225039b37SCy Schubert return 0; 26325039b37SCy Schubert } 26425039b37SCy Schubert } 26525039b37SCy Schubert 26625039b37SCy Schubert void 26725039b37SCy Schubert inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type, 26825039b37SCy Schubert int id) { 26925039b37SCy Schubert struct inplace_cb* temp = env->inplace_cb_lists[type]; 27025039b37SCy Schubert struct inplace_cb* prev = NULL; 27125039b37SCy Schubert 27225039b37SCy Schubert while(temp) { 27325039b37SCy Schubert if(temp->id == id) { 27425039b37SCy Schubert if(!prev) { 27525039b37SCy Schubert env->inplace_cb_lists[type] = temp->next; 27625039b37SCy Schubert free(temp->cb_arg); 27725039b37SCy Schubert free(temp); 27825039b37SCy Schubert temp = env->inplace_cb_lists[type]; 27925039b37SCy Schubert } 28025039b37SCy Schubert else { 28125039b37SCy Schubert prev->next = temp->next; 28225039b37SCy Schubert free(temp->cb_arg); 28325039b37SCy Schubert free(temp); 28425039b37SCy Schubert temp = prev->next; 28525039b37SCy Schubert } 28625039b37SCy Schubert } 28725039b37SCy Schubert else { 28825039b37SCy Schubert prev = temp; 28925039b37SCy Schubert temp = temp->next; 29025039b37SCy Schubert } 29125039b37SCy Schubert } 29225039b37SCy Schubert } 29325039b37SCy Schubert 29425039b37SCy Schubert 29525039b37SCy Schubert /** 29625039b37SCy Schubert * The module function block 29725039b37SCy Schubert */ 29825039b37SCy Schubert static struct module_func_block dynlibmod_block = { 29925039b37SCy Schubert "dynlib", 300*56850988SCy Schubert NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, 301*56850988SCy Schubert &dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem 30225039b37SCy Schubert }; 30325039b37SCy Schubert 30425039b37SCy Schubert struct module_func_block* dynlibmod_get_funcblock(void) 30525039b37SCy Schubert { 30625039b37SCy Schubert return &dynlibmod_block; 30725039b37SCy Schubert } 308