1*b7579f77SDag-Erling Smørgrav /* 2*b7579f77SDag-Erling Smørgrav * util/config_file.c - reads and stores the config file for unbound. 3*b7579f77SDag-Erling Smørgrav * 4*b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5*b7579f77SDag-Erling Smørgrav * 6*b7579f77SDag-Erling Smørgrav * This software is open source. 7*b7579f77SDag-Erling Smørgrav * 8*b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9*b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10*b7579f77SDag-Erling Smørgrav * are met: 11*b7579f77SDag-Erling Smørgrav * 12*b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13*b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14*b7579f77SDag-Erling Smørgrav * 15*b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16*b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17*b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18*b7579f77SDag-Erling Smørgrav * 19*b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20*b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21*b7579f77SDag-Erling Smørgrav * specific prior written permission. 22*b7579f77SDag-Erling Smørgrav * 23*b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*b7579f77SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25*b7579f77SDag-Erling Smørgrav * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26*b7579f77SDag-Erling Smørgrav * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27*b7579f77SDag-Erling Smørgrav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28*b7579f77SDag-Erling Smørgrav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29*b7579f77SDag-Erling Smørgrav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30*b7579f77SDag-Erling Smørgrav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31*b7579f77SDag-Erling Smørgrav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32*b7579f77SDag-Erling Smørgrav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33*b7579f77SDag-Erling Smørgrav * POSSIBILITY OF SUCH DAMAGE. 34*b7579f77SDag-Erling Smørgrav */ 35*b7579f77SDag-Erling Smørgrav 36*b7579f77SDag-Erling Smørgrav /** 37*b7579f77SDag-Erling Smørgrav * \file 38*b7579f77SDag-Erling Smørgrav * 39*b7579f77SDag-Erling Smørgrav * This file contains functions for the config file. 40*b7579f77SDag-Erling Smørgrav */ 41*b7579f77SDag-Erling Smørgrav 42*b7579f77SDag-Erling Smørgrav #include "config.h" 43*b7579f77SDag-Erling Smørgrav #include <ctype.h> 44*b7579f77SDag-Erling Smørgrav #include <ldns/ldns.h> 45*b7579f77SDag-Erling Smørgrav #include "util/log.h" 46*b7579f77SDag-Erling Smørgrav 47*b7579f77SDag-Erling Smørgrav #include "util/configyyrename.h" 48*b7579f77SDag-Erling Smørgrav #include "util/config_file.h" 49*b7579f77SDag-Erling Smørgrav #include "util/configparser.h" 50*b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 51*b7579f77SDag-Erling Smørgrav #include "util/data/msgparse.h" 52*b7579f77SDag-Erling Smørgrav #include "util/module.h" 53*b7579f77SDag-Erling Smørgrav #include "util/regional.h" 54*b7579f77SDag-Erling Smørgrav #include "util/fptr_wlist.h" 55*b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 56*b7579f77SDag-Erling Smørgrav /** global config during parsing */ 57*b7579f77SDag-Erling Smørgrav struct config_parser_state* cfg_parser = 0; 58*b7579f77SDag-Erling Smørgrav /** lex in file */ 59*b7579f77SDag-Erling Smørgrav extern FILE* ub_c_in; 60*b7579f77SDag-Erling Smørgrav /** lex out file */ 61*b7579f77SDag-Erling Smørgrav extern FILE* ub_c_out; 62*b7579f77SDag-Erling Smørgrav /** the yacc lex generated parse function */ 63*b7579f77SDag-Erling Smørgrav int ub_c_parse(void); 64*b7579f77SDag-Erling Smørgrav /** the lexer function */ 65*b7579f77SDag-Erling Smørgrav int ub_c_lex(void); 66*b7579f77SDag-Erling Smørgrav /** wrap function */ 67*b7579f77SDag-Erling Smørgrav int ub_c_wrap(void); 68*b7579f77SDag-Erling Smørgrav 69*b7579f77SDag-Erling Smørgrav /** init ports possible for use */ 70*b7579f77SDag-Erling Smørgrav static void init_outgoing_availports(int* array, int num); 71*b7579f77SDag-Erling Smørgrav 72*b7579f77SDag-Erling Smørgrav struct config_file* 73*b7579f77SDag-Erling Smørgrav config_create(void) 74*b7579f77SDag-Erling Smørgrav { 75*b7579f77SDag-Erling Smørgrav struct config_file* cfg; 76*b7579f77SDag-Erling Smørgrav cfg = (struct config_file*)calloc(1, sizeof(struct config_file)); 77*b7579f77SDag-Erling Smørgrav if(!cfg) 78*b7579f77SDag-Erling Smørgrav return NULL; 79*b7579f77SDag-Erling Smørgrav /* the defaults if no config is present */ 80*b7579f77SDag-Erling Smørgrav cfg->verbosity = 1; 81*b7579f77SDag-Erling Smørgrav cfg->stat_interval = 0; 82*b7579f77SDag-Erling Smørgrav cfg->stat_cumulative = 0; 83*b7579f77SDag-Erling Smørgrav cfg->stat_extended = 0; 84*b7579f77SDag-Erling Smørgrav cfg->num_threads = 1; 85*b7579f77SDag-Erling Smørgrav cfg->port = UNBOUND_DNS_PORT; 86*b7579f77SDag-Erling Smørgrav cfg->do_ip4 = 1; 87*b7579f77SDag-Erling Smørgrav cfg->do_ip6 = 1; 88*b7579f77SDag-Erling Smørgrav cfg->do_udp = 1; 89*b7579f77SDag-Erling Smørgrav cfg->do_tcp = 1; 90*b7579f77SDag-Erling Smørgrav cfg->tcp_upstream = 0; 91*b7579f77SDag-Erling Smørgrav cfg->ssl_service_key = NULL; 92*b7579f77SDag-Erling Smørgrav cfg->ssl_service_pem = NULL; 93*b7579f77SDag-Erling Smørgrav cfg->ssl_port = 443; 94*b7579f77SDag-Erling Smørgrav cfg->ssl_upstream = 0; 95*b7579f77SDag-Erling Smørgrav cfg->use_syslog = 1; 96*b7579f77SDag-Erling Smørgrav cfg->log_time_ascii = 0; 97*b7579f77SDag-Erling Smørgrav cfg->log_queries = 0; 98*b7579f77SDag-Erling Smørgrav #ifndef USE_WINSOCK 99*b7579f77SDag-Erling Smørgrav # ifdef USE_MINI_EVENT 100*b7579f77SDag-Erling Smørgrav /* select max 1024 sockets */ 101*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_ports = 960; 102*b7579f77SDag-Erling Smørgrav cfg->num_queries_per_thread = 512; 103*b7579f77SDag-Erling Smørgrav # else 104*b7579f77SDag-Erling Smørgrav /* libevent can use many sockets */ 105*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_ports = 4096; 106*b7579f77SDag-Erling Smørgrav cfg->num_queries_per_thread = 1024; 107*b7579f77SDag-Erling Smørgrav # endif 108*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_tcp = 10; 109*b7579f77SDag-Erling Smørgrav cfg->incoming_num_tcp = 10; 110*b7579f77SDag-Erling Smørgrav #else 111*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_ports = 48; /* windows is limited in num fds */ 112*b7579f77SDag-Erling Smørgrav cfg->num_queries_per_thread = 24; 113*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_tcp = 2; /* leaves 64-52=12 for: 4if,1stop,thread4 */ 114*b7579f77SDag-Erling Smørgrav cfg->incoming_num_tcp = 2; 115*b7579f77SDag-Erling Smørgrav #endif 116*b7579f77SDag-Erling Smørgrav cfg->edns_buffer_size = 4096; /* 4k from rfc recommendation */ 117*b7579f77SDag-Erling Smørgrav cfg->msg_buffer_size = 65552; /* 64 k + a small margin */ 118*b7579f77SDag-Erling Smørgrav cfg->msg_cache_size = 4 * 1024 * 1024; 119*b7579f77SDag-Erling Smørgrav cfg->msg_cache_slabs = 4; 120*b7579f77SDag-Erling Smørgrav cfg->jostle_time = 200; 121*b7579f77SDag-Erling Smørgrav cfg->rrset_cache_size = 4 * 1024 * 1024; 122*b7579f77SDag-Erling Smørgrav cfg->rrset_cache_slabs = 4; 123*b7579f77SDag-Erling Smørgrav cfg->host_ttl = 900; 124*b7579f77SDag-Erling Smørgrav cfg->bogus_ttl = 60; 125*b7579f77SDag-Erling Smørgrav cfg->min_ttl = 0; 126*b7579f77SDag-Erling Smørgrav cfg->max_ttl = 3600 * 24; 127*b7579f77SDag-Erling Smørgrav cfg->prefetch = 0; 128*b7579f77SDag-Erling Smørgrav cfg->prefetch_key = 0; 129*b7579f77SDag-Erling Smørgrav cfg->infra_cache_slabs = 4; 130*b7579f77SDag-Erling Smørgrav cfg->infra_cache_numhosts = 10000; 131*b7579f77SDag-Erling Smørgrav if(!(cfg->outgoing_avail_ports = (int*)calloc(65536, sizeof(int)))) 132*b7579f77SDag-Erling Smørgrav goto error_exit; 133*b7579f77SDag-Erling Smørgrav init_outgoing_availports(cfg->outgoing_avail_ports, 65536); 134*b7579f77SDag-Erling Smørgrav if(!(cfg->username = strdup(UB_USERNAME))) goto error_exit; 135*b7579f77SDag-Erling Smørgrav #ifdef HAVE_CHROOT 136*b7579f77SDag-Erling Smørgrav if(!(cfg->chrootdir = strdup(CHROOT_DIR))) goto error_exit; 137*b7579f77SDag-Erling Smørgrav #endif 138*b7579f77SDag-Erling Smørgrav if(!(cfg->directory = strdup(RUN_DIR))) goto error_exit; 139*b7579f77SDag-Erling Smørgrav if(!(cfg->logfile = strdup(""))) goto error_exit; 140*b7579f77SDag-Erling Smørgrav if(!(cfg->pidfile = strdup(PIDFILE))) goto error_exit; 141*b7579f77SDag-Erling Smørgrav if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit; 142*b7579f77SDag-Erling Smørgrav cfg->donotqueryaddrs = NULL; 143*b7579f77SDag-Erling Smørgrav cfg->donotquery_localhost = 1; 144*b7579f77SDag-Erling Smørgrav cfg->root_hints = NULL; 145*b7579f77SDag-Erling Smørgrav cfg->do_daemonize = 1; 146*b7579f77SDag-Erling Smørgrav cfg->if_automatic = 0; 147*b7579f77SDag-Erling Smørgrav cfg->so_rcvbuf = 0; 148*b7579f77SDag-Erling Smørgrav cfg->so_sndbuf = 0; 149*b7579f77SDag-Erling Smørgrav cfg->num_ifs = 0; 150*b7579f77SDag-Erling Smørgrav cfg->ifs = NULL; 151*b7579f77SDag-Erling Smørgrav cfg->num_out_ifs = 0; 152*b7579f77SDag-Erling Smørgrav cfg->out_ifs = NULL; 153*b7579f77SDag-Erling Smørgrav cfg->stubs = NULL; 154*b7579f77SDag-Erling Smørgrav cfg->forwards = NULL; 155*b7579f77SDag-Erling Smørgrav cfg->acls = NULL; 156*b7579f77SDag-Erling Smørgrav cfg->harden_short_bufsize = 0; 157*b7579f77SDag-Erling Smørgrav cfg->harden_large_queries = 0; 158*b7579f77SDag-Erling Smørgrav cfg->harden_glue = 1; 159*b7579f77SDag-Erling Smørgrav cfg->harden_dnssec_stripped = 1; 160*b7579f77SDag-Erling Smørgrav cfg->harden_below_nxdomain = 0; 161*b7579f77SDag-Erling Smørgrav cfg->harden_referral_path = 0; 162*b7579f77SDag-Erling Smørgrav cfg->use_caps_bits_for_id = 0; 163*b7579f77SDag-Erling Smørgrav cfg->private_address = NULL; 164*b7579f77SDag-Erling Smørgrav cfg->private_domain = NULL; 165*b7579f77SDag-Erling Smørgrav cfg->unwanted_threshold = 0; 166*b7579f77SDag-Erling Smørgrav cfg->hide_identity = 0; 167*b7579f77SDag-Erling Smørgrav cfg->hide_version = 0; 168*b7579f77SDag-Erling Smørgrav cfg->identity = NULL; 169*b7579f77SDag-Erling Smørgrav cfg->version = NULL; 170*b7579f77SDag-Erling Smørgrav cfg->auto_trust_anchor_file_list = NULL; 171*b7579f77SDag-Erling Smørgrav cfg->trust_anchor_file_list = NULL; 172*b7579f77SDag-Erling Smørgrav cfg->trust_anchor_list = NULL; 173*b7579f77SDag-Erling Smørgrav cfg->trusted_keys_file_list = NULL; 174*b7579f77SDag-Erling Smørgrav cfg->dlv_anchor_file = NULL; 175*b7579f77SDag-Erling Smørgrav cfg->dlv_anchor_list = NULL; 176*b7579f77SDag-Erling Smørgrav cfg->domain_insecure = NULL; 177*b7579f77SDag-Erling Smørgrav cfg->val_date_override = 0; 178*b7579f77SDag-Erling Smørgrav cfg->val_sig_skew_min = 3600; /* at least daylight savings trouble */ 179*b7579f77SDag-Erling Smørgrav cfg->val_sig_skew_max = 86400; /* at most timezone settings trouble */ 180*b7579f77SDag-Erling Smørgrav cfg->val_clean_additional = 1; 181*b7579f77SDag-Erling Smørgrav cfg->val_log_level = 0; 182*b7579f77SDag-Erling Smørgrav cfg->val_log_squelch = 0; 183*b7579f77SDag-Erling Smørgrav cfg->val_permissive_mode = 0; 184*b7579f77SDag-Erling Smørgrav cfg->ignore_cd = 0; 185*b7579f77SDag-Erling Smørgrav cfg->add_holddown = 30*24*3600; 186*b7579f77SDag-Erling Smørgrav cfg->del_holddown = 30*24*3600; 187*b7579f77SDag-Erling Smørgrav cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */ 188*b7579f77SDag-Erling Smørgrav cfg->key_cache_size = 4 * 1024 * 1024; 189*b7579f77SDag-Erling Smørgrav cfg->key_cache_slabs = 4; 190*b7579f77SDag-Erling Smørgrav cfg->neg_cache_size = 1 * 1024 * 1024; 191*b7579f77SDag-Erling Smørgrav cfg->local_zones = NULL; 192*b7579f77SDag-Erling Smørgrav cfg->local_zones_nodefault = NULL; 193*b7579f77SDag-Erling Smørgrav cfg->local_data = NULL; 194*b7579f77SDag-Erling Smørgrav cfg->python_script = NULL; 195*b7579f77SDag-Erling Smørgrav cfg->remote_control_enable = 0; 196*b7579f77SDag-Erling Smørgrav cfg->control_ifs = NULL; 197*b7579f77SDag-Erling Smørgrav cfg->control_port = UNBOUND_CONTROL_PORT; 198*b7579f77SDag-Erling Smørgrav cfg->minimal_responses = 0; 199*b7579f77SDag-Erling Smørgrav cfg->rrset_roundrobin = 0; 200*b7579f77SDag-Erling Smørgrav if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key"))) 201*b7579f77SDag-Erling Smørgrav goto error_exit; 202*b7579f77SDag-Erling Smørgrav if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem"))) 203*b7579f77SDag-Erling Smørgrav goto error_exit; 204*b7579f77SDag-Erling Smørgrav if(!(cfg->control_key_file = strdup(RUN_DIR"/unbound_control.key"))) 205*b7579f77SDag-Erling Smørgrav goto error_exit; 206*b7579f77SDag-Erling Smørgrav if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem"))) 207*b7579f77SDag-Erling Smørgrav goto error_exit; 208*b7579f77SDag-Erling Smørgrav 209*b7579f77SDag-Erling Smørgrav if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit; 210*b7579f77SDag-Erling Smørgrav if(!(cfg->val_nsec3_key_iterations = 211*b7579f77SDag-Erling Smørgrav strdup("1024 150 2048 500 4096 2500"))) goto error_exit; 212*b7579f77SDag-Erling Smørgrav return cfg; 213*b7579f77SDag-Erling Smørgrav error_exit: 214*b7579f77SDag-Erling Smørgrav config_delete(cfg); 215*b7579f77SDag-Erling Smørgrav return NULL; 216*b7579f77SDag-Erling Smørgrav } 217*b7579f77SDag-Erling Smørgrav 218*b7579f77SDag-Erling Smørgrav struct config_file* config_create_forlib(void) 219*b7579f77SDag-Erling Smørgrav { 220*b7579f77SDag-Erling Smørgrav struct config_file* cfg = config_create(); 221*b7579f77SDag-Erling Smørgrav if(!cfg) return NULL; 222*b7579f77SDag-Erling Smørgrav /* modifications for library use, less verbose, less memory */ 223*b7579f77SDag-Erling Smørgrav free(cfg->chrootdir); 224*b7579f77SDag-Erling Smørgrav cfg->chrootdir = NULL; 225*b7579f77SDag-Erling Smørgrav cfg->verbosity = 0; 226*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_ports = 16; /* in library use, this is 'reasonable' 227*b7579f77SDag-Erling Smørgrav and probably within the ulimit(maxfds) of the user */ 228*b7579f77SDag-Erling Smørgrav cfg->outgoing_num_tcp = 2; 229*b7579f77SDag-Erling Smørgrav cfg->msg_cache_size = 1024*1024; 230*b7579f77SDag-Erling Smørgrav cfg->msg_cache_slabs = 1; 231*b7579f77SDag-Erling Smørgrav cfg->rrset_cache_size = 1024*1024; 232*b7579f77SDag-Erling Smørgrav cfg->rrset_cache_slabs = 1; 233*b7579f77SDag-Erling Smørgrav cfg->infra_cache_slabs = 1; 234*b7579f77SDag-Erling Smørgrav cfg->use_syslog = 0; 235*b7579f77SDag-Erling Smørgrav cfg->key_cache_size = 1024*1024; 236*b7579f77SDag-Erling Smørgrav cfg->key_cache_slabs = 1; 237*b7579f77SDag-Erling Smørgrav cfg->neg_cache_size = 100 * 1024; 238*b7579f77SDag-Erling Smørgrav cfg->donotquery_localhost = 0; /* allow, so that you can ask a 239*b7579f77SDag-Erling Smørgrav forward nameserver running on localhost */ 240*b7579f77SDag-Erling Smørgrav cfg->val_log_level = 2; /* to fill why_bogus with */ 241*b7579f77SDag-Erling Smørgrav cfg->val_log_squelch = 1; 242*b7579f77SDag-Erling Smørgrav return cfg; 243*b7579f77SDag-Erling Smørgrav } 244*b7579f77SDag-Erling Smørgrav 245*b7579f77SDag-Erling Smørgrav /** check that the value passed is >= 0 */ 246*b7579f77SDag-Erling Smørgrav #define IS_NUMBER_OR_ZERO \ 247*b7579f77SDag-Erling Smørgrav if(atoi(val) == 0 && strcmp(val, "0") != 0) return 0 248*b7579f77SDag-Erling Smørgrav /** check that the value passed is > 0 */ 249*b7579f77SDag-Erling Smørgrav #define IS_NONZERO_NUMBER \ 250*b7579f77SDag-Erling Smørgrav if(atoi(val) == 0) return 0 251*b7579f77SDag-Erling Smørgrav /** check that the value passed is not 0 and a power of 2 */ 252*b7579f77SDag-Erling Smørgrav #define IS_POW2_NUMBER \ 253*b7579f77SDag-Erling Smørgrav if(atoi(val) == 0 || !is_pow2((size_t)atoi(val))) return 0 254*b7579f77SDag-Erling Smørgrav /** check that the value passed is yes or no */ 255*b7579f77SDag-Erling Smørgrav #define IS_YES_OR_NO \ 256*b7579f77SDag-Erling Smørgrav if(strcmp(val, "yes") != 0 && strcmp(val, "no") != 0) return 0 257*b7579f77SDag-Erling Smørgrav /** put integer_or_zero into variable */ 258*b7579f77SDag-Erling Smørgrav #define S_NUMBER_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ 259*b7579f77SDag-Erling Smørgrav { IS_NUMBER_OR_ZERO; cfg->var = atoi(val); } 260*b7579f77SDag-Erling Smørgrav /** put integer_nonzero into variable */ 261*b7579f77SDag-Erling Smørgrav #define S_NUMBER_NONZERO(str, var) if(strcmp(opt, str) == 0) \ 262*b7579f77SDag-Erling Smørgrav { IS_NONZERO_NUMBER; cfg->var = atoi(val); } 263*b7579f77SDag-Erling Smørgrav /** put integer_or_zero into unsigned */ 264*b7579f77SDag-Erling Smørgrav #define S_UNSIGNED_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ 265*b7579f77SDag-Erling Smørgrav { IS_NUMBER_OR_ZERO; cfg->var = (unsigned)atoi(val); } 266*b7579f77SDag-Erling Smørgrav /** put integer_or_zero into size_t */ 267*b7579f77SDag-Erling Smørgrav #define S_SIZET_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ 268*b7579f77SDag-Erling Smørgrav { IS_NUMBER_OR_ZERO; cfg->var = (size_t)atoi(val); } 269*b7579f77SDag-Erling Smørgrav /** put integer_nonzero into size_t */ 270*b7579f77SDag-Erling Smørgrav #define S_SIZET_NONZERO(str, var) if(strcmp(opt, str) == 0) \ 271*b7579f77SDag-Erling Smørgrav { IS_NONZERO_NUMBER; cfg->var = (size_t)atoi(val); } 272*b7579f77SDag-Erling Smørgrav /** put yesno into variable */ 273*b7579f77SDag-Erling Smørgrav #define S_YNO(str, var) if(strcmp(opt, str) == 0) \ 274*b7579f77SDag-Erling Smørgrav { IS_YES_OR_NO; cfg->var = (strcmp(val, "yes") == 0); } 275*b7579f77SDag-Erling Smørgrav /** put memsize into variable */ 276*b7579f77SDag-Erling Smørgrav #define S_MEMSIZE(str, var) if(strcmp(opt, str)==0) \ 277*b7579f77SDag-Erling Smørgrav { return cfg_parse_memsize(val, &cfg->var); } 278*b7579f77SDag-Erling Smørgrav /** put pow2 number into variable */ 279*b7579f77SDag-Erling Smørgrav #define S_POW2(str, var) if(strcmp(opt, str)==0) \ 280*b7579f77SDag-Erling Smørgrav { IS_POW2_NUMBER; cfg->var = (size_t)atoi(val); } 281*b7579f77SDag-Erling Smørgrav /** put string into variable */ 282*b7579f77SDag-Erling Smørgrav #define S_STR(str, var) if(strcmp(opt, str)==0) \ 283*b7579f77SDag-Erling Smørgrav { free(cfg->var); return (cfg->var = strdup(val)) != NULL; } 284*b7579f77SDag-Erling Smørgrav /** put string into strlist */ 285*b7579f77SDag-Erling Smørgrav #define S_STRLIST(str, var) if(strcmp(opt, str)==0) \ 286*b7579f77SDag-Erling Smørgrav { return cfg_strlist_insert(&cfg->var, strdup(val)); } 287*b7579f77SDag-Erling Smørgrav 288*b7579f77SDag-Erling Smørgrav int config_set_option(struct config_file* cfg, const char* opt, 289*b7579f77SDag-Erling Smørgrav const char* val) 290*b7579f77SDag-Erling Smørgrav { 291*b7579f77SDag-Erling Smørgrav S_NUMBER_OR_ZERO("verbosity:", verbosity) 292*b7579f77SDag-Erling Smørgrav else if(strcmp(opt, "statistics-interval:") == 0) { 293*b7579f77SDag-Erling Smørgrav if(strcmp(val, "0") == 0 || strcmp(val, "") == 0) 294*b7579f77SDag-Erling Smørgrav cfg->stat_interval = 0; 295*b7579f77SDag-Erling Smørgrav else if(atoi(val) == 0) 296*b7579f77SDag-Erling Smørgrav return 0; 297*b7579f77SDag-Erling Smørgrav else cfg->stat_interval = atoi(val); 298*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "num_threads:") == 0) { 299*b7579f77SDag-Erling Smørgrav /* not supported, library must have 1 thread in bgworker */ 300*b7579f77SDag-Erling Smørgrav return 0; 301*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "outgoing-port-permit:") == 0) { 302*b7579f77SDag-Erling Smørgrav return cfg_mark_ports(val, 1, 303*b7579f77SDag-Erling Smørgrav cfg->outgoing_avail_ports, 65536); 304*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "outgoing-port-avoid:") == 0) { 305*b7579f77SDag-Erling Smørgrav return cfg_mark_ports(val, 0, 306*b7579f77SDag-Erling Smørgrav cfg->outgoing_avail_ports, 65536); 307*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "local-zone:") == 0) { 308*b7579f77SDag-Erling Smørgrav return cfg_parse_local_zone(cfg, val); 309*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "val-override-date:") == 0) { 310*b7579f77SDag-Erling Smørgrav if(strcmp(val, "") == 0 || strcmp(val, "0") == 0) { 311*b7579f77SDag-Erling Smørgrav cfg->val_date_override = 0; 312*b7579f77SDag-Erling Smørgrav } else if(strlen(val) == 14) { 313*b7579f77SDag-Erling Smørgrav cfg->val_date_override = cfg_convert_timeval(val); 314*b7579f77SDag-Erling Smørgrav return cfg->val_date_override != 0; 315*b7579f77SDag-Erling Smørgrav } else { 316*b7579f77SDag-Erling Smørgrav if(atoi(val) == 0) return 0; 317*b7579f77SDag-Erling Smørgrav cfg->val_date_override = (uint32_t)atoi(val); 318*b7579f77SDag-Erling Smørgrav } 319*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "local-data-ptr:") == 0) { 320*b7579f77SDag-Erling Smørgrav char* ptr = cfg_ptr_reverse((char*)opt); 321*b7579f77SDag-Erling Smørgrav return cfg_strlist_insert(&cfg->local_data, ptr); 322*b7579f77SDag-Erling Smørgrav } else if(strcmp(opt, "logfile:") == 0) { 323*b7579f77SDag-Erling Smørgrav cfg->use_syslog = 0; 324*b7579f77SDag-Erling Smørgrav free(cfg->logfile); 325*b7579f77SDag-Erling Smørgrav return (cfg->logfile = strdup(val)) != NULL; 326*b7579f77SDag-Erling Smørgrav } 327*b7579f77SDag-Erling Smørgrav else S_YNO("use-syslog:", use_syslog) 328*b7579f77SDag-Erling Smørgrav else S_YNO("extended-statistics:", stat_extended) 329*b7579f77SDag-Erling Smørgrav else S_YNO("statistics-cumulative:", stat_cumulative) 330*b7579f77SDag-Erling Smørgrav else S_YNO("do-ip4:", do_ip4) 331*b7579f77SDag-Erling Smørgrav else S_YNO("do-ip6:", do_ip6) 332*b7579f77SDag-Erling Smørgrav else S_YNO("do-udp:", do_udp) 333*b7579f77SDag-Erling Smørgrav else S_YNO("do-tcp:", do_tcp) 334*b7579f77SDag-Erling Smørgrav else S_YNO("tcp-upstream:", tcp_upstream) 335*b7579f77SDag-Erling Smørgrav else S_YNO("ssl-upstream:", ssl_upstream) 336*b7579f77SDag-Erling Smørgrav else S_STR("ssl-service-key:", ssl_service_key) 337*b7579f77SDag-Erling Smørgrav else S_STR("ssl-service-pem:", ssl_service_pem) 338*b7579f77SDag-Erling Smørgrav else S_NUMBER_NONZERO("ssl-port:", ssl_port) 339*b7579f77SDag-Erling Smørgrav else S_YNO("interface-automatic:", if_automatic) 340*b7579f77SDag-Erling Smørgrav else S_YNO("do-daemonize:", do_daemonize) 341*b7579f77SDag-Erling Smørgrav else S_NUMBER_NONZERO("port:", port) 342*b7579f77SDag-Erling Smørgrav else S_NUMBER_NONZERO("outgoing-range:", outgoing_num_ports) 343*b7579f77SDag-Erling Smørgrav else S_SIZET_OR_ZERO("outgoing-num-tcp:", outgoing_num_tcp) 344*b7579f77SDag-Erling Smørgrav else S_SIZET_OR_ZERO("incoming-num-tcp:", incoming_num_tcp) 345*b7579f77SDag-Erling Smørgrav else S_SIZET_NONZERO("edns-buffer-size:", edns_buffer_size) 346*b7579f77SDag-Erling Smørgrav else S_SIZET_NONZERO("msg-buffer-size:", msg_buffer_size) 347*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("msg-cache-size:", msg_cache_size) 348*b7579f77SDag-Erling Smørgrav else S_POW2("msg-cache-slabs:", msg_cache_slabs) 349*b7579f77SDag-Erling Smørgrav else S_SIZET_NONZERO("num-queries-per-thread:",num_queries_per_thread) 350*b7579f77SDag-Erling Smørgrav else S_SIZET_OR_ZERO("jostle-timeout:", jostle_time) 351*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("so-rcvbuf:", so_rcvbuf) 352*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("so-sndbuf:", so_sndbuf) 353*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("rrset-cache-size:", rrset_cache_size) 354*b7579f77SDag-Erling Smørgrav else S_POW2("rrset-cache-slabs:", rrset_cache_slabs) 355*b7579f77SDag-Erling Smørgrav else S_YNO("prefetch:", prefetch) 356*b7579f77SDag-Erling Smørgrav else S_YNO("prefetch-key:", prefetch_key) 357*b7579f77SDag-Erling Smørgrav else S_NUMBER_OR_ZERO("cache-max-ttl:", max_ttl) 358*b7579f77SDag-Erling Smørgrav else S_NUMBER_OR_ZERO("infra-host-ttl:", host_ttl) 359*b7579f77SDag-Erling Smørgrav else S_POW2("infra-cache-slabs:", infra_cache_slabs) 360*b7579f77SDag-Erling Smørgrav else S_SIZET_NONZERO("infra-cache-numhosts:", infra_cache_numhosts) 361*b7579f77SDag-Erling Smørgrav else S_STR("chroot:", chrootdir) 362*b7579f77SDag-Erling Smørgrav else S_STR("username:", username) 363*b7579f77SDag-Erling Smørgrav else S_STR("directory:", directory) 364*b7579f77SDag-Erling Smørgrav else S_STR("pidfile:", pidfile) 365*b7579f77SDag-Erling Smørgrav else S_YNO("hide-identity:", hide_identity) 366*b7579f77SDag-Erling Smørgrav else S_YNO("hide-version:", hide_version) 367*b7579f77SDag-Erling Smørgrav else S_STR("identity:", identity) 368*b7579f77SDag-Erling Smørgrav else S_STR("version:", version) 369*b7579f77SDag-Erling Smørgrav else S_STRLIST("root-hints:", root_hints) 370*b7579f77SDag-Erling Smørgrav else S_STR("target-fetch-policy:", target_fetch_policy) 371*b7579f77SDag-Erling Smørgrav else S_YNO("harden-glue:", harden_glue) 372*b7579f77SDag-Erling Smørgrav else S_YNO("harden-short-bufsize:", harden_short_bufsize) 373*b7579f77SDag-Erling Smørgrav else S_YNO("harden-large-queries:", harden_large_queries) 374*b7579f77SDag-Erling Smørgrav else S_YNO("harden-dnssec-stripped:", harden_dnssec_stripped) 375*b7579f77SDag-Erling Smørgrav else S_YNO("harden-below-nxdomain:", harden_below_nxdomain) 376*b7579f77SDag-Erling Smørgrav else S_YNO("harden-referral-path:", harden_referral_path) 377*b7579f77SDag-Erling Smørgrav else S_YNO("use-caps-for-id", use_caps_bits_for_id) 378*b7579f77SDag-Erling Smørgrav else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold) 379*b7579f77SDag-Erling Smørgrav else S_STRLIST("private-address:", private_address) 380*b7579f77SDag-Erling Smørgrav else S_STRLIST("private-domain:", private_domain) 381*b7579f77SDag-Erling Smørgrav else S_YNO("do-not-query-localhost:", donotquery_localhost) 382*b7579f77SDag-Erling Smørgrav else S_STRLIST("do-not-query-address:", donotqueryaddrs) 383*b7579f77SDag-Erling Smørgrav else S_STRLIST("auto-trust-anchor-file:", auto_trust_anchor_file_list) 384*b7579f77SDag-Erling Smørgrav else S_STRLIST("trust-anchor-file:", trust_anchor_file_list) 385*b7579f77SDag-Erling Smørgrav else S_STRLIST("trust-anchor:", trust_anchor_list) 386*b7579f77SDag-Erling Smørgrav else S_STRLIST("trusted-keys-file:", trusted_keys_file_list) 387*b7579f77SDag-Erling Smørgrav else S_STR("dlv-anchor-file:", dlv_anchor_file) 388*b7579f77SDag-Erling Smørgrav else S_STRLIST("dlv-anchor:", dlv_anchor_list) 389*b7579f77SDag-Erling Smørgrav else S_STRLIST("domain-insecure:", domain_insecure) 390*b7579f77SDag-Erling Smørgrav else S_NUMBER_OR_ZERO("val-bogus-ttl:", bogus_ttl) 391*b7579f77SDag-Erling Smørgrav else S_YNO("val-clean-additional:", val_clean_additional) 392*b7579f77SDag-Erling Smørgrav else S_NUMBER_OR_ZERO("val-log-level:", val_log_level) 393*b7579f77SDag-Erling Smørgrav else S_YNO("val-log-squelch:", val_log_squelch) 394*b7579f77SDag-Erling Smørgrav else S_YNO("log-queries:", log_queries) 395*b7579f77SDag-Erling Smørgrav else S_YNO("val-permissive-mode:", val_permissive_mode) 396*b7579f77SDag-Erling Smørgrav else S_YNO("ignore-cd-flag:", ignore_cd) 397*b7579f77SDag-Erling Smørgrav else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations) 398*b7579f77SDag-Erling Smørgrav else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown) 399*b7579f77SDag-Erling Smørgrav else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown) 400*b7579f77SDag-Erling Smørgrav else S_UNSIGNED_OR_ZERO("keep-missing:", keep_missing) 401*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("key-cache-size:", key_cache_size) 402*b7579f77SDag-Erling Smørgrav else S_POW2("key-cache-slabs:", key_cache_slabs) 403*b7579f77SDag-Erling Smørgrav else S_MEMSIZE("neg-cache-size:", neg_cache_size) 404*b7579f77SDag-Erling Smørgrav else S_YNO("minimal-responses:", minimal_responses) 405*b7579f77SDag-Erling Smørgrav else S_YNO("rrset-roundrobin:", rrset_roundrobin) 406*b7579f77SDag-Erling Smørgrav else S_STRLIST("local-data:", local_data) 407*b7579f77SDag-Erling Smørgrav else S_YNO("control-enable:", remote_control_enable) 408*b7579f77SDag-Erling Smørgrav else S_STRLIST("control-interface:", control_ifs) 409*b7579f77SDag-Erling Smørgrav else S_NUMBER_NONZERO("control-port:", control_port) 410*b7579f77SDag-Erling Smørgrav else S_STR("server-key-file:", server_key_file) 411*b7579f77SDag-Erling Smørgrav else S_STR("server-cert-file:", server_cert_file) 412*b7579f77SDag-Erling Smørgrav else S_STR("control-key-file:", control_key_file) 413*b7579f77SDag-Erling Smørgrav else S_STR("control-cert-file:", control_cert_file) 414*b7579f77SDag-Erling Smørgrav else S_STR("module-config:", module_conf) 415*b7579f77SDag-Erling Smørgrav else S_STR("python-script:", python_script) 416*b7579f77SDag-Erling Smørgrav else if (strcmp(opt, "outgoing-interface:") == 0) { 417*b7579f77SDag-Erling Smørgrav char* d = strdup(val); 418*b7579f77SDag-Erling Smørgrav char** oi = (char**)malloc((cfg->num_out_ifs+1)*sizeof(char*)); 419*b7579f77SDag-Erling Smørgrav if(!d || !oi) { free(d); free(oi); return -1; } 420*b7579f77SDag-Erling Smørgrav if(cfg->out_ifs && cfg->num_out_ifs) { 421*b7579f77SDag-Erling Smørgrav memmove(oi, cfg->out_ifs, cfg->num_out_ifs*sizeof(char*)); 422*b7579f77SDag-Erling Smørgrav free(cfg->out_ifs); 423*b7579f77SDag-Erling Smørgrav } 424*b7579f77SDag-Erling Smørgrav oi[cfg->num_out_ifs++] = d; 425*b7579f77SDag-Erling Smørgrav cfg->out_ifs = oi; 426*b7579f77SDag-Erling Smørgrav } else { 427*b7579f77SDag-Erling Smørgrav /* unknown or unsupported (from the set_option interface): 428*b7579f77SDag-Erling Smørgrav * interface, outgoing-interface, access-control, 429*b7579f77SDag-Erling Smørgrav * stub-zone, name, stub-addr, stub-host, stub-prime 430*b7579f77SDag-Erling Smørgrav * forward-first, stub-first, 431*b7579f77SDag-Erling Smørgrav * forward-zone, name, forward-addr, forward-host */ 432*b7579f77SDag-Erling Smørgrav return 0; 433*b7579f77SDag-Erling Smørgrav } 434*b7579f77SDag-Erling Smørgrav return 1; 435*b7579f77SDag-Erling Smørgrav } 436*b7579f77SDag-Erling Smørgrav 437*b7579f77SDag-Erling Smørgrav void config_print_func(char* line, void* arg) 438*b7579f77SDag-Erling Smørgrav { 439*b7579f77SDag-Erling Smørgrav FILE* f = (FILE*)arg; 440*b7579f77SDag-Erling Smørgrav (void)fprintf(f, "%s\n", line); 441*b7579f77SDag-Erling Smørgrav } 442*b7579f77SDag-Erling Smørgrav 443*b7579f77SDag-Erling Smørgrav /** collate func arg */ 444*b7579f77SDag-Erling Smørgrav struct config_collate_arg { 445*b7579f77SDag-Erling Smørgrav /** list of result items */ 446*b7579f77SDag-Erling Smørgrav struct config_strlist_head list; 447*b7579f77SDag-Erling Smørgrav /** if a malloc error occurred, 0 is OK */ 448*b7579f77SDag-Erling Smørgrav int status; 449*b7579f77SDag-Erling Smørgrav }; 450*b7579f77SDag-Erling Smørgrav 451*b7579f77SDag-Erling Smørgrav void config_collate_func(char* line, void* arg) 452*b7579f77SDag-Erling Smørgrav { 453*b7579f77SDag-Erling Smørgrav struct config_collate_arg* m = (struct config_collate_arg*)arg; 454*b7579f77SDag-Erling Smørgrav if(m->status) 455*b7579f77SDag-Erling Smørgrav return; 456*b7579f77SDag-Erling Smørgrav if(!cfg_strlist_append(&m->list, strdup(line))) 457*b7579f77SDag-Erling Smørgrav m->status = 1; 458*b7579f77SDag-Erling Smørgrav } 459*b7579f77SDag-Erling Smørgrav 460*b7579f77SDag-Erling Smørgrav int config_get_option_list(struct config_file* cfg, const char* opt, 461*b7579f77SDag-Erling Smørgrav struct config_strlist** list) 462*b7579f77SDag-Erling Smørgrav { 463*b7579f77SDag-Erling Smørgrav struct config_collate_arg m; 464*b7579f77SDag-Erling Smørgrav memset(&m, 0, sizeof(m)); 465*b7579f77SDag-Erling Smørgrav *list = NULL; 466*b7579f77SDag-Erling Smørgrav if(!config_get_option(cfg, opt, config_collate_func, &m)) 467*b7579f77SDag-Erling Smørgrav return 1; 468*b7579f77SDag-Erling Smørgrav if(m.status) { 469*b7579f77SDag-Erling Smørgrav config_delstrlist(m.list.first); 470*b7579f77SDag-Erling Smørgrav return 2; 471*b7579f77SDag-Erling Smørgrav } 472*b7579f77SDag-Erling Smørgrav *list = m.list.first; 473*b7579f77SDag-Erling Smørgrav return 0; 474*b7579f77SDag-Erling Smørgrav } 475*b7579f77SDag-Erling Smørgrav 476*b7579f77SDag-Erling Smørgrav int 477*b7579f77SDag-Erling Smørgrav config_get_option_collate(struct config_file* cfg, const char* opt, char** str) 478*b7579f77SDag-Erling Smørgrav { 479*b7579f77SDag-Erling Smørgrav struct config_strlist* list = NULL; 480*b7579f77SDag-Erling Smørgrav int r; 481*b7579f77SDag-Erling Smørgrav *str = NULL; 482*b7579f77SDag-Erling Smørgrav if((r = config_get_option_list(cfg, opt, &list)) != 0) 483*b7579f77SDag-Erling Smørgrav return r; 484*b7579f77SDag-Erling Smørgrav *str = config_collate_cat(list); 485*b7579f77SDag-Erling Smørgrav config_delstrlist(list); 486*b7579f77SDag-Erling Smørgrav if(!*str) return 2; 487*b7579f77SDag-Erling Smørgrav return 0; 488*b7579f77SDag-Erling Smørgrav } 489*b7579f77SDag-Erling Smørgrav 490*b7579f77SDag-Erling Smørgrav char* 491*b7579f77SDag-Erling Smørgrav config_collate_cat(struct config_strlist* list) 492*b7579f77SDag-Erling Smørgrav { 493*b7579f77SDag-Erling Smørgrav size_t total = 0, left; 494*b7579f77SDag-Erling Smørgrav struct config_strlist* s; 495*b7579f77SDag-Erling Smørgrav char *r, *w; 496*b7579f77SDag-Erling Smørgrav if(!list) /* no elements */ 497*b7579f77SDag-Erling Smørgrav return strdup(""); 498*b7579f77SDag-Erling Smørgrav if(list->next == NULL) /* one element , no newline at end. */ 499*b7579f77SDag-Erling Smørgrav return strdup(list->str); 500*b7579f77SDag-Erling Smørgrav /* count total length */ 501*b7579f77SDag-Erling Smørgrav for(s=list; s; s=s->next) 502*b7579f77SDag-Erling Smørgrav total += strlen(s->str) + 1; /* len + newline */ 503*b7579f77SDag-Erling Smørgrav left = total+1; /* one extra for nul at end */ 504*b7579f77SDag-Erling Smørgrav r = malloc(left); 505*b7579f77SDag-Erling Smørgrav if(!r) 506*b7579f77SDag-Erling Smørgrav return NULL; 507*b7579f77SDag-Erling Smørgrav w = r; 508*b7579f77SDag-Erling Smørgrav for(s=list; s; s=s->next) { 509*b7579f77SDag-Erling Smørgrav size_t this = strlen(s->str); 510*b7579f77SDag-Erling Smørgrav if(this+2 > left) { /* sanity check */ 511*b7579f77SDag-Erling Smørgrav free(r); 512*b7579f77SDag-Erling Smørgrav return NULL; 513*b7579f77SDag-Erling Smørgrav } 514*b7579f77SDag-Erling Smørgrav snprintf(w, left, "%s\n", s->str); 515*b7579f77SDag-Erling Smørgrav w += this+1; 516*b7579f77SDag-Erling Smørgrav left -= this+1; 517*b7579f77SDag-Erling Smørgrav } 518*b7579f77SDag-Erling Smørgrav return r; 519*b7579f77SDag-Erling Smørgrav } 520*b7579f77SDag-Erling Smørgrav 521*b7579f77SDag-Erling Smørgrav /** compare and print decimal option */ 522*b7579f77SDag-Erling Smørgrav #define O_DEC(opt, str, var) if(strcmp(opt, str)==0) \ 523*b7579f77SDag-Erling Smørgrav {snprintf(buf, len, "%d", (int)cfg->var); \ 524*b7579f77SDag-Erling Smørgrav func(buf, arg);} 525*b7579f77SDag-Erling Smørgrav /** compare and print unsigned option */ 526*b7579f77SDag-Erling Smørgrav #define O_UNS(opt, str, var) if(strcmp(opt, str)==0) \ 527*b7579f77SDag-Erling Smørgrav {snprintf(buf, len, "%u", (unsigned)cfg->var); \ 528*b7579f77SDag-Erling Smørgrav func(buf, arg);} 529*b7579f77SDag-Erling Smørgrav /** compare and print yesno option */ 530*b7579f77SDag-Erling Smørgrav #define O_YNO(opt, str, var) if(strcmp(opt, str)==0) \ 531*b7579f77SDag-Erling Smørgrav {func(cfg->var?"yes":"no", arg);} 532*b7579f77SDag-Erling Smørgrav /** compare and print string option */ 533*b7579f77SDag-Erling Smørgrav #define O_STR(opt, str, var) if(strcmp(opt, str)==0) \ 534*b7579f77SDag-Erling Smørgrav {func(cfg->var?cfg->var:"", arg);} 535*b7579f77SDag-Erling Smørgrav /** compare and print array option */ 536*b7579f77SDag-Erling Smørgrav #define O_IFC(opt, str, num, arr) if(strcmp(opt, str)==0) \ 537*b7579f77SDag-Erling Smørgrav {int i; for(i=0; i<cfg->num; i++) func(cfg->arr[i], arg);} 538*b7579f77SDag-Erling Smørgrav /** compare and print memorysize option */ 539*b7579f77SDag-Erling Smørgrav #define O_MEM(opt, str, var) if(strcmp(opt, str)==0) { \ 540*b7579f77SDag-Erling Smørgrav if(cfg->var > 1024*1024*1024) { \ 541*b7579f77SDag-Erling Smørgrav size_t f=cfg->var/(size_t)1000000, b=cfg->var%(size_t)1000000; \ 542*b7579f77SDag-Erling Smørgrav snprintf(buf, len, "%u%6.6u\n", (unsigned)f, (unsigned)b); \ 543*b7579f77SDag-Erling Smørgrav } else snprintf(buf, len, "%u\n", (unsigned)cfg->var); \ 544*b7579f77SDag-Erling Smørgrav func(buf, arg);} 545*b7579f77SDag-Erling Smørgrav /** compare and print list option */ 546*b7579f77SDag-Erling Smørgrav #define O_LST(opt, name, lst) if(strcmp(opt, name)==0) { \ 547*b7579f77SDag-Erling Smørgrav struct config_strlist* p = cfg->lst; \ 548*b7579f77SDag-Erling Smørgrav for(p = cfg->lst; p; p = p->next) \ 549*b7579f77SDag-Erling Smørgrav func(p->str, arg); \ 550*b7579f77SDag-Erling Smørgrav } 551*b7579f77SDag-Erling Smørgrav /** compare and print list option */ 552*b7579f77SDag-Erling Smørgrav #define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \ 553*b7579f77SDag-Erling Smørgrav struct config_str2list* p = cfg->lst; \ 554*b7579f77SDag-Erling Smørgrav for(p = cfg->lst; p; p = p->next) \ 555*b7579f77SDag-Erling Smørgrav snprintf(buf, len, "%s %s\n", p->str, p->str2); \ 556*b7579f77SDag-Erling Smørgrav func(buf, arg); \ 557*b7579f77SDag-Erling Smørgrav } 558*b7579f77SDag-Erling Smørgrav 559*b7579f77SDag-Erling Smørgrav int 560*b7579f77SDag-Erling Smørgrav config_get_option(struct config_file* cfg, const char* opt, 561*b7579f77SDag-Erling Smørgrav void (*func)(char*,void*), void* arg) 562*b7579f77SDag-Erling Smørgrav { 563*b7579f77SDag-Erling Smørgrav char buf[1024]; 564*b7579f77SDag-Erling Smørgrav size_t len = sizeof(buf); 565*b7579f77SDag-Erling Smørgrav fptr_ok(fptr_whitelist_print_func(func)); 566*b7579f77SDag-Erling Smørgrav O_DEC(opt, "verbosity", verbosity) 567*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "statistics-interval", stat_interval) 568*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "statistics-cumulative", stat_cumulative) 569*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "extended-statistics", stat_extended) 570*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "use-syslog", use_syslog) 571*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "num-threads", num_threads) 572*b7579f77SDag-Erling Smørgrav else O_IFC(opt, "interface", num_ifs, ifs) 573*b7579f77SDag-Erling Smørgrav else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs) 574*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "interface-automatic", if_automatic) 575*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "port", port) 576*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "outgoing-range", outgoing_num_ports) 577*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp) 578*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "incoming-num-tcp", incoming_num_tcp) 579*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "edns-buffer-size", edns_buffer_size) 580*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "msg-buffer-size", msg_buffer_size) 581*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "msg-cache-size", msg_cache_size) 582*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "msg-cache-slabs", msg_cache_slabs) 583*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "num-queries-per-thread", num_queries_per_thread) 584*b7579f77SDag-Erling Smørgrav else O_UNS(opt, "jostle-timeout", jostle_time) 585*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "so-rcvbuf", so_rcvbuf) 586*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "so-sndbuf", so_sndbuf) 587*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "rrset-cache-size", rrset_cache_size) 588*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs) 589*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "prefetch-key", prefetch_key) 590*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "prefetch", prefetch) 591*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "cache-max-ttl", max_ttl) 592*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "infra-host-ttl", host_ttl) 593*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs) 594*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "infra-cache-numhosts", infra_cache_numhosts) 595*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-ip4", do_ip4) 596*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-ip6", do_ip6) 597*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-udp", do_udp) 598*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-tcp", do_tcp) 599*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "tcp-upstream", tcp_upstream) 600*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "ssl-upstream", ssl_upstream) 601*b7579f77SDag-Erling Smørgrav else O_STR(opt, "ssl-service-key", ssl_service_key) 602*b7579f77SDag-Erling Smørgrav else O_STR(opt, "ssl-service-pem", ssl_service_pem) 603*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "ssl-port", ssl_port) 604*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-daemonize", do_daemonize) 605*b7579f77SDag-Erling Smørgrav else O_STR(opt, "chroot", chrootdir) 606*b7579f77SDag-Erling Smørgrav else O_STR(opt, "username", username) 607*b7579f77SDag-Erling Smørgrav else O_STR(opt, "directory", directory) 608*b7579f77SDag-Erling Smørgrav else O_STR(opt, "logfile", logfile) 609*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "log-queries", log_queries) 610*b7579f77SDag-Erling Smørgrav else O_STR(opt, "pidfile", pidfile) 611*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "hide-identity", hide_identity) 612*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "hide-version", hide_version) 613*b7579f77SDag-Erling Smørgrav else O_STR(opt, "identity", identity) 614*b7579f77SDag-Erling Smørgrav else O_STR(opt, "version", version) 615*b7579f77SDag-Erling Smørgrav else O_STR(opt, "target-fetch-policy", target_fetch_policy) 616*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-short-bufsize", harden_short_bufsize) 617*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-large-queries", harden_large_queries) 618*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-glue", harden_glue) 619*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-dnssec-stripped", harden_dnssec_stripped) 620*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-below-nxdomain", harden_below_nxdomain) 621*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "harden-referral-path", harden_referral_path) 622*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id) 623*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold) 624*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "do-not-query-localhost", donotquery_localhost) 625*b7579f77SDag-Erling Smørgrav else O_STR(opt, "module-config", module_conf) 626*b7579f77SDag-Erling Smørgrav else O_STR(opt, "dlv-anchor-file", dlv_anchor_file) 627*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "val-bogus-ttl", bogus_ttl) 628*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "val-clean-additional", val_clean_additional) 629*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "val-log-level", val_log_level) 630*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "val-permissive-mode", val_permissive_mode) 631*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "ignore-cd-flag", ignore_cd) 632*b7579f77SDag-Erling Smørgrav else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations) 633*b7579f77SDag-Erling Smørgrav else O_UNS(opt, "add-holddown", add_holddown) 634*b7579f77SDag-Erling Smørgrav else O_UNS(opt, "del-holddown", del_holddown) 635*b7579f77SDag-Erling Smørgrav else O_UNS(opt, "keep-missing", keep_missing) 636*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "key-cache-size", key_cache_size) 637*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "key-cache-slabs", key_cache_slabs) 638*b7579f77SDag-Erling Smørgrav else O_MEM(opt, "neg-cache-size", neg_cache_size) 639*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "control-enable", remote_control_enable) 640*b7579f77SDag-Erling Smørgrav else O_DEC(opt, "control-port", control_port) 641*b7579f77SDag-Erling Smørgrav else O_STR(opt, "server-key-file", server_key_file) 642*b7579f77SDag-Erling Smørgrav else O_STR(opt, "server-cert-file", server_cert_file) 643*b7579f77SDag-Erling Smørgrav else O_STR(opt, "control-key-file", control_key_file) 644*b7579f77SDag-Erling Smørgrav else O_STR(opt, "control-cert-file", control_cert_file) 645*b7579f77SDag-Erling Smørgrav else O_LST(opt, "root-hints", root_hints) 646*b7579f77SDag-Erling Smørgrav else O_LS2(opt, "access-control", acls) 647*b7579f77SDag-Erling Smørgrav else O_LST(opt, "do-not-query-address", donotqueryaddrs) 648*b7579f77SDag-Erling Smørgrav else O_LST(opt, "private-address", private_address) 649*b7579f77SDag-Erling Smørgrav else O_LST(opt, "private-domain", private_domain) 650*b7579f77SDag-Erling Smørgrav else O_LST(opt, "auto-trust-anchor-file", auto_trust_anchor_file_list) 651*b7579f77SDag-Erling Smørgrav else O_LST(opt, "trust-anchor-file", trust_anchor_file_list) 652*b7579f77SDag-Erling Smørgrav else O_LST(opt, "trust-anchor", trust_anchor_list) 653*b7579f77SDag-Erling Smørgrav else O_LST(opt, "trusted-keys-file", trusted_keys_file_list) 654*b7579f77SDag-Erling Smørgrav else O_LST(opt, "dlv-anchor", dlv_anchor_list) 655*b7579f77SDag-Erling Smørgrav else O_LST(opt, "control-interface", control_ifs) 656*b7579f77SDag-Erling Smørgrav else O_LST(opt, "domain-insecure", domain_insecure) 657*b7579f77SDag-Erling Smørgrav else O_UNS(opt, "val-override-date", val_date_override) 658*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "minimal-responses", minimal_responses) 659*b7579f77SDag-Erling Smørgrav else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin) 660*b7579f77SDag-Erling Smørgrav /* not here: 661*b7579f77SDag-Erling Smørgrav * outgoing-permit, outgoing-avoid - have list of ports 662*b7579f77SDag-Erling Smørgrav * local-zone - zones and nodefault variables 663*b7579f77SDag-Erling Smørgrav * local-data - see below 664*b7579f77SDag-Erling Smørgrav * local-data-ptr - converted to local-data entries 665*b7579f77SDag-Erling Smørgrav * stub-zone, name, stub-addr, stub-host, stub-prime 666*b7579f77SDag-Erling Smørgrav * forward-zone, name, forward-addr, forward-host 667*b7579f77SDag-Erling Smørgrav */ 668*b7579f77SDag-Erling Smørgrav else return 0; 669*b7579f77SDag-Erling Smørgrav return 1; 670*b7579f77SDag-Erling Smørgrav } 671*b7579f77SDag-Erling Smørgrav 672*b7579f77SDag-Erling Smørgrav /** initialize the global cfg_parser object */ 673*b7579f77SDag-Erling Smørgrav static void 674*b7579f77SDag-Erling Smørgrav create_cfg_parser(struct config_file* cfg, char* filename, const char* chroot) 675*b7579f77SDag-Erling Smørgrav { 676*b7579f77SDag-Erling Smørgrav static struct config_parser_state st; 677*b7579f77SDag-Erling Smørgrav cfg_parser = &st; 678*b7579f77SDag-Erling Smørgrav cfg_parser->filename = filename; 679*b7579f77SDag-Erling Smørgrav cfg_parser->line = 1; 680*b7579f77SDag-Erling Smørgrav cfg_parser->errors = 0; 681*b7579f77SDag-Erling Smørgrav cfg_parser->cfg = cfg; 682*b7579f77SDag-Erling Smørgrav cfg_parser->chroot = chroot; 683*b7579f77SDag-Erling Smørgrav } 684*b7579f77SDag-Erling Smørgrav 685*b7579f77SDag-Erling Smørgrav int 686*b7579f77SDag-Erling Smørgrav config_read(struct config_file* cfg, const char* filename, const char* chroot) 687*b7579f77SDag-Erling Smørgrav { 688*b7579f77SDag-Erling Smørgrav FILE *in; 689*b7579f77SDag-Erling Smørgrav char *fname = (char*)filename; 690*b7579f77SDag-Erling Smørgrav if(!fname) 691*b7579f77SDag-Erling Smørgrav return 1; 692*b7579f77SDag-Erling Smørgrav in = fopen(fname, "r"); 693*b7579f77SDag-Erling Smørgrav if(!in) { 694*b7579f77SDag-Erling Smørgrav log_err("Could not open %s: %s", fname, strerror(errno)); 695*b7579f77SDag-Erling Smørgrav return 0; 696*b7579f77SDag-Erling Smørgrav } 697*b7579f77SDag-Erling Smørgrav create_cfg_parser(cfg, fname, chroot); 698*b7579f77SDag-Erling Smørgrav ub_c_in = in; 699*b7579f77SDag-Erling Smørgrav ub_c_parse(); 700*b7579f77SDag-Erling Smørgrav fclose(in); 701*b7579f77SDag-Erling Smørgrav 702*b7579f77SDag-Erling Smørgrav if(cfg_parser->errors != 0) { 703*b7579f77SDag-Erling Smørgrav fprintf(stderr, "read %s failed: %d errors in configuration file\n", 704*b7579f77SDag-Erling Smørgrav cfg_parser->filename, cfg_parser->errors); 705*b7579f77SDag-Erling Smørgrav errno=EINVAL; 706*b7579f77SDag-Erling Smørgrav return 0; 707*b7579f77SDag-Erling Smørgrav } 708*b7579f77SDag-Erling Smørgrav return 1; 709*b7579f77SDag-Erling Smørgrav } 710*b7579f77SDag-Erling Smørgrav 711*b7579f77SDag-Erling Smørgrav void 712*b7579f77SDag-Erling Smørgrav config_delstrlist(struct config_strlist* p) 713*b7579f77SDag-Erling Smørgrav { 714*b7579f77SDag-Erling Smørgrav struct config_strlist *np; 715*b7579f77SDag-Erling Smørgrav while(p) { 716*b7579f77SDag-Erling Smørgrav np = p->next; 717*b7579f77SDag-Erling Smørgrav free(p->str); 718*b7579f77SDag-Erling Smørgrav free(p); 719*b7579f77SDag-Erling Smørgrav p = np; 720*b7579f77SDag-Erling Smørgrav } 721*b7579f77SDag-Erling Smørgrav } 722*b7579f77SDag-Erling Smørgrav 723*b7579f77SDag-Erling Smørgrav void 724*b7579f77SDag-Erling Smørgrav config_deldblstrlist(struct config_str2list* p) 725*b7579f77SDag-Erling Smørgrav { 726*b7579f77SDag-Erling Smørgrav struct config_str2list *np; 727*b7579f77SDag-Erling Smørgrav while(p) { 728*b7579f77SDag-Erling Smørgrav np = p->next; 729*b7579f77SDag-Erling Smørgrav free(p->str); 730*b7579f77SDag-Erling Smørgrav free(p->str2); 731*b7579f77SDag-Erling Smørgrav free(p); 732*b7579f77SDag-Erling Smørgrav p = np; 733*b7579f77SDag-Erling Smørgrav } 734*b7579f77SDag-Erling Smørgrav } 735*b7579f77SDag-Erling Smørgrav 736*b7579f77SDag-Erling Smørgrav void 737*b7579f77SDag-Erling Smørgrav config_delstubs(struct config_stub* p) 738*b7579f77SDag-Erling Smørgrav { 739*b7579f77SDag-Erling Smørgrav struct config_stub* np; 740*b7579f77SDag-Erling Smørgrav while(p) { 741*b7579f77SDag-Erling Smørgrav np = p->next; 742*b7579f77SDag-Erling Smørgrav free(p->name); 743*b7579f77SDag-Erling Smørgrav config_delstrlist(p->hosts); 744*b7579f77SDag-Erling Smørgrav config_delstrlist(p->addrs); 745*b7579f77SDag-Erling Smørgrav free(p); 746*b7579f77SDag-Erling Smørgrav p = np; 747*b7579f77SDag-Erling Smørgrav } 748*b7579f77SDag-Erling Smørgrav } 749*b7579f77SDag-Erling Smørgrav 750*b7579f77SDag-Erling Smørgrav void 751*b7579f77SDag-Erling Smørgrav config_delete(struct config_file* cfg) 752*b7579f77SDag-Erling Smørgrav { 753*b7579f77SDag-Erling Smørgrav if(!cfg) return; 754*b7579f77SDag-Erling Smørgrav free(cfg->username); 755*b7579f77SDag-Erling Smørgrav free(cfg->chrootdir); 756*b7579f77SDag-Erling Smørgrav free(cfg->directory); 757*b7579f77SDag-Erling Smørgrav free(cfg->logfile); 758*b7579f77SDag-Erling Smørgrav free(cfg->pidfile); 759*b7579f77SDag-Erling Smørgrav free(cfg->target_fetch_policy); 760*b7579f77SDag-Erling Smørgrav free(cfg->ssl_service_key); 761*b7579f77SDag-Erling Smørgrav free(cfg->ssl_service_pem); 762*b7579f77SDag-Erling Smørgrav if(cfg->ifs) { 763*b7579f77SDag-Erling Smørgrav int i; 764*b7579f77SDag-Erling Smørgrav for(i=0; i<cfg->num_ifs; i++) 765*b7579f77SDag-Erling Smørgrav free(cfg->ifs[i]); 766*b7579f77SDag-Erling Smørgrav free(cfg->ifs); 767*b7579f77SDag-Erling Smørgrav } 768*b7579f77SDag-Erling Smørgrav if(cfg->out_ifs) { 769*b7579f77SDag-Erling Smørgrav int i; 770*b7579f77SDag-Erling Smørgrav for(i=0; i<cfg->num_out_ifs; i++) 771*b7579f77SDag-Erling Smørgrav free(cfg->out_ifs[i]); 772*b7579f77SDag-Erling Smørgrav free(cfg->out_ifs); 773*b7579f77SDag-Erling Smørgrav } 774*b7579f77SDag-Erling Smørgrav config_delstubs(cfg->stubs); 775*b7579f77SDag-Erling Smørgrav config_delstubs(cfg->forwards); 776*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->donotqueryaddrs); 777*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->root_hints); 778*b7579f77SDag-Erling Smørgrav free(cfg->identity); 779*b7579f77SDag-Erling Smørgrav free(cfg->version); 780*b7579f77SDag-Erling Smørgrav free(cfg->module_conf); 781*b7579f77SDag-Erling Smørgrav free(cfg->outgoing_avail_ports); 782*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->private_address); 783*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->private_domain); 784*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->auto_trust_anchor_file_list); 785*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->trust_anchor_file_list); 786*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->trusted_keys_file_list); 787*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->trust_anchor_list); 788*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->domain_insecure); 789*b7579f77SDag-Erling Smørgrav free(cfg->dlv_anchor_file); 790*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->dlv_anchor_list); 791*b7579f77SDag-Erling Smørgrav config_deldblstrlist(cfg->acls); 792*b7579f77SDag-Erling Smørgrav free(cfg->val_nsec3_key_iterations); 793*b7579f77SDag-Erling Smørgrav config_deldblstrlist(cfg->local_zones); 794*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->local_zones_nodefault); 795*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->local_data); 796*b7579f77SDag-Erling Smørgrav config_delstrlist(cfg->control_ifs); 797*b7579f77SDag-Erling Smørgrav free(cfg->server_key_file); 798*b7579f77SDag-Erling Smørgrav free(cfg->server_cert_file); 799*b7579f77SDag-Erling Smørgrav free(cfg->control_key_file); 800*b7579f77SDag-Erling Smørgrav free(cfg->control_cert_file); 801*b7579f77SDag-Erling Smørgrav free(cfg); 802*b7579f77SDag-Erling Smørgrav } 803*b7579f77SDag-Erling Smørgrav 804*b7579f77SDag-Erling Smørgrav static void 805*b7579f77SDag-Erling Smørgrav init_outgoing_availports(int* a, int num) 806*b7579f77SDag-Erling Smørgrav { 807*b7579f77SDag-Erling Smørgrav /* generated with make iana_update */ 808*b7579f77SDag-Erling Smørgrav const int iana_assigned[] = { 809*b7579f77SDag-Erling Smørgrav #include "util/iana_ports.inc" 810*b7579f77SDag-Erling Smørgrav -1 }; /* end marker to put behind trailing comma */ 811*b7579f77SDag-Erling Smørgrav 812*b7579f77SDag-Erling Smørgrav int i; 813*b7579f77SDag-Erling Smørgrav /* do not use <1024, that could be trouble with the system, privs */ 814*b7579f77SDag-Erling Smørgrav for(i=1024; i<num; i++) { 815*b7579f77SDag-Erling Smørgrav a[i] = i; 816*b7579f77SDag-Erling Smørgrav } 817*b7579f77SDag-Erling Smørgrav /* create empty spot at 49152 to keep ephemeral ports available 818*b7579f77SDag-Erling Smørgrav * to other programs */ 819*b7579f77SDag-Erling Smørgrav for(i=49152; i<49152+256; i++) 820*b7579f77SDag-Erling Smørgrav a[i] = 0; 821*b7579f77SDag-Erling Smørgrav /* pick out all the IANA assigned ports */ 822*b7579f77SDag-Erling Smørgrav for(i=0; iana_assigned[i]!=-1; i++) { 823*b7579f77SDag-Erling Smørgrav if(iana_assigned[i] < num) 824*b7579f77SDag-Erling Smørgrav a[iana_assigned[i]] = 0; 825*b7579f77SDag-Erling Smørgrav } 826*b7579f77SDag-Erling Smørgrav } 827*b7579f77SDag-Erling Smørgrav 828*b7579f77SDag-Erling Smørgrav int 829*b7579f77SDag-Erling Smørgrav cfg_mark_ports(const char* str, int allow, int* avail, int num) 830*b7579f77SDag-Erling Smørgrav { 831*b7579f77SDag-Erling Smørgrav char* mid = strchr(str, '-'); 832*b7579f77SDag-Erling Smørgrav if(!mid) { 833*b7579f77SDag-Erling Smørgrav int port = atoi(str); 834*b7579f77SDag-Erling Smørgrav if(port == 0 && strcmp(str, "0") != 0) { 835*b7579f77SDag-Erling Smørgrav log_err("cannot parse port number '%s'", str); 836*b7579f77SDag-Erling Smørgrav return 0; 837*b7579f77SDag-Erling Smørgrav } 838*b7579f77SDag-Erling Smørgrav if(port < num) 839*b7579f77SDag-Erling Smørgrav avail[port] = (allow?port:0); 840*b7579f77SDag-Erling Smørgrav } else { 841*b7579f77SDag-Erling Smørgrav int i, low, high = atoi(mid+1); 842*b7579f77SDag-Erling Smørgrav char buf[16]; 843*b7579f77SDag-Erling Smørgrav if(high == 0 && strcmp(mid+1, "0") != 0) { 844*b7579f77SDag-Erling Smørgrav log_err("cannot parse port number '%s'", mid+1); 845*b7579f77SDag-Erling Smørgrav return 0; 846*b7579f77SDag-Erling Smørgrav } 847*b7579f77SDag-Erling Smørgrav if( (int)(mid-str)+1 >= (int)sizeof(buf) ) { 848*b7579f77SDag-Erling Smørgrav log_err("cannot parse port number '%s'", str); 849*b7579f77SDag-Erling Smørgrav return 0; 850*b7579f77SDag-Erling Smørgrav } 851*b7579f77SDag-Erling Smørgrav if(mid > str) 852*b7579f77SDag-Erling Smørgrav memcpy(buf, str, (size_t)(mid-str)); 853*b7579f77SDag-Erling Smørgrav buf[mid-str] = 0; 854*b7579f77SDag-Erling Smørgrav low = atoi(buf); 855*b7579f77SDag-Erling Smørgrav if(low == 0 && strcmp(buf, "0") != 0) { 856*b7579f77SDag-Erling Smørgrav log_err("cannot parse port number '%s'", buf); 857*b7579f77SDag-Erling Smørgrav return 0; 858*b7579f77SDag-Erling Smørgrav } 859*b7579f77SDag-Erling Smørgrav for(i=low; i<=high; i++) { 860*b7579f77SDag-Erling Smørgrav if(i < num) 861*b7579f77SDag-Erling Smørgrav avail[i] = (allow?i:0); 862*b7579f77SDag-Erling Smørgrav } 863*b7579f77SDag-Erling Smørgrav return 1; 864*b7579f77SDag-Erling Smørgrav } 865*b7579f77SDag-Erling Smørgrav return 1; 866*b7579f77SDag-Erling Smørgrav } 867*b7579f77SDag-Erling Smørgrav 868*b7579f77SDag-Erling Smørgrav int 869*b7579f77SDag-Erling Smørgrav cfg_scan_ports(int* avail, int num) 870*b7579f77SDag-Erling Smørgrav { 871*b7579f77SDag-Erling Smørgrav int i; 872*b7579f77SDag-Erling Smørgrav int count = 0; 873*b7579f77SDag-Erling Smørgrav for(i=0; i<num; i++) { 874*b7579f77SDag-Erling Smørgrav if(avail[i]) 875*b7579f77SDag-Erling Smørgrav count++; 876*b7579f77SDag-Erling Smørgrav } 877*b7579f77SDag-Erling Smørgrav return count; 878*b7579f77SDag-Erling Smørgrav } 879*b7579f77SDag-Erling Smørgrav 880*b7579f77SDag-Erling Smørgrav int cfg_condense_ports(struct config_file* cfg, int** avail) 881*b7579f77SDag-Erling Smørgrav { 882*b7579f77SDag-Erling Smørgrav int num = cfg_scan_ports(cfg->outgoing_avail_ports, 65536); 883*b7579f77SDag-Erling Smørgrav int i, at = 0; 884*b7579f77SDag-Erling Smørgrav *avail = NULL; 885*b7579f77SDag-Erling Smørgrav if(num == 0) 886*b7579f77SDag-Erling Smørgrav return 0; 887*b7579f77SDag-Erling Smørgrav *avail = (int*)malloc(sizeof(int)*num); 888*b7579f77SDag-Erling Smørgrav if(!*avail) 889*b7579f77SDag-Erling Smørgrav return 0; 890*b7579f77SDag-Erling Smørgrav for(i=0; i<65536; i++) { 891*b7579f77SDag-Erling Smørgrav if(cfg->outgoing_avail_ports[i]) 892*b7579f77SDag-Erling Smørgrav (*avail)[at++] = cfg->outgoing_avail_ports[i]; 893*b7579f77SDag-Erling Smørgrav } 894*b7579f77SDag-Erling Smørgrav log_assert(at == num); 895*b7579f77SDag-Erling Smørgrav return num; 896*b7579f77SDag-Erling Smørgrav } 897*b7579f77SDag-Erling Smørgrav 898*b7579f77SDag-Erling Smørgrav /** print error with file and line number */ 899*b7579f77SDag-Erling Smørgrav static void ub_c_error_va_list(const char *fmt, va_list args) 900*b7579f77SDag-Erling Smørgrav { 901*b7579f77SDag-Erling Smørgrav cfg_parser->errors++; 902*b7579f77SDag-Erling Smørgrav fprintf(stderr, "%s:%d: error: ", cfg_parser->filename, 903*b7579f77SDag-Erling Smørgrav cfg_parser->line); 904*b7579f77SDag-Erling Smørgrav vfprintf(stderr, fmt, args); 905*b7579f77SDag-Erling Smørgrav fprintf(stderr, "\n"); 906*b7579f77SDag-Erling Smørgrav } 907*b7579f77SDag-Erling Smørgrav 908*b7579f77SDag-Erling Smørgrav /** print error with file and line number */ 909*b7579f77SDag-Erling Smørgrav void ub_c_error_msg(const char* fmt, ...) 910*b7579f77SDag-Erling Smørgrav { 911*b7579f77SDag-Erling Smørgrav va_list args; 912*b7579f77SDag-Erling Smørgrav va_start(args, fmt); 913*b7579f77SDag-Erling Smørgrav ub_c_error_va_list(fmt, args); 914*b7579f77SDag-Erling Smørgrav va_end(args); 915*b7579f77SDag-Erling Smørgrav } 916*b7579f77SDag-Erling Smørgrav 917*b7579f77SDag-Erling Smørgrav void ub_c_error(const char *str) 918*b7579f77SDag-Erling Smørgrav { 919*b7579f77SDag-Erling Smørgrav cfg_parser->errors++; 920*b7579f77SDag-Erling Smørgrav fprintf(stderr, "%s:%d: error: %s\n", cfg_parser->filename, 921*b7579f77SDag-Erling Smørgrav cfg_parser->line, str); 922*b7579f77SDag-Erling Smørgrav } 923*b7579f77SDag-Erling Smørgrav 924*b7579f77SDag-Erling Smørgrav int ub_c_wrap(void) 925*b7579f77SDag-Erling Smørgrav { 926*b7579f77SDag-Erling Smørgrav return 1; 927*b7579f77SDag-Erling Smørgrav } 928*b7579f77SDag-Erling Smørgrav 929*b7579f77SDag-Erling Smørgrav int cfg_strlist_append(struct config_strlist_head* list, char* item) 930*b7579f77SDag-Erling Smørgrav { 931*b7579f77SDag-Erling Smørgrav struct config_strlist *s; 932*b7579f77SDag-Erling Smørgrav if(!item || !list) 933*b7579f77SDag-Erling Smørgrav return 0; 934*b7579f77SDag-Erling Smørgrav s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); 935*b7579f77SDag-Erling Smørgrav if(!s) 936*b7579f77SDag-Erling Smørgrav return 0; 937*b7579f77SDag-Erling Smørgrav s->str = item; 938*b7579f77SDag-Erling Smørgrav s->next = NULL; 939*b7579f77SDag-Erling Smørgrav if(list->last) 940*b7579f77SDag-Erling Smørgrav list->last->next = s; 941*b7579f77SDag-Erling Smørgrav else 942*b7579f77SDag-Erling Smørgrav list->first = s; 943*b7579f77SDag-Erling Smørgrav list->last = s; 944*b7579f77SDag-Erling Smørgrav return 1; 945*b7579f77SDag-Erling Smørgrav } 946*b7579f77SDag-Erling Smørgrav 947*b7579f77SDag-Erling Smørgrav int 948*b7579f77SDag-Erling Smørgrav cfg_strlist_insert(struct config_strlist** head, char* item) 949*b7579f77SDag-Erling Smørgrav { 950*b7579f77SDag-Erling Smørgrav struct config_strlist *s; 951*b7579f77SDag-Erling Smørgrav if(!item || !head) 952*b7579f77SDag-Erling Smørgrav return 0; 953*b7579f77SDag-Erling Smørgrav s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); 954*b7579f77SDag-Erling Smørgrav if(!s) 955*b7579f77SDag-Erling Smørgrav return 0; 956*b7579f77SDag-Erling Smørgrav s->str = item; 957*b7579f77SDag-Erling Smørgrav s->next = *head; 958*b7579f77SDag-Erling Smørgrav *head = s; 959*b7579f77SDag-Erling Smørgrav return 1; 960*b7579f77SDag-Erling Smørgrav } 961*b7579f77SDag-Erling Smørgrav 962*b7579f77SDag-Erling Smørgrav int 963*b7579f77SDag-Erling Smørgrav cfg_str2list_insert(struct config_str2list** head, char* item, char* i2) 964*b7579f77SDag-Erling Smørgrav { 965*b7579f77SDag-Erling Smørgrav struct config_str2list *s; 966*b7579f77SDag-Erling Smørgrav if(!item || !i2 || !head) 967*b7579f77SDag-Erling Smørgrav return 0; 968*b7579f77SDag-Erling Smørgrav s = (struct config_str2list*)calloc(1, sizeof(struct config_str2list)); 969*b7579f77SDag-Erling Smørgrav if(!s) 970*b7579f77SDag-Erling Smørgrav return 0; 971*b7579f77SDag-Erling Smørgrav s->str = item; 972*b7579f77SDag-Erling Smørgrav s->str2 = i2; 973*b7579f77SDag-Erling Smørgrav s->next = *head; 974*b7579f77SDag-Erling Smørgrav *head = s; 975*b7579f77SDag-Erling Smørgrav return 1; 976*b7579f77SDag-Erling Smørgrav } 977*b7579f77SDag-Erling Smørgrav 978*b7579f77SDag-Erling Smørgrav uint32_t 979*b7579f77SDag-Erling Smørgrav cfg_convert_timeval(const char* str) 980*b7579f77SDag-Erling Smørgrav { 981*b7579f77SDag-Erling Smørgrav uint32_t t; 982*b7579f77SDag-Erling Smørgrav struct tm tm; 983*b7579f77SDag-Erling Smørgrav memset(&tm, 0, sizeof(tm)); 984*b7579f77SDag-Erling Smørgrav if(strlen(str) < 14) 985*b7579f77SDag-Erling Smørgrav return 0; 986*b7579f77SDag-Erling Smørgrav if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, 987*b7579f77SDag-Erling Smørgrav &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) 988*b7579f77SDag-Erling Smørgrav return 0; 989*b7579f77SDag-Erling Smørgrav tm.tm_year -= 1900; 990*b7579f77SDag-Erling Smørgrav tm.tm_mon--; 991*b7579f77SDag-Erling Smørgrav /* Check values */ 992*b7579f77SDag-Erling Smørgrav if (tm.tm_year < 70) return 0; 993*b7579f77SDag-Erling Smørgrav if (tm.tm_mon < 0 || tm.tm_mon > 11) return 0; 994*b7579f77SDag-Erling Smørgrav if (tm.tm_mday < 1 || tm.tm_mday > 31) return 0; 995*b7579f77SDag-Erling Smørgrav if (tm.tm_hour < 0 || tm.tm_hour > 23) return 0; 996*b7579f77SDag-Erling Smørgrav if (tm.tm_min < 0 || tm.tm_min > 59) return 0; 997*b7579f77SDag-Erling Smørgrav if (tm.tm_sec < 0 || tm.tm_sec > 59) return 0; 998*b7579f77SDag-Erling Smørgrav /* call ldns conversion function */ 999*b7579f77SDag-Erling Smørgrav t = mktime_from_utc(&tm); 1000*b7579f77SDag-Erling Smørgrav return t; 1001*b7579f77SDag-Erling Smørgrav } 1002*b7579f77SDag-Erling Smørgrav 1003*b7579f77SDag-Erling Smørgrav int 1004*b7579f77SDag-Erling Smørgrav cfg_count_numbers(const char* s) 1005*b7579f77SDag-Erling Smørgrav { 1006*b7579f77SDag-Erling Smørgrav /* format ::= (sp num)+ sp */ 1007*b7579f77SDag-Erling Smørgrav /* num ::= [-](0-9)+ */ 1008*b7579f77SDag-Erling Smørgrav /* sp ::= (space|tab)* */ 1009*b7579f77SDag-Erling Smørgrav int num = 0; 1010*b7579f77SDag-Erling Smørgrav while(*s) { 1011*b7579f77SDag-Erling Smørgrav while(*s && isspace((int)*s)) 1012*b7579f77SDag-Erling Smørgrav s++; 1013*b7579f77SDag-Erling Smørgrav if(!*s) /* end of string */ 1014*b7579f77SDag-Erling Smørgrav break; 1015*b7579f77SDag-Erling Smørgrav if(*s == '-') 1016*b7579f77SDag-Erling Smørgrav s++; 1017*b7579f77SDag-Erling Smørgrav if(!*s) /* only - not allowed */ 1018*b7579f77SDag-Erling Smørgrav return 0; 1019*b7579f77SDag-Erling Smørgrav if(!isdigit((int)*s)) /* bad character */ 1020*b7579f77SDag-Erling Smørgrav return 0; 1021*b7579f77SDag-Erling Smørgrav while(*s && isdigit((int)*s)) 1022*b7579f77SDag-Erling Smørgrav s++; 1023*b7579f77SDag-Erling Smørgrav num++; 1024*b7579f77SDag-Erling Smørgrav } 1025*b7579f77SDag-Erling Smørgrav return num; 1026*b7579f77SDag-Erling Smørgrav } 1027*b7579f77SDag-Erling Smørgrav 1028*b7579f77SDag-Erling Smørgrav /** all digit number */ 1029*b7579f77SDag-Erling Smørgrav static int isalldigit(const char* str, size_t l) 1030*b7579f77SDag-Erling Smørgrav { 1031*b7579f77SDag-Erling Smørgrav size_t i; 1032*b7579f77SDag-Erling Smørgrav for(i=0; i<l; i++) 1033*b7579f77SDag-Erling Smørgrav if(!isdigit(str[i])) 1034*b7579f77SDag-Erling Smørgrav return 0; 1035*b7579f77SDag-Erling Smørgrav return 1; 1036*b7579f77SDag-Erling Smørgrav } 1037*b7579f77SDag-Erling Smørgrav 1038*b7579f77SDag-Erling Smørgrav int 1039*b7579f77SDag-Erling Smørgrav cfg_parse_memsize(const char* str, size_t* res) 1040*b7579f77SDag-Erling Smørgrav { 1041*b7579f77SDag-Erling Smørgrav size_t len = (size_t)strlen(str); 1042*b7579f77SDag-Erling Smørgrav size_t mult = 1; 1043*b7579f77SDag-Erling Smørgrav if(!str || len == 0) { 1044*b7579f77SDag-Erling Smørgrav log_err("not a size: '%s'", str); 1045*b7579f77SDag-Erling Smørgrav return 0; 1046*b7579f77SDag-Erling Smørgrav } 1047*b7579f77SDag-Erling Smørgrav if(isalldigit(str, len)) { 1048*b7579f77SDag-Erling Smørgrav *res = (size_t)atol(str); 1049*b7579f77SDag-Erling Smørgrav return 1; 1050*b7579f77SDag-Erling Smørgrav } 1051*b7579f77SDag-Erling Smørgrav /* check appended num */ 1052*b7579f77SDag-Erling Smørgrav while(len>0 && str[len-1]==' ') 1053*b7579f77SDag-Erling Smørgrav len--; 1054*b7579f77SDag-Erling Smørgrav if(len > 1 && str[len-1] == 'b') 1055*b7579f77SDag-Erling Smørgrav len--; 1056*b7579f77SDag-Erling Smørgrav else if(len > 1 && str[len-1] == 'B') 1057*b7579f77SDag-Erling Smørgrav len--; 1058*b7579f77SDag-Erling Smørgrav 1059*b7579f77SDag-Erling Smørgrav if(len > 1 && tolower(str[len-1]) == 'g') 1060*b7579f77SDag-Erling Smørgrav mult = 1024*1024*1024; 1061*b7579f77SDag-Erling Smørgrav else if(len > 1 && tolower(str[len-1]) == 'm') 1062*b7579f77SDag-Erling Smørgrav mult = 1024*1024; 1063*b7579f77SDag-Erling Smørgrav else if(len > 1 && tolower(str[len-1]) == 'k') 1064*b7579f77SDag-Erling Smørgrav mult = 1024; 1065*b7579f77SDag-Erling Smørgrav else if(len > 0 && isdigit(str[len-1])) 1066*b7579f77SDag-Erling Smørgrav mult = 1; 1067*b7579f77SDag-Erling Smørgrav else { 1068*b7579f77SDag-Erling Smørgrav log_err("unknown size specifier: '%s'", str); 1069*b7579f77SDag-Erling Smørgrav return 0; 1070*b7579f77SDag-Erling Smørgrav } 1071*b7579f77SDag-Erling Smørgrav while(len>1 && str[len-2]==' ') 1072*b7579f77SDag-Erling Smørgrav len--; 1073*b7579f77SDag-Erling Smørgrav 1074*b7579f77SDag-Erling Smørgrav if(!isalldigit(str, len-1)) { 1075*b7579f77SDag-Erling Smørgrav log_err("unknown size specifier: '%s'", str); 1076*b7579f77SDag-Erling Smørgrav return 0; 1077*b7579f77SDag-Erling Smørgrav } 1078*b7579f77SDag-Erling Smørgrav *res = ((size_t)atol(str)) * mult; 1079*b7579f77SDag-Erling Smørgrav return 1; 1080*b7579f77SDag-Erling Smørgrav } 1081*b7579f77SDag-Erling Smørgrav 1082*b7579f77SDag-Erling Smørgrav void 1083*b7579f77SDag-Erling Smørgrav config_apply(struct config_file* config) 1084*b7579f77SDag-Erling Smørgrav { 1085*b7579f77SDag-Erling Smørgrav MAX_TTL = (uint32_t)config->max_ttl; 1086*b7579f77SDag-Erling Smørgrav MIN_TTL = (uint32_t)config->min_ttl; 1087*b7579f77SDag-Erling Smørgrav EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size; 1088*b7579f77SDag-Erling Smørgrav MINIMAL_RESPONSES = config->minimal_responses; 1089*b7579f77SDag-Erling Smørgrav RRSET_ROUNDROBIN = config->rrset_roundrobin; 1090*b7579f77SDag-Erling Smørgrav log_set_time_asc(config->log_time_ascii); 1091*b7579f77SDag-Erling Smørgrav } 1092*b7579f77SDag-Erling Smørgrav 1093*b7579f77SDag-Erling Smørgrav /** 1094*b7579f77SDag-Erling Smørgrav * Calculate string length of full pathname in original filesys 1095*b7579f77SDag-Erling Smørgrav * @param fname: the path name to convert. 1096*b7579f77SDag-Erling Smørgrav * Must not be null or empty. 1097*b7579f77SDag-Erling Smørgrav * @param cfg: config struct for chroot and chdir (if set). 1098*b7579f77SDag-Erling Smørgrav * @param use_chdir: if false, only chroot is applied. 1099*b7579f77SDag-Erling Smørgrav * @return length of string. 1100*b7579f77SDag-Erling Smørgrav * remember to allocate one more for 0 at end in mallocs. 1101*b7579f77SDag-Erling Smørgrav */ 1102*b7579f77SDag-Erling Smørgrav static size_t 1103*b7579f77SDag-Erling Smørgrav strlen_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) 1104*b7579f77SDag-Erling Smørgrav { 1105*b7579f77SDag-Erling Smørgrav size_t len = 0; 1106*b7579f77SDag-Erling Smørgrav int slashit = 0; 1107*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0] && 1108*b7579f77SDag-Erling Smørgrav strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { 1109*b7579f77SDag-Erling Smørgrav /* already full pathname, return it */ 1110*b7579f77SDag-Erling Smørgrav return strlen(fname); 1111*b7579f77SDag-Erling Smørgrav } 1112*b7579f77SDag-Erling Smørgrav /* chroot */ 1113*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0]) { 1114*b7579f77SDag-Erling Smørgrav /* start with chrootdir */ 1115*b7579f77SDag-Erling Smørgrav len += strlen(cfg->chrootdir); 1116*b7579f77SDag-Erling Smørgrav slashit = 1; 1117*b7579f77SDag-Erling Smørgrav } 1118*b7579f77SDag-Erling Smørgrav /* chdir */ 1119*b7579f77SDag-Erling Smørgrav #ifdef UB_ON_WINDOWS 1120*b7579f77SDag-Erling Smørgrav if(fname[0] != 0 && fname[1] == ':') { 1121*b7579f77SDag-Erling Smørgrav /* full path, no chdir */ 1122*b7579f77SDag-Erling Smørgrav } else 1123*b7579f77SDag-Erling Smørgrav #endif 1124*b7579f77SDag-Erling Smørgrav if(fname[0] == '/' || !use_chdir) { 1125*b7579f77SDag-Erling Smørgrav /* full path, no chdir */ 1126*b7579f77SDag-Erling Smørgrav } else if(cfg->directory && cfg->directory[0]) { 1127*b7579f77SDag-Erling Smørgrav /* prepend chdir */ 1128*b7579f77SDag-Erling Smørgrav if(slashit && cfg->directory[0] != '/') 1129*b7579f77SDag-Erling Smørgrav len++; 1130*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0] && 1131*b7579f77SDag-Erling Smørgrav strncmp(cfg->chrootdir, cfg->directory, 1132*b7579f77SDag-Erling Smørgrav strlen(cfg->chrootdir)) == 0) 1133*b7579f77SDag-Erling Smørgrav len += strlen(cfg->directory)-strlen(cfg->chrootdir); 1134*b7579f77SDag-Erling Smørgrav else len += strlen(cfg->directory); 1135*b7579f77SDag-Erling Smørgrav slashit = 1; 1136*b7579f77SDag-Erling Smørgrav } 1137*b7579f77SDag-Erling Smørgrav /* fname */ 1138*b7579f77SDag-Erling Smørgrav if(slashit && fname[0] != '/') 1139*b7579f77SDag-Erling Smørgrav len++; 1140*b7579f77SDag-Erling Smørgrav len += strlen(fname); 1141*b7579f77SDag-Erling Smørgrav return len; 1142*b7579f77SDag-Erling Smørgrav } 1143*b7579f77SDag-Erling Smørgrav 1144*b7579f77SDag-Erling Smørgrav char* 1145*b7579f77SDag-Erling Smørgrav fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) 1146*b7579f77SDag-Erling Smørgrav { 1147*b7579f77SDag-Erling Smørgrav size_t len = strlen_after_chroot(fname, cfg, use_chdir); 1148*b7579f77SDag-Erling Smørgrav int slashit = 0; 1149*b7579f77SDag-Erling Smørgrav char* buf = (char*)malloc(len+1); 1150*b7579f77SDag-Erling Smørgrav if(!buf) 1151*b7579f77SDag-Erling Smørgrav return NULL; 1152*b7579f77SDag-Erling Smørgrav buf[0] = 0; 1153*b7579f77SDag-Erling Smørgrav /* is fname already in chroot ? */ 1154*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0] && 1155*b7579f77SDag-Erling Smørgrav strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { 1156*b7579f77SDag-Erling Smørgrav /* already full pathname, return it */ 1157*b7579f77SDag-Erling Smørgrav strncpy(buf, fname, len); 1158*b7579f77SDag-Erling Smørgrav buf[len] = 0; 1159*b7579f77SDag-Erling Smørgrav return buf; 1160*b7579f77SDag-Erling Smørgrav } 1161*b7579f77SDag-Erling Smørgrav /* chroot */ 1162*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0]) { 1163*b7579f77SDag-Erling Smørgrav /* start with chrootdir */ 1164*b7579f77SDag-Erling Smørgrav strncpy(buf, cfg->chrootdir, len); 1165*b7579f77SDag-Erling Smørgrav slashit = 1; 1166*b7579f77SDag-Erling Smørgrav } 1167*b7579f77SDag-Erling Smørgrav #ifdef UB_ON_WINDOWS 1168*b7579f77SDag-Erling Smørgrav if(fname[0] != 0 && fname[1] == ':') { 1169*b7579f77SDag-Erling Smørgrav /* full path, no chdir */ 1170*b7579f77SDag-Erling Smørgrav } else 1171*b7579f77SDag-Erling Smørgrav #endif 1172*b7579f77SDag-Erling Smørgrav /* chdir */ 1173*b7579f77SDag-Erling Smørgrav if(fname[0] == '/' || !use_chdir) { 1174*b7579f77SDag-Erling Smørgrav /* full path, no chdir */ 1175*b7579f77SDag-Erling Smørgrav } else if(cfg->directory && cfg->directory[0]) { 1176*b7579f77SDag-Erling Smørgrav /* prepend chdir */ 1177*b7579f77SDag-Erling Smørgrav if(slashit && cfg->directory[0] != '/') 1178*b7579f77SDag-Erling Smørgrav strncat(buf, "/", len-strlen(buf)); 1179*b7579f77SDag-Erling Smørgrav /* is the directory already in the chroot? */ 1180*b7579f77SDag-Erling Smørgrav if(cfg->chrootdir && cfg->chrootdir[0] && 1181*b7579f77SDag-Erling Smørgrav strncmp(cfg->chrootdir, cfg->directory, 1182*b7579f77SDag-Erling Smørgrav strlen(cfg->chrootdir)) == 0) 1183*b7579f77SDag-Erling Smørgrav strncat(buf, cfg->directory+strlen(cfg->chrootdir), 1184*b7579f77SDag-Erling Smørgrav len-strlen(buf)); 1185*b7579f77SDag-Erling Smørgrav else strncat(buf, cfg->directory, len-strlen(buf)); 1186*b7579f77SDag-Erling Smørgrav slashit = 1; 1187*b7579f77SDag-Erling Smørgrav } 1188*b7579f77SDag-Erling Smørgrav /* fname */ 1189*b7579f77SDag-Erling Smørgrav if(slashit && fname[0] != '/') 1190*b7579f77SDag-Erling Smørgrav strncat(buf, "/", len-strlen(buf)); 1191*b7579f77SDag-Erling Smørgrav strncat(buf, fname, len-strlen(buf)); 1192*b7579f77SDag-Erling Smørgrav buf[len] = 0; 1193*b7579f77SDag-Erling Smørgrav return buf; 1194*b7579f77SDag-Erling Smørgrav } 1195*b7579f77SDag-Erling Smørgrav 1196*b7579f77SDag-Erling Smørgrav /** return next space character in string */ 1197*b7579f77SDag-Erling Smørgrav static char* next_space_pos(const char* str) 1198*b7579f77SDag-Erling Smørgrav { 1199*b7579f77SDag-Erling Smørgrav char* sp = strchr(str, ' '); 1200*b7579f77SDag-Erling Smørgrav char* tab = strchr(str, '\t'); 1201*b7579f77SDag-Erling Smørgrav if(!tab && !sp) 1202*b7579f77SDag-Erling Smørgrav return NULL; 1203*b7579f77SDag-Erling Smørgrav if(!sp) return tab; 1204*b7579f77SDag-Erling Smørgrav if(!tab) return sp; 1205*b7579f77SDag-Erling Smørgrav return (sp<tab)?sp:tab; 1206*b7579f77SDag-Erling Smørgrav } 1207*b7579f77SDag-Erling Smørgrav 1208*b7579f77SDag-Erling Smørgrav /** return last space character in string */ 1209*b7579f77SDag-Erling Smørgrav static char* last_space_pos(const char* str) 1210*b7579f77SDag-Erling Smørgrav { 1211*b7579f77SDag-Erling Smørgrav char* sp = strrchr(str, ' '); 1212*b7579f77SDag-Erling Smørgrav char* tab = strrchr(str, '\t'); 1213*b7579f77SDag-Erling Smørgrav if(!tab && !sp) 1214*b7579f77SDag-Erling Smørgrav return NULL; 1215*b7579f77SDag-Erling Smørgrav if(!sp) return tab; 1216*b7579f77SDag-Erling Smørgrav if(!tab) return sp; 1217*b7579f77SDag-Erling Smørgrav return (sp>tab)?sp:tab; 1218*b7579f77SDag-Erling Smørgrav } 1219*b7579f77SDag-Erling Smørgrav 1220*b7579f77SDag-Erling Smørgrav int 1221*b7579f77SDag-Erling Smørgrav cfg_parse_local_zone(struct config_file* cfg, const char* val) 1222*b7579f77SDag-Erling Smørgrav { 1223*b7579f77SDag-Erling Smørgrav const char *type, *name_end, *name; 1224*b7579f77SDag-Erling Smørgrav char buf[256]; 1225*b7579f77SDag-Erling Smørgrav 1226*b7579f77SDag-Erling Smørgrav /* parse it as: [zone_name] [between stuff] [zone_type] */ 1227*b7579f77SDag-Erling Smørgrav name = val; 1228*b7579f77SDag-Erling Smørgrav while(*name && isspace(*name)) 1229*b7579f77SDag-Erling Smørgrav name++; 1230*b7579f77SDag-Erling Smørgrav if(!*name) { 1231*b7579f77SDag-Erling Smørgrav log_err("syntax error: too short: %s", val); 1232*b7579f77SDag-Erling Smørgrav return 0; 1233*b7579f77SDag-Erling Smørgrav } 1234*b7579f77SDag-Erling Smørgrav name_end = next_space_pos(name); 1235*b7579f77SDag-Erling Smørgrav if(!name_end || !*name_end) { 1236*b7579f77SDag-Erling Smørgrav log_err("syntax error: expected zone type: %s", val); 1237*b7579f77SDag-Erling Smørgrav return 0; 1238*b7579f77SDag-Erling Smørgrav } 1239*b7579f77SDag-Erling Smørgrav if (name_end - name > 255) { 1240*b7579f77SDag-Erling Smørgrav log_err("syntax error: bad zone name: %s", val); 1241*b7579f77SDag-Erling Smørgrav return 0; 1242*b7579f77SDag-Erling Smørgrav } 1243*b7579f77SDag-Erling Smørgrav strncpy(buf, name, (size_t)(name_end-name)); 1244*b7579f77SDag-Erling Smørgrav buf[name_end-name] = '\0'; 1245*b7579f77SDag-Erling Smørgrav 1246*b7579f77SDag-Erling Smørgrav type = last_space_pos(name_end); 1247*b7579f77SDag-Erling Smørgrav while(type && *type && isspace(*type)) 1248*b7579f77SDag-Erling Smørgrav type++; 1249*b7579f77SDag-Erling Smørgrav if(!type || !*type) { 1250*b7579f77SDag-Erling Smørgrav log_err("syntax error: expected zone type: %s", val); 1251*b7579f77SDag-Erling Smørgrav return 0; 1252*b7579f77SDag-Erling Smørgrav } 1253*b7579f77SDag-Erling Smørgrav 1254*b7579f77SDag-Erling Smørgrav if(strcmp(type, "nodefault")==0) { 1255*b7579f77SDag-Erling Smørgrav return cfg_strlist_insert(&cfg->local_zones_nodefault, 1256*b7579f77SDag-Erling Smørgrav strdup(name)); 1257*b7579f77SDag-Erling Smørgrav } else { 1258*b7579f77SDag-Erling Smørgrav return cfg_str2list_insert(&cfg->local_zones, strdup(buf), 1259*b7579f77SDag-Erling Smørgrav strdup(type)); 1260*b7579f77SDag-Erling Smørgrav } 1261*b7579f77SDag-Erling Smørgrav } 1262*b7579f77SDag-Erling Smørgrav 1263*b7579f77SDag-Erling Smørgrav char* cfg_ptr_reverse(char* str) 1264*b7579f77SDag-Erling Smørgrav { 1265*b7579f77SDag-Erling Smørgrav char* ip, *ip_end; 1266*b7579f77SDag-Erling Smørgrav char* name; 1267*b7579f77SDag-Erling Smørgrav char* result; 1268*b7579f77SDag-Erling Smørgrav char buf[1024]; 1269*b7579f77SDag-Erling Smørgrav struct sockaddr_storage addr; 1270*b7579f77SDag-Erling Smørgrav socklen_t addrlen; 1271*b7579f77SDag-Erling Smørgrav 1272*b7579f77SDag-Erling Smørgrav /* parse it as: [IP] [between stuff] [name] */ 1273*b7579f77SDag-Erling Smørgrav ip = str; 1274*b7579f77SDag-Erling Smørgrav while(*ip && isspace(*ip)) 1275*b7579f77SDag-Erling Smørgrav ip++; 1276*b7579f77SDag-Erling Smørgrav if(!*ip) { 1277*b7579f77SDag-Erling Smørgrav log_err("syntax error: too short: %s", str); 1278*b7579f77SDag-Erling Smørgrav return NULL; 1279*b7579f77SDag-Erling Smørgrav } 1280*b7579f77SDag-Erling Smørgrav ip_end = next_space_pos(ip); 1281*b7579f77SDag-Erling Smørgrav if(!ip_end || !*ip_end) { 1282*b7579f77SDag-Erling Smørgrav log_err("syntax error: expected name: %s", str); 1283*b7579f77SDag-Erling Smørgrav return NULL; 1284*b7579f77SDag-Erling Smørgrav } 1285*b7579f77SDag-Erling Smørgrav 1286*b7579f77SDag-Erling Smørgrav name = last_space_pos(ip_end); 1287*b7579f77SDag-Erling Smørgrav if(!name || !*name) { 1288*b7579f77SDag-Erling Smørgrav log_err("syntax error: expected name: %s", str); 1289*b7579f77SDag-Erling Smørgrav return NULL; 1290*b7579f77SDag-Erling Smørgrav } 1291*b7579f77SDag-Erling Smørgrav 1292*b7579f77SDag-Erling Smørgrav sscanf(ip, "%100s", buf); 1293*b7579f77SDag-Erling Smørgrav buf[sizeof(buf)-1]=0; 1294*b7579f77SDag-Erling Smørgrav 1295*b7579f77SDag-Erling Smørgrav if(!ipstrtoaddr(buf, UNBOUND_DNS_PORT, &addr, &addrlen)) { 1296*b7579f77SDag-Erling Smørgrav log_err("syntax error: cannot parse address: %s", str); 1297*b7579f77SDag-Erling Smørgrav return NULL; 1298*b7579f77SDag-Erling Smørgrav } 1299*b7579f77SDag-Erling Smørgrav 1300*b7579f77SDag-Erling Smørgrav /* reverse IPv4: 1301*b7579f77SDag-Erling Smørgrav * ddd.ddd.ddd.ddd.in-addr-arpa. 1302*b7579f77SDag-Erling Smørgrav * IPv6: (h.){32}.ip6.arpa. */ 1303*b7579f77SDag-Erling Smørgrav 1304*b7579f77SDag-Erling Smørgrav if(addr_is_ip6(&addr, addrlen)) { 1305*b7579f77SDag-Erling Smørgrav uint8_t ad[16]; 1306*b7579f77SDag-Erling Smørgrav const char* hex = "0123456789abcdef"; 1307*b7579f77SDag-Erling Smørgrav char *p = buf; 1308*b7579f77SDag-Erling Smørgrav int i; 1309*b7579f77SDag-Erling Smørgrav memmove(ad, &((struct sockaddr_in6*)&addr)->sin6_addr, 1310*b7579f77SDag-Erling Smørgrav sizeof(ad)); 1311*b7579f77SDag-Erling Smørgrav for(i=15; i>=0; i--) { 1312*b7579f77SDag-Erling Smørgrav uint8_t b = ad[i]; 1313*b7579f77SDag-Erling Smørgrav *p++ = hex[ (b&0x0f) ]; 1314*b7579f77SDag-Erling Smørgrav *p++ = '.'; 1315*b7579f77SDag-Erling Smørgrav *p++ = hex[ (b&0xf0) >> 4 ]; 1316*b7579f77SDag-Erling Smørgrav *p++ = '.'; 1317*b7579f77SDag-Erling Smørgrav } 1318*b7579f77SDag-Erling Smørgrav snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa. "); 1319*b7579f77SDag-Erling Smørgrav } else { 1320*b7579f77SDag-Erling Smørgrav uint8_t ad[4]; 1321*b7579f77SDag-Erling Smørgrav memmove(ad, &((struct sockaddr_in*)&addr)->sin_addr, 1322*b7579f77SDag-Erling Smørgrav sizeof(ad)); 1323*b7579f77SDag-Erling Smørgrav snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa. ", 1324*b7579f77SDag-Erling Smørgrav (unsigned)ad[3], (unsigned)ad[2], 1325*b7579f77SDag-Erling Smørgrav (unsigned)ad[1], (unsigned)ad[0]); 1326*b7579f77SDag-Erling Smørgrav } 1327*b7579f77SDag-Erling Smørgrav 1328*b7579f77SDag-Erling Smørgrav /* printed the reverse address, now the between goop and name on end */ 1329*b7579f77SDag-Erling Smørgrav while(*ip_end && isspace(*ip_end)) 1330*b7579f77SDag-Erling Smørgrav ip_end++; 1331*b7579f77SDag-Erling Smørgrav if(name>ip_end) { 1332*b7579f77SDag-Erling Smørgrav snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%.*s", 1333*b7579f77SDag-Erling Smørgrav (int)(name-ip_end), ip_end); 1334*b7579f77SDag-Erling Smørgrav } 1335*b7579f77SDag-Erling Smørgrav snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), " PTR %s", name); 1336*b7579f77SDag-Erling Smørgrav 1337*b7579f77SDag-Erling Smørgrav result = strdup(buf); 1338*b7579f77SDag-Erling Smørgrav if(!result) { 1339*b7579f77SDag-Erling Smørgrav log_err("out of memory parsing %s", str); 1340*b7579f77SDag-Erling Smørgrav return NULL; 1341*b7579f77SDag-Erling Smørgrav } 1342*b7579f77SDag-Erling Smørgrav return result; 1343*b7579f77SDag-Erling Smørgrav } 1344*b7579f77SDag-Erling Smørgrav 1345*b7579f77SDag-Erling Smørgrav #ifdef UB_ON_WINDOWS 1346*b7579f77SDag-Erling Smørgrav char* 1347*b7579f77SDag-Erling Smørgrav w_lookup_reg_str(const char* key, const char* name) 1348*b7579f77SDag-Erling Smørgrav { 1349*b7579f77SDag-Erling Smørgrav HKEY hk = NULL; 1350*b7579f77SDag-Erling Smørgrav DWORD type = 0; 1351*b7579f77SDag-Erling Smørgrav BYTE buf[1024]; 1352*b7579f77SDag-Erling Smørgrav DWORD len = (DWORD)sizeof(buf); 1353*b7579f77SDag-Erling Smørgrav LONG ret; 1354*b7579f77SDag-Erling Smørgrav char* result = NULL; 1355*b7579f77SDag-Erling Smørgrav ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk); 1356*b7579f77SDag-Erling Smørgrav if(ret == ERROR_FILE_NOT_FOUND) 1357*b7579f77SDag-Erling Smørgrav return NULL; /* key does not exist */ 1358*b7579f77SDag-Erling Smørgrav else if(ret != ERROR_SUCCESS) { 1359*b7579f77SDag-Erling Smørgrav log_err("RegOpenKeyEx failed"); 1360*b7579f77SDag-Erling Smørgrav return NULL; 1361*b7579f77SDag-Erling Smørgrav } 1362*b7579f77SDag-Erling Smørgrav ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len); 1363*b7579f77SDag-Erling Smørgrav if(RegCloseKey(hk)) 1364*b7579f77SDag-Erling Smørgrav log_err("RegCloseKey"); 1365*b7579f77SDag-Erling Smørgrav if(ret == ERROR_FILE_NOT_FOUND) 1366*b7579f77SDag-Erling Smørgrav return NULL; /* name does not exist */ 1367*b7579f77SDag-Erling Smørgrav else if(ret != ERROR_SUCCESS) { 1368*b7579f77SDag-Erling Smørgrav log_err("RegQueryValueEx failed"); 1369*b7579f77SDag-Erling Smørgrav return NULL; 1370*b7579f77SDag-Erling Smørgrav } 1371*b7579f77SDag-Erling Smørgrav if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { 1372*b7579f77SDag-Erling Smørgrav buf[sizeof(buf)-1] = 0; 1373*b7579f77SDag-Erling Smørgrav buf[sizeof(buf)-2] = 0; /* for multi_sz */ 1374*b7579f77SDag-Erling Smørgrav result = strdup((char*)buf); 1375*b7579f77SDag-Erling Smørgrav if(!result) log_err("out of memory"); 1376*b7579f77SDag-Erling Smørgrav } 1377*b7579f77SDag-Erling Smørgrav return result; 1378*b7579f77SDag-Erling Smørgrav } 1379*b7579f77SDag-Erling Smørgrav #endif /* UB_ON_WINDOWS */ 1380*b7579f77SDag-Erling Smørgrav 1381*b7579f77SDag-Erling Smørgrav void errinf(struct module_qstate* qstate, const char* str) 1382*b7579f77SDag-Erling Smørgrav { 1383*b7579f77SDag-Erling Smørgrav struct config_strlist* p; 1384*b7579f77SDag-Erling Smørgrav if(qstate->env->cfg->val_log_level < 2 || !str) 1385*b7579f77SDag-Erling Smørgrav return; 1386*b7579f77SDag-Erling Smørgrav p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p)); 1387*b7579f77SDag-Erling Smørgrav if(!p) { 1388*b7579f77SDag-Erling Smørgrav log_err("malloc failure in validator-error-info string"); 1389*b7579f77SDag-Erling Smørgrav return; 1390*b7579f77SDag-Erling Smørgrav } 1391*b7579f77SDag-Erling Smørgrav p->next = NULL; 1392*b7579f77SDag-Erling Smørgrav p->str = regional_strdup(qstate->region, str); 1393*b7579f77SDag-Erling Smørgrav if(!p->str) { 1394*b7579f77SDag-Erling Smørgrav log_err("malloc failure in validator-error-info string"); 1395*b7579f77SDag-Erling Smørgrav return; 1396*b7579f77SDag-Erling Smørgrav } 1397*b7579f77SDag-Erling Smørgrav /* add at end */ 1398*b7579f77SDag-Erling Smørgrav if(qstate->errinf) { 1399*b7579f77SDag-Erling Smørgrav struct config_strlist* q = qstate->errinf; 1400*b7579f77SDag-Erling Smørgrav while(q->next) 1401*b7579f77SDag-Erling Smørgrav q = q->next; 1402*b7579f77SDag-Erling Smørgrav q->next = p; 1403*b7579f77SDag-Erling Smørgrav } else qstate->errinf = p; 1404*b7579f77SDag-Erling Smørgrav } 1405*b7579f77SDag-Erling Smørgrav 1406*b7579f77SDag-Erling Smørgrav void errinf_origin(struct module_qstate* qstate, struct sock_list *origin) 1407*b7579f77SDag-Erling Smørgrav { 1408*b7579f77SDag-Erling Smørgrav struct sock_list* p; 1409*b7579f77SDag-Erling Smørgrav if(qstate->env->cfg->val_log_level < 2) 1410*b7579f77SDag-Erling Smørgrav return; 1411*b7579f77SDag-Erling Smørgrav for(p=origin; p; p=p->next) { 1412*b7579f77SDag-Erling Smørgrav char buf[256]; 1413*b7579f77SDag-Erling Smørgrav if(p == origin) 1414*b7579f77SDag-Erling Smørgrav snprintf(buf, sizeof(buf), "from "); 1415*b7579f77SDag-Erling Smørgrav else snprintf(buf, sizeof(buf), "and "); 1416*b7579f77SDag-Erling Smørgrav if(p->len == 0) 1417*b7579f77SDag-Erling Smørgrav snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 1418*b7579f77SDag-Erling Smørgrav "cache"); 1419*b7579f77SDag-Erling Smørgrav else 1420*b7579f77SDag-Erling Smørgrav addr_to_str(&p->addr, p->len, buf+strlen(buf), 1421*b7579f77SDag-Erling Smørgrav sizeof(buf)-strlen(buf)); 1422*b7579f77SDag-Erling Smørgrav errinf(qstate, buf); 1423*b7579f77SDag-Erling Smørgrav } 1424*b7579f77SDag-Erling Smørgrav } 1425*b7579f77SDag-Erling Smørgrav 1426*b7579f77SDag-Erling Smørgrav char* errinf_to_str(struct module_qstate* qstate) 1427*b7579f77SDag-Erling Smørgrav { 1428*b7579f77SDag-Erling Smørgrav char buf[20480]; 1429*b7579f77SDag-Erling Smørgrav char* p = buf; 1430*b7579f77SDag-Erling Smørgrav size_t left = sizeof(buf); 1431*b7579f77SDag-Erling Smørgrav struct config_strlist* s; 1432*b7579f77SDag-Erling Smørgrav char dname[LDNS_MAX_DOMAINLEN+1]; 1433*b7579f77SDag-Erling Smørgrav char* t = ldns_rr_type2str(qstate->qinfo.qtype); 1434*b7579f77SDag-Erling Smørgrav char* c = ldns_rr_class2str(qstate->qinfo.qclass); 1435*b7579f77SDag-Erling Smørgrav if(!t || !c) { 1436*b7579f77SDag-Erling Smørgrav free(t); 1437*b7579f77SDag-Erling Smørgrav free(c); 1438*b7579f77SDag-Erling Smørgrav log_err("malloc failure in errinf_to_str"); 1439*b7579f77SDag-Erling Smørgrav return NULL; 1440*b7579f77SDag-Erling Smørgrav } 1441*b7579f77SDag-Erling Smørgrav dname_str(qstate->qinfo.qname, dname); 1442*b7579f77SDag-Erling Smørgrav snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c); 1443*b7579f77SDag-Erling Smørgrav free(t); 1444*b7579f77SDag-Erling Smørgrav free(c); 1445*b7579f77SDag-Erling Smørgrav left -= strlen(p); p += strlen(p); 1446*b7579f77SDag-Erling Smørgrav if(!qstate->errinf) 1447*b7579f77SDag-Erling Smørgrav snprintf(p, left, " misc failure"); 1448*b7579f77SDag-Erling Smørgrav else for(s=qstate->errinf; s; s=s->next) { 1449*b7579f77SDag-Erling Smørgrav snprintf(p, left, " %s", s->str); 1450*b7579f77SDag-Erling Smørgrav left -= strlen(p); p += strlen(p); 1451*b7579f77SDag-Erling Smørgrav } 1452*b7579f77SDag-Erling Smørgrav p = strdup(buf); 1453*b7579f77SDag-Erling Smørgrav if(!p) 1454*b7579f77SDag-Erling Smørgrav log_err("malloc failure in errinf_to_str"); 1455*b7579f77SDag-Erling Smørgrav return p; 1456*b7579f77SDag-Erling Smørgrav } 1457*b7579f77SDag-Erling Smørgrav 1458*b7579f77SDag-Erling Smørgrav void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr) 1459*b7579f77SDag-Erling Smørgrav { 1460*b7579f77SDag-Erling Smørgrav char buf[1024]; 1461*b7579f77SDag-Erling Smørgrav char dname[LDNS_MAX_DOMAINLEN+1]; 1462*b7579f77SDag-Erling Smørgrav char *t, *c; 1463*b7579f77SDag-Erling Smørgrav if(qstate->env->cfg->val_log_level < 2 || !rr) 1464*b7579f77SDag-Erling Smørgrav return; 1465*b7579f77SDag-Erling Smørgrav t = ldns_rr_type2str(ntohs(rr->rk.type)); 1466*b7579f77SDag-Erling Smørgrav c = ldns_rr_class2str(ntohs(rr->rk.rrset_class)); 1467*b7579f77SDag-Erling Smørgrav if(!t || !c) { 1468*b7579f77SDag-Erling Smørgrav free(t); 1469*b7579f77SDag-Erling Smørgrav free(c); 1470*b7579f77SDag-Erling Smørgrav log_err("malloc failure in errinf_rrset"); 1471*b7579f77SDag-Erling Smørgrav return; 1472*b7579f77SDag-Erling Smørgrav } 1473*b7579f77SDag-Erling Smørgrav dname_str(rr->rk.dname, dname); 1474*b7579f77SDag-Erling Smørgrav snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c); 1475*b7579f77SDag-Erling Smørgrav free(t); 1476*b7579f77SDag-Erling Smørgrav free(c); 1477*b7579f77SDag-Erling Smørgrav errinf(qstate, buf); 1478*b7579f77SDag-Erling Smørgrav } 1479*b7579f77SDag-Erling Smørgrav 1480*b7579f77SDag-Erling Smørgrav void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname) 1481*b7579f77SDag-Erling Smørgrav { 1482*b7579f77SDag-Erling Smørgrav char b[1024]; 1483*b7579f77SDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN+1]; 1484*b7579f77SDag-Erling Smørgrav if(qstate->env->cfg->val_log_level < 2 || !str || !dname) 1485*b7579f77SDag-Erling Smørgrav return; 1486*b7579f77SDag-Erling Smørgrav dname_str(dname, buf); 1487*b7579f77SDag-Erling Smørgrav snprintf(b, sizeof(b), "%s %s", str, buf); 1488*b7579f77SDag-Erling Smørgrav errinf(qstate, b); 1489*b7579f77SDag-Erling Smørgrav } 1490