diff options
Diffstat (limited to 'external/unbound/util/module.c')
-rw-r--r-- | external/unbound/util/module.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/external/unbound/util/module.c b/external/unbound/util/module.c index 09e276c30..f4b715d14 100644 --- a/external/unbound/util/module.c +++ b/external/unbound/util/module.c @@ -39,6 +39,7 @@ #include "config.h" #include "util/module.h" +#include "sldns/wire2str.h" const char* strextstate(enum module_ext_state s) @@ -69,3 +70,169 @@ strmodulevent(enum module_ev e) } return "bad_event_value"; } + +int +edns_known_options_init(struct module_env* env) +{ + env->edns_known_options_num = 0; + env->edns_known_options = (struct edns_known_option*)calloc( + MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option)); + if(!env->edns_known_options) return 0; + return 1; +} + +void +edns_known_options_delete(struct module_env* env) +{ + free(env->edns_known_options); + env->edns_known_options = NULL; + env->edns_known_options_num = 0; +} + +int +edns_register_option(uint16_t opt_code, int bypass_cache_stage, + int no_aggregation, struct module_env* env) +{ + size_t i; + if(env->worker) { + log_err("invalid edns registration: " + "trying to register option after module init phase"); + return 0; + } + + /** + * Checking if we are full first is faster but it does not provide + * the option to change the flags when the array is full. + * It only impacts unbound initialization, leave it for now. + */ + /* Check if the option is already registered. */ + for(i=0; i<env->edns_known_options_num; i++) + if(env->edns_known_options[i].opt_code == opt_code) + break; + /* If it is not yet registered check if we have space to add a new one. */ + if(i == env->edns_known_options_num) { + if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) { + log_err("invalid edns registration: maximum options reached"); + return 0; + } + env->edns_known_options_num++; + } + env->edns_known_options[i].opt_code = opt_code; + env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage; + env->edns_known_options[i].no_aggregation = no_aggregation; + return 1; +} + +int +inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg, + struct module_env* env, int id) +{ + struct inplace_cb* callback; + struct inplace_cb** prevp; + if(env->worker) { + log_err("invalid edns callback registration: " + "trying to register callback after module init phase"); + return 0; + } + + callback = (struct inplace_cb*)calloc(1, sizeof(*callback)); + if(callback == NULL) { + log_err("out of memory during edns callback registration."); + return 0; + } + callback->id = id; + callback->next = NULL; + callback->cb = cb; + callback->cb_arg = cbarg; + + prevp = (struct inplace_cb**) &env->inplace_cb_lists[type]; + /* append at end of list */ + while(*prevp != NULL) + prevp = &((*prevp)->next); + *prevp = callback; + return 1; +} + +void +inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type, + int id) +{ + struct inplace_cb* temp = env->inplace_cb_lists[type]; + struct inplace_cb* prev = NULL; + + while(temp) { + if(temp->id == id) { + if(!prev) { + env->inplace_cb_lists[type] = temp->next; + free(temp); + temp = env->inplace_cb_lists[type]; + } + else { + prev->next = temp->next; + free(temp); + temp = prev->next; + } + } + else { + prev = temp; + temp = temp->next; + } + } +} + +struct edns_known_option* +edns_option_is_known(uint16_t opt_code, struct module_env* env) +{ + size_t i; + for(i=0; i<env->edns_known_options_num; i++) + if(env->edns_known_options[i].opt_code == opt_code) + return env->edns_known_options + i; + return NULL; +} + +int +edns_bypass_cache_stage(struct edns_option* list, struct module_env* env) +{ + size_t i; + for(; list; list=list->next) + for(i=0; i<env->edns_known_options_num; i++) + if(env->edns_known_options[i].opt_code == list->opt_code && + env->edns_known_options[i].bypass_cache_stage == 1) + return 1; + return 0; +} + +int +unique_mesh_state(struct edns_option* list, struct module_env* env) +{ + size_t i; + if(env->unique_mesh) + return 1; + for(; list; list=list->next) + for(i=0; i<env->edns_known_options_num; i++) + if(env->edns_known_options[i].opt_code == list->opt_code && + env->edns_known_options[i].no_aggregation == 1) + return 1; + return 0; +} + +void +log_edns_known_options(enum verbosity_value level, struct module_env* env) +{ + size_t i; + char str[32], *s; + size_t slen; + if(env->edns_known_options_num > 0 && verbosity >= level) { + verbose(level, "EDNS known options:"); + verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:"); + for(i=0; i<env->edns_known_options_num; i++) { + s = str; + slen = sizeof(str); + (void)sldns_wire2str_edns_option_code_print(&s, &slen, + env->edns_known_options[i].opt_code); + verbose(level, " %-8.8s %-19s %-15s", str, + env->edns_known_options[i].bypass_cache_stage?"YES":"NO", + env->edns_known_options[i].no_aggregation?"NO":"YES"); + } + } +} |