1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * util/module.c - module interface 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav /** 36b7579f77SDag-Erling Smørgrav * \file 37b7579f77SDag-Erling Smørgrav * Implementation of module.h. 38b7579f77SDag-Erling Smørgrav */ 39b7579f77SDag-Erling Smørgrav 40b7579f77SDag-Erling Smørgrav #include "config.h" 41b7579f77SDag-Erling Smørgrav #include "util/module.h" 42bc892140SDag-Erling Smørgrav #include "sldns/wire2str.h" 43b7579f77SDag-Erling Smørgrav 44b7579f77SDag-Erling Smørgrav const char* 45b7579f77SDag-Erling Smørgrav strextstate(enum module_ext_state s) 46b7579f77SDag-Erling Smørgrav { 47b7579f77SDag-Erling Smørgrav switch(s) { 48b7579f77SDag-Erling Smørgrav case module_state_initial: return "module_state_initial"; 49b7579f77SDag-Erling Smørgrav case module_wait_reply: return "module_wait_reply"; 50b7579f77SDag-Erling Smørgrav case module_wait_module: return "module_wait_module"; 51b7579f77SDag-Erling Smørgrav case module_restart_next: return "module_restart_next"; 52b7579f77SDag-Erling Smørgrav case module_wait_subquery: return "module_wait_subquery"; 53b7579f77SDag-Erling Smørgrav case module_error: return "module_error"; 54b7579f77SDag-Erling Smørgrav case module_finished: return "module_finished"; 55b7579f77SDag-Erling Smørgrav } 56b7579f77SDag-Erling Smørgrav return "bad_extstate_value"; 57b7579f77SDag-Erling Smørgrav } 58b7579f77SDag-Erling Smørgrav 59b7579f77SDag-Erling Smørgrav const char* 60b7579f77SDag-Erling Smørgrav strmodulevent(enum module_ev e) 61b7579f77SDag-Erling Smørgrav { 62b7579f77SDag-Erling Smørgrav switch(e) { 63b7579f77SDag-Erling Smørgrav case module_event_new: return "module_event_new"; 64b7579f77SDag-Erling Smørgrav case module_event_pass: return "module_event_pass"; 65b7579f77SDag-Erling Smørgrav case module_event_reply: return "module_event_reply"; 66b7579f77SDag-Erling Smørgrav case module_event_noreply: return "module_event_noreply"; 67b7579f77SDag-Erling Smørgrav case module_event_capsfail: return "module_event_capsfail"; 68b7579f77SDag-Erling Smørgrav case module_event_moddone: return "module_event_moddone"; 69b7579f77SDag-Erling Smørgrav case module_event_error: return "module_event_error"; 70b7579f77SDag-Erling Smørgrav } 71b7579f77SDag-Erling Smørgrav return "bad_event_value"; 72b7579f77SDag-Erling Smørgrav } 73bc892140SDag-Erling Smørgrav 74bc892140SDag-Erling Smørgrav int 75bc892140SDag-Erling Smørgrav edns_known_options_init(struct module_env* env) 76bc892140SDag-Erling Smørgrav { 77bc892140SDag-Erling Smørgrav env->edns_known_options_num = 0; 78bc892140SDag-Erling Smørgrav env->edns_known_options = (struct edns_known_option*)calloc( 79bc892140SDag-Erling Smørgrav MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option)); 80bc892140SDag-Erling Smørgrav if(!env->edns_known_options) return 0; 81bc892140SDag-Erling Smørgrav return 1; 82bc892140SDag-Erling Smørgrav } 83bc892140SDag-Erling Smørgrav 84bc892140SDag-Erling Smørgrav void 85bc892140SDag-Erling Smørgrav edns_known_options_delete(struct module_env* env) 86bc892140SDag-Erling Smørgrav { 87bc892140SDag-Erling Smørgrav free(env->edns_known_options); 88bc892140SDag-Erling Smørgrav env->edns_known_options = NULL; 89bc892140SDag-Erling Smørgrav env->edns_known_options_num = 0; 90bc892140SDag-Erling Smørgrav } 91bc892140SDag-Erling Smørgrav 92bc892140SDag-Erling Smørgrav int 93bc892140SDag-Erling Smørgrav edns_register_option(uint16_t opt_code, int bypass_cache_stage, 94bc892140SDag-Erling Smørgrav int no_aggregation, struct module_env* env) 95bc892140SDag-Erling Smørgrav { 96bc892140SDag-Erling Smørgrav size_t i; 97bc892140SDag-Erling Smørgrav if(env->worker) { 98bc892140SDag-Erling Smørgrav log_err("invalid edns registration: " 99bc892140SDag-Erling Smørgrav "trying to register option after module init phase"); 100bc892140SDag-Erling Smørgrav return 0; 101bc892140SDag-Erling Smørgrav } 102bc892140SDag-Erling Smørgrav 103bc892140SDag-Erling Smørgrav /** 104bc892140SDag-Erling Smørgrav * Checking if we are full first is faster but it does not provide 105bc892140SDag-Erling Smørgrav * the option to change the flags when the array is full. 106bc892140SDag-Erling Smørgrav * It only impacts unbound initialization, leave it for now. 107bc892140SDag-Erling Smørgrav */ 108bc892140SDag-Erling Smørgrav /* Check if the option is already registered. */ 109bc892140SDag-Erling Smørgrav for(i=0; i<env->edns_known_options_num; i++) 110bc892140SDag-Erling Smørgrav if(env->edns_known_options[i].opt_code == opt_code) 111bc892140SDag-Erling Smørgrav break; 112bc892140SDag-Erling Smørgrav /* If it is not yet registered check if we have space to add a new one. */ 113bc892140SDag-Erling Smørgrav if(i == env->edns_known_options_num) { 114bc892140SDag-Erling Smørgrav if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) { 115bc892140SDag-Erling Smørgrav log_err("invalid edns registration: maximum options reached"); 116bc892140SDag-Erling Smørgrav return 0; 117bc892140SDag-Erling Smørgrav } 118bc892140SDag-Erling Smørgrav env->edns_known_options_num++; 119bc892140SDag-Erling Smørgrav } 120bc892140SDag-Erling Smørgrav env->edns_known_options[i].opt_code = opt_code; 121bc892140SDag-Erling Smørgrav env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage; 122bc892140SDag-Erling Smørgrav env->edns_known_options[i].no_aggregation = no_aggregation; 123bc892140SDag-Erling Smørgrav return 1; 124bc892140SDag-Erling Smørgrav } 125bc892140SDag-Erling Smørgrav 126*65b390aaSDag-Erling Smørgrav int 127*65b390aaSDag-Erling Smørgrav inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg, 128*65b390aaSDag-Erling Smørgrav struct module_env* env, int id) 129bc892140SDag-Erling Smørgrav { 130*65b390aaSDag-Erling Smørgrav struct inplace_cb* callback; 131*65b390aaSDag-Erling Smørgrav struct inplace_cb** prevp; 132bc892140SDag-Erling Smørgrav if(env->worker) { 133bc892140SDag-Erling Smørgrav log_err("invalid edns callback registration: " 134bc892140SDag-Erling Smørgrav "trying to register callback after module init phase"); 135bc892140SDag-Erling Smørgrav return 0; 136bc892140SDag-Erling Smørgrav } 137bc892140SDag-Erling Smørgrav 138*65b390aaSDag-Erling Smørgrav callback = (struct inplace_cb*)calloc(1, sizeof(*callback)); 139bc892140SDag-Erling Smørgrav if(callback == NULL) { 140bc892140SDag-Erling Smørgrav log_err("out of memory during edns callback registration."); 141bc892140SDag-Erling Smørgrav return 0; 142bc892140SDag-Erling Smørgrav } 143*65b390aaSDag-Erling Smørgrav callback->id = id; 144bc892140SDag-Erling Smørgrav callback->next = NULL; 145bc892140SDag-Erling Smørgrav callback->cb = cb; 146*65b390aaSDag-Erling Smørgrav callback->cb_arg = cbarg; 147bc892140SDag-Erling Smørgrav 148*65b390aaSDag-Erling Smørgrav prevp = (struct inplace_cb**) &env->inplace_cb_lists[type]; 149bc892140SDag-Erling Smørgrav /* append at end of list */ 150bc892140SDag-Erling Smørgrav while(*prevp != NULL) 151bc892140SDag-Erling Smørgrav prevp = &((*prevp)->next); 152bc892140SDag-Erling Smørgrav *prevp = callback; 153bc892140SDag-Erling Smørgrav return 1; 154bc892140SDag-Erling Smørgrav } 155bc892140SDag-Erling Smørgrav 156bc892140SDag-Erling Smørgrav void 157*65b390aaSDag-Erling Smørgrav inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type, 158*65b390aaSDag-Erling Smørgrav int id) 159bc892140SDag-Erling Smørgrav { 160*65b390aaSDag-Erling Smørgrav struct inplace_cb* temp = env->inplace_cb_lists[type]; 161*65b390aaSDag-Erling Smørgrav struct inplace_cb* prev = NULL; 162bc892140SDag-Erling Smørgrav 163*65b390aaSDag-Erling Smørgrav while(temp) { 164*65b390aaSDag-Erling Smørgrav if(temp->id == id) { 165*65b390aaSDag-Erling Smørgrav if(!prev) { 166*65b390aaSDag-Erling Smørgrav env->inplace_cb_lists[type] = temp->next; 167*65b390aaSDag-Erling Smørgrav free(temp); 168*65b390aaSDag-Erling Smørgrav temp = env->inplace_cb_lists[type]; 169*65b390aaSDag-Erling Smørgrav } 170*65b390aaSDag-Erling Smørgrav else { 171*65b390aaSDag-Erling Smørgrav prev->next = temp->next; 172*65b390aaSDag-Erling Smørgrav free(temp); 173*65b390aaSDag-Erling Smørgrav temp = prev->next; 174*65b390aaSDag-Erling Smørgrav } 175*65b390aaSDag-Erling Smørgrav } 176*65b390aaSDag-Erling Smørgrav else { 177*65b390aaSDag-Erling Smørgrav prev = temp; 178*65b390aaSDag-Erling Smørgrav temp = temp->next; 179*65b390aaSDag-Erling Smørgrav } 180*65b390aaSDag-Erling Smørgrav } 181bc892140SDag-Erling Smørgrav } 182bc892140SDag-Erling Smørgrav 183bc892140SDag-Erling Smørgrav struct edns_known_option* 184bc892140SDag-Erling Smørgrav edns_option_is_known(uint16_t opt_code, struct module_env* env) 185bc892140SDag-Erling Smørgrav { 186bc892140SDag-Erling Smørgrav size_t i; 187bc892140SDag-Erling Smørgrav for(i=0; i<env->edns_known_options_num; i++) 188bc892140SDag-Erling Smørgrav if(env->edns_known_options[i].opt_code == opt_code) 189bc892140SDag-Erling Smørgrav return env->edns_known_options + i; 190bc892140SDag-Erling Smørgrav return NULL; 191bc892140SDag-Erling Smørgrav } 192bc892140SDag-Erling Smørgrav 193bc892140SDag-Erling Smørgrav int 194bc892140SDag-Erling Smørgrav edns_bypass_cache_stage(struct edns_option* list, struct module_env* env) 195bc892140SDag-Erling Smørgrav { 196bc892140SDag-Erling Smørgrav size_t i; 197bc892140SDag-Erling Smørgrav for(; list; list=list->next) 198bc892140SDag-Erling Smørgrav for(i=0; i<env->edns_known_options_num; i++) 199bc892140SDag-Erling Smørgrav if(env->edns_known_options[i].opt_code == list->opt_code && 200bc892140SDag-Erling Smørgrav env->edns_known_options[i].bypass_cache_stage == 1) 201bc892140SDag-Erling Smørgrav return 1; 202bc892140SDag-Erling Smørgrav return 0; 203bc892140SDag-Erling Smørgrav } 204bc892140SDag-Erling Smørgrav 205bc892140SDag-Erling Smørgrav int 206*65b390aaSDag-Erling Smørgrav unique_mesh_state(struct edns_option* list, struct module_env* env) 207bc892140SDag-Erling Smørgrav { 208bc892140SDag-Erling Smørgrav size_t i; 209*65b390aaSDag-Erling Smørgrav if(env->unique_mesh) 210*65b390aaSDag-Erling Smørgrav return 1; 211bc892140SDag-Erling Smørgrav for(; list; list=list->next) 212bc892140SDag-Erling Smørgrav for(i=0; i<env->edns_known_options_num; i++) 213bc892140SDag-Erling Smørgrav if(env->edns_known_options[i].opt_code == list->opt_code && 214bc892140SDag-Erling Smørgrav env->edns_known_options[i].no_aggregation == 1) 215bc892140SDag-Erling Smørgrav return 1; 216bc892140SDag-Erling Smørgrav return 0; 217bc892140SDag-Erling Smørgrav } 218bc892140SDag-Erling Smørgrav 219bc892140SDag-Erling Smørgrav void 220bc892140SDag-Erling Smørgrav log_edns_known_options(enum verbosity_value level, struct module_env* env) 221bc892140SDag-Erling Smørgrav { 222bc892140SDag-Erling Smørgrav size_t i; 223bc892140SDag-Erling Smørgrav char str[32], *s; 224bc892140SDag-Erling Smørgrav size_t slen; 225bc892140SDag-Erling Smørgrav if(env->edns_known_options_num > 0 && verbosity >= level) { 226bc892140SDag-Erling Smørgrav verbose(level, "EDNS known options:"); 227bc892140SDag-Erling Smørgrav verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:"); 228bc892140SDag-Erling Smørgrav for(i=0; i<env->edns_known_options_num; i++) { 229bc892140SDag-Erling Smørgrav s = str; 230bc892140SDag-Erling Smørgrav slen = sizeof(str); 231bc892140SDag-Erling Smørgrav (void)sldns_wire2str_edns_option_code_print(&s, &slen, 232bc892140SDag-Erling Smørgrav env->edns_known_options[i].opt_code); 233bc892140SDag-Erling Smørgrav verbose(level, " %-8.8s %-19s %-15s", str, 234bc892140SDag-Erling Smørgrav env->edns_known_options[i].bypass_cache_stage?"YES":"NO", 235bc892140SDag-Erling Smørgrav env->edns_known_options[i].no_aggregation?"NO":"YES"); 236bc892140SDag-Erling Smørgrav } 237bc892140SDag-Erling Smørgrav } 238bc892140SDag-Erling Smørgrav } 239