1712b2f30Ssthen /* 2712b2f30Ssthen * testcode/testbound.c - test program for unbound. 3712b2f30Ssthen * 4712b2f30Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved. 5712b2f30Ssthen * 6712b2f30Ssthen * This software is open source. 7712b2f30Ssthen * 8712b2f30Ssthen * Redistribution and use in source and binary forms, with or without 9712b2f30Ssthen * modification, are permitted provided that the following conditions 10712b2f30Ssthen * are met: 11712b2f30Ssthen * 12712b2f30Ssthen * Redistributions of source code must retain the above copyright notice, 13712b2f30Ssthen * this list of conditions and the following disclaimer. 14712b2f30Ssthen * 15712b2f30Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16712b2f30Ssthen * this list of conditions and the following disclaimer in the documentation 17712b2f30Ssthen * and/or other materials provided with the distribution. 18712b2f30Ssthen * 19712b2f30Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20712b2f30Ssthen * be used to endorse or promote products derived from this software without 21712b2f30Ssthen * specific prior written permission. 22712b2f30Ssthen * 23712b2f30Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24712b2f30Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25712b2f30Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26712b2f30Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27712b2f30Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28712b2f30Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29712b2f30Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30712b2f30Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31712b2f30Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32712b2f30Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33712b2f30Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34712b2f30Ssthen * 35712b2f30Ssthen */ 36712b2f30Ssthen /** 37712b2f30Ssthen * \file 38712b2f30Ssthen * Exits with code 1 on a failure. 0 if all unit tests are successful. 39712b2f30Ssthen */ 40712b2f30Ssthen 41712b2f30Ssthen #include "config.h" 42712b2f30Ssthen #ifdef HAVE_TIME_H 43712b2f30Ssthen # include <time.h> 44712b2f30Ssthen #endif 45cddcdaaaSsthen #include <ctype.h> 46712b2f30Ssthen #include "testcode/testpkts.h" 47712b2f30Ssthen #include "testcode/replay.h" 48712b2f30Ssthen #include "testcode/fake_event.h" 49712b2f30Ssthen #include "daemon/remote.h" 50cddcdaaaSsthen #include "libunbound/worker.h" 51*2682a17cSsthen #include "daemon/worker.h" 52712b2f30Ssthen #include "util/config_file.h" 53712b2f30Ssthen #include "sldns/keyraw.h" 54cddcdaaaSsthen #ifdef UB_ON_WINDOWS 55cddcdaaaSsthen #include "winrc/win_svc.h" 56cddcdaaaSsthen #endif 57712b2f30Ssthen 58712b2f30Ssthen /** signal that this is a testbound compile */ 59712b2f30Ssthen #define unbound_testbound 1 60cddcdaaaSsthen /** renamed main routine */ 61cddcdaaaSsthen int daemon_main(int argc, char* argv[]); 62712b2f30Ssthen /** 63712b2f30Ssthen * include the main program from the unbound daemon. 64712b2f30Ssthen * rename main to daemon_main to call it 65712b2f30Ssthen */ 66712b2f30Ssthen #define main daemon_main 67712b2f30Ssthen #include "daemon/unbound.c" 68712b2f30Ssthen #undef main 69712b2f30Ssthen 70712b2f30Ssthen /** maximum line length for lines in the replay file. */ 71712b2f30Ssthen #define MAX_LINE_LEN 1024 72712b2f30Ssthen /** config files (removed at exit) */ 73712b2f30Ssthen static struct config_strlist* cfgfiles = NULL; 74712b2f30Ssthen 75712b2f30Ssthen /** give commandline usage for testbound. */ 76712b2f30Ssthen static void 77712b2f30Ssthen testbound_usage(void) 78712b2f30Ssthen { 79712b2f30Ssthen printf("usage: testbound [options]\n"); 80712b2f30Ssthen printf("\ttest the unbound daemon.\n"); 81712b2f30Ssthen printf("-h this help\n"); 82712b2f30Ssthen printf("-p file playback text file\n"); 83712b2f30Ssthen printf("-1 detect SHA1 support (exit code 0 or 1)\n"); 84712b2f30Ssthen printf("-2 detect SHA256 support (exit code 0 or 1)\n"); 85712b2f30Ssthen printf("-g detect GOST support (exit code 0 or 1)\n"); 86712b2f30Ssthen printf("-e detect ECDSA support (exit code 0 or 1)\n"); 87712b2f30Ssthen printf("-c detect CLIENT_SUBNET support (exit code 0 or 1)\n"); 88712b2f30Ssthen printf("-i detect IPSECMOD support (exit code 0 or 1)\n"); 89712b2f30Ssthen printf("-s testbound self-test - unit test of testbound parts.\n"); 90712b2f30Ssthen printf("-o str unbound commandline options separated by spaces.\n"); 91712b2f30Ssthen printf("Version %s\n", PACKAGE_VERSION); 92712b2f30Ssthen printf("BSD licensed, see LICENSE file in source package.\n"); 93712b2f30Ssthen printf("Report bugs to %s.\n", PACKAGE_BUGREPORT); 94712b2f30Ssthen } 95712b2f30Ssthen 96712b2f30Ssthen /** Max number of arguments to pass to unbound. */ 97712b2f30Ssthen #define MAXARG 100 98712b2f30Ssthen 99712b2f30Ssthen /** 100712b2f30Ssthen * Add options from string to passed argc. splits on whitespace. 101712b2f30Ssthen * @param args: the option argument, "-v -p 12345" or so. 102712b2f30Ssthen * @param pass_argc: ptr to the argc for unbound. Modified. 103712b2f30Ssthen * @param pass_argv: the argv to pass to unbound. Modified. 104712b2f30Ssthen */ 105712b2f30Ssthen static void 106712b2f30Ssthen add_opts(const char* args, int* pass_argc, char* pass_argv[]) 107712b2f30Ssthen { 108712b2f30Ssthen const char *p = args, *np; 109712b2f30Ssthen size_t len; 110712b2f30Ssthen while(p && isspace((unsigned char)*p)) 111712b2f30Ssthen p++; 112712b2f30Ssthen while(p && *p) { 113712b2f30Ssthen /* find location of next string and length of this one */ 114712b2f30Ssthen if((np = strchr(p, ' '))) 115712b2f30Ssthen len = (size_t)(np-p); 116712b2f30Ssthen else len = strlen(p); 117712b2f30Ssthen /* allocate and copy option */ 118712b2f30Ssthen if(*pass_argc >= MAXARG-1) 119712b2f30Ssthen fatal_exit("too many arguments: '%s'", p); 120712b2f30Ssthen pass_argv[*pass_argc] = (char*)malloc(len+1); 121712b2f30Ssthen if(!pass_argv[*pass_argc]) 122712b2f30Ssthen fatal_exit("add_opts: out of memory"); 123712b2f30Ssthen memcpy(pass_argv[*pass_argc], p, len); 124712b2f30Ssthen pass_argv[*pass_argc][len] = 0; 125712b2f30Ssthen (*pass_argc)++; 126712b2f30Ssthen /* go to next option */ 127712b2f30Ssthen p = np; 128712b2f30Ssthen while(p && isspace((unsigned char)*p)) 129712b2f30Ssthen p++; 130712b2f30Ssthen } 131712b2f30Ssthen } 132712b2f30Ssthen 133712b2f30Ssthen /** pretty print commandline for unbound in this test */ 134712b2f30Ssthen static void 135712b2f30Ssthen echo_cmdline(int argc, char* argv[]) 136712b2f30Ssthen { 137712b2f30Ssthen int i; 138712b2f30Ssthen fprintf(stderr, "testbound is starting:"); 139712b2f30Ssthen for(i=0; i<argc; i++) { 140712b2f30Ssthen fprintf(stderr, " [%s]", argv[i]); 141712b2f30Ssthen } 142712b2f30Ssthen fprintf(stderr, "\n"); 143712b2f30Ssthen } 144712b2f30Ssthen 145712b2f30Ssthen /** spool temp file name */ 146712b2f30Ssthen static void 147712b2f30Ssthen spool_temp_file_name(int* lineno, FILE* cfg, char* id) 148712b2f30Ssthen { 149712b2f30Ssthen char line[MAX_LINE_LEN]; 150712b2f30Ssthen /* find filename for new file */ 151712b2f30Ssthen while(isspace((unsigned char)*id)) 152712b2f30Ssthen id++; 153712b2f30Ssthen if(*id == '\0') 154712b2f30Ssthen fatal_exit("TEMPFILE_NAME must have id, line %d", *lineno); 155a6cc1574Ssthen strip_end_white(id); 156712b2f30Ssthen fake_temp_file("_temp_", id, line, sizeof(line)); 157712b2f30Ssthen fprintf(cfg, "\"%s\"\n", line); 158712b2f30Ssthen } 159712b2f30Ssthen 160712b2f30Ssthen /** spool temp file */ 161712b2f30Ssthen static void 162712b2f30Ssthen spool_temp_file(FILE* in, int* lineno, char* id) 163712b2f30Ssthen { 164712b2f30Ssthen char line[MAX_LINE_LEN]; 165712b2f30Ssthen char* parse; 166712b2f30Ssthen FILE* spool; 167712b2f30Ssthen /* find filename for new file */ 168712b2f30Ssthen while(isspace((unsigned char)*id)) 169712b2f30Ssthen id++; 170712b2f30Ssthen if(*id == '\0') 171712b2f30Ssthen fatal_exit("TEMPFILE_CONTENTS must have id, line %d", *lineno); 172a6cc1574Ssthen strip_end_white(id); 173712b2f30Ssthen fake_temp_file("_temp_", id, line, sizeof(line)); 174712b2f30Ssthen /* open file and spool to it */ 175712b2f30Ssthen spool = fopen(line, "w"); 176712b2f30Ssthen if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno)); 177712b2f30Ssthen fprintf(stderr, "testbound is spooling temp file: %s\n", line); 178712b2f30Ssthen if(!cfg_strlist_insert(&cfgfiles, strdup(line))) 179712b2f30Ssthen fatal_exit("out of memory"); 180712b2f30Ssthen line[sizeof(line)-1] = 0; 181712b2f30Ssthen while(fgets(line, MAX_LINE_LEN-1, in)) { 182712b2f30Ssthen parse = line; 183712b2f30Ssthen (*lineno)++; 184712b2f30Ssthen while(isspace((unsigned char)*parse)) 185712b2f30Ssthen parse++; 186712b2f30Ssthen if(strncmp(parse, "$INCLUDE_TEMPFILE", 17) == 0) { 187712b2f30Ssthen char l2[MAX_LINE_LEN-30]; /* -30 makes it fit with 188712b2f30Ssthen a preceding $INCLUDE in the buf line[] */ 189712b2f30Ssthen char* tid = parse+17; 190712b2f30Ssthen while(isspace((unsigned char)*tid)) 191712b2f30Ssthen tid++; 192a6cc1574Ssthen strip_end_white(tid); 193712b2f30Ssthen fake_temp_file("_temp_", tid, l2, sizeof(l2)); 194712b2f30Ssthen snprintf(line, sizeof(line), "$INCLUDE %s\n", l2); 195712b2f30Ssthen } 196712b2f30Ssthen if(strncmp(parse, "TEMPFILE_END", 12) == 0) { 197712b2f30Ssthen fclose(spool); 198712b2f30Ssthen return; 199712b2f30Ssthen } 200712b2f30Ssthen fputs(line, spool); 201712b2f30Ssthen } 202712b2f30Ssthen fatal_exit("no TEMPFILE_END in input file"); 203712b2f30Ssthen } 204712b2f30Ssthen 205712b2f30Ssthen /** spool autotrust file */ 206712b2f30Ssthen static void 207712b2f30Ssthen spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id) 208712b2f30Ssthen { 209712b2f30Ssthen char line[MAX_LINE_LEN]; 210712b2f30Ssthen char* parse; 211712b2f30Ssthen FILE* spool; 212712b2f30Ssthen /* find filename for new file */ 213712b2f30Ssthen while(isspace((unsigned char)*id)) 214712b2f30Ssthen id++; 215712b2f30Ssthen if(*id == '\0') 216712b2f30Ssthen fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno); 217a6cc1574Ssthen strip_end_white(id); 218712b2f30Ssthen fake_temp_file("_auto_", id, line, sizeof(line)); 219712b2f30Ssthen /* add option for the file */ 220712b2f30Ssthen fprintf(cfg, "server: auto-trust-anchor-file: \"%s\"\n", line); 221712b2f30Ssthen /* open file and spool to it */ 222712b2f30Ssthen spool = fopen(line, "w"); 223712b2f30Ssthen if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno)); 224712b2f30Ssthen fprintf(stderr, "testbound is spooling key file: %s\n", line); 225712b2f30Ssthen if(!cfg_strlist_insert(&cfgfiles, strdup(line))) 226712b2f30Ssthen fatal_exit("out of memory"); 227712b2f30Ssthen line[sizeof(line)-1] = 0; 228712b2f30Ssthen while(fgets(line, MAX_LINE_LEN-1, in)) { 229712b2f30Ssthen parse = line; 230712b2f30Ssthen (*lineno)++; 231712b2f30Ssthen while(isspace((unsigned char)*parse)) 232712b2f30Ssthen parse++; 233712b2f30Ssthen if(strncmp(parse, "AUTOTRUST_END", 13) == 0) { 234712b2f30Ssthen fclose(spool); 235712b2f30Ssthen return; 236712b2f30Ssthen } 237712b2f30Ssthen fputs(line, spool); 238712b2f30Ssthen } 239712b2f30Ssthen fatal_exit("no AUTOTRUST_END in input file"); 240712b2f30Ssthen } 241712b2f30Ssthen 242712b2f30Ssthen /** process config elements */ 243712b2f30Ssthen static void 244712b2f30Ssthen setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[]) 245712b2f30Ssthen { 246712b2f30Ssthen char configfile[MAX_LINE_LEN]; 247712b2f30Ssthen char line[MAX_LINE_LEN]; 248712b2f30Ssthen char* parse; 249712b2f30Ssthen FILE* cfg; 250712b2f30Ssthen fake_temp_file("_cfg", "", configfile, sizeof(configfile)); 251712b2f30Ssthen add_opts("-c", pass_argc, pass_argv); 252712b2f30Ssthen add_opts(configfile, pass_argc, pass_argv); 253712b2f30Ssthen cfg = fopen(configfile, "w"); 254712b2f30Ssthen if(!cfg) fatal_exit("could not open %s: %s", 255712b2f30Ssthen configfile, strerror(errno)); 256712b2f30Ssthen if(!cfg_strlist_insert(&cfgfiles, strdup(configfile))) 257712b2f30Ssthen fatal_exit("out of memory"); 258712b2f30Ssthen line[sizeof(line)-1] = 0; 259712b2f30Ssthen /* some basic settings to not pollute the host system */ 260712b2f30Ssthen fprintf(cfg, "server: use-syslog: no\n"); 261712b2f30Ssthen fprintf(cfg, " directory: \"\"\n"); 262712b2f30Ssthen fprintf(cfg, " chroot: \"\"\n"); 263712b2f30Ssthen fprintf(cfg, " username: \"\"\n"); 264712b2f30Ssthen fprintf(cfg, " pidfile: \"\"\n"); 265712b2f30Ssthen fprintf(cfg, " val-log-level: 2\n"); 266a6cc1574Ssthen fprintf(cfg, " log-servfail: yes\n"); 267712b2f30Ssthen fprintf(cfg, "remote-control: control-enable: no\n"); 268712b2f30Ssthen while(fgets(line, MAX_LINE_LEN-1, in)) { 269712b2f30Ssthen parse = line; 270712b2f30Ssthen (*lineno)++; 271712b2f30Ssthen while(isspace((unsigned char)*parse)) 272712b2f30Ssthen parse++; 273712b2f30Ssthen if(!*parse || parse[0] == ';') 274712b2f30Ssthen continue; 275712b2f30Ssthen if(strncmp(parse, "COMMANDLINE", 11) == 0) { 276712b2f30Ssthen parse[strlen(parse)-1] = 0; /* strip off \n */ 277712b2f30Ssthen add_opts(parse+11, pass_argc, pass_argv); 278712b2f30Ssthen continue; 279712b2f30Ssthen } 280712b2f30Ssthen if(strncmp(parse, "AUTOTRUST_FILE", 14) == 0) { 281712b2f30Ssthen spool_auto_file(in, lineno, cfg, parse+14); 282712b2f30Ssthen continue; 283712b2f30Ssthen } 284712b2f30Ssthen if(strncmp(parse, "TEMPFILE_NAME", 13) == 0) { 285712b2f30Ssthen spool_temp_file_name(lineno, cfg, parse+13); 286712b2f30Ssthen continue; 287712b2f30Ssthen } 288712b2f30Ssthen if(strncmp(parse, "TEMPFILE_CONTENTS", 17) == 0) { 289712b2f30Ssthen spool_temp_file(in, lineno, parse+17); 290712b2f30Ssthen continue; 291712b2f30Ssthen } 292712b2f30Ssthen if(strncmp(parse, "CONFIG_END", 10) == 0) { 293712b2f30Ssthen fclose(cfg); 294712b2f30Ssthen return; 295712b2f30Ssthen } 296712b2f30Ssthen fputs(line, cfg); 297712b2f30Ssthen } 298712b2f30Ssthen fatal_exit("No CONFIG_END in input file"); 299712b2f30Ssthen 300712b2f30Ssthen } 301712b2f30Ssthen 302712b2f30Ssthen /** read playback file */ 303712b2f30Ssthen static struct replay_scenario* 304712b2f30Ssthen setup_playback(const char* filename, int* pass_argc, char* pass_argv[]) 305712b2f30Ssthen { 306712b2f30Ssthen struct replay_scenario* scen = NULL; 307712b2f30Ssthen int lineno = 0; 308712b2f30Ssthen 309712b2f30Ssthen if(filename) { 310712b2f30Ssthen FILE *in = fopen(filename, "rb"); 311712b2f30Ssthen if(!in) { 312712b2f30Ssthen perror(filename); 313712b2f30Ssthen exit(1); 314712b2f30Ssthen } 315712b2f30Ssthen setup_config(in, &lineno, pass_argc, pass_argv); 316712b2f30Ssthen scen = replay_scenario_read(in, filename, &lineno); 317712b2f30Ssthen fclose(in); 318712b2f30Ssthen if(!scen) 319712b2f30Ssthen fatal_exit("Could not read: %s", filename); 320712b2f30Ssthen } 321712b2f30Ssthen else fatal_exit("need a playback file (-p)"); 322712b2f30Ssthen log_info("Scenario: %s", scen->title); 323712b2f30Ssthen return scen; 324712b2f30Ssthen } 325712b2f30Ssthen 326712b2f30Ssthen /** remove config file at exit */ 327cddcdaaaSsthen static void remove_configfile(void) 328712b2f30Ssthen { 329712b2f30Ssthen struct config_strlist* p; 330712b2f30Ssthen for(p=cfgfiles; p; p=p->next) 331712b2f30Ssthen unlink(p->str); 332712b2f30Ssthen config_delstrlist(cfgfiles); 333712b2f30Ssthen cfgfiles = NULL; 334712b2f30Ssthen } 335712b2f30Ssthen 336712b2f30Ssthen /** 337712b2f30Ssthen * Main fake event test program. Setup, teardown and report errors. 338712b2f30Ssthen * @param argc: arg count. 339712b2f30Ssthen * @param argv: array of commandline arguments. 340712b2f30Ssthen * @return program failure if test fails. 341712b2f30Ssthen */ 342712b2f30Ssthen int 343712b2f30Ssthen main(int argc, char* argv[]) 344712b2f30Ssthen { 345712b2f30Ssthen int c, res; 346712b2f30Ssthen int pass_argc = 0; 347712b2f30Ssthen char* pass_argv[MAXARG]; 348712b2f30Ssthen char* playback_file = NULL; 349712b2f30Ssthen int init_optind = optind; 350712b2f30Ssthen char* init_optarg = optarg; 351712b2f30Ssthen struct replay_scenario* scen = NULL; 352712b2f30Ssthen 353712b2f30Ssthen /* we do not want the test to depend on the timezone */ 354712b2f30Ssthen (void)putenv("TZ=UTC"); 35566a34dc2Ssthen memset(pass_argv, 0, sizeof(pass_argv)); 35672f58708Ssthen #ifdef HAVE_SYSTEMD 35772f58708Ssthen /* we do not want the test to use systemd daemon startup notification*/ 35872f58708Ssthen (void)unsetenv("NOTIFY_SOCKET"); 35972f58708Ssthen #endif /* HAVE_SYSTEMD */ 360712b2f30Ssthen 36183152a15Ssthen checklock_start(); 362712b2f30Ssthen log_init(NULL, 0, NULL); 363712b2f30Ssthen /* determine commandline options for the daemon */ 364712b2f30Ssthen pass_argc = 1; 365712b2f30Ssthen pass_argv[0] = "unbound"; 366712b2f30Ssthen add_opts("-d", &pass_argc, pass_argv); 367712b2f30Ssthen while( (c=getopt(argc, argv, "12egciho:p:s")) != -1) { 368712b2f30Ssthen switch(c) { 369712b2f30Ssthen case 's': 370712b2f30Ssthen free(pass_argv[1]); 371712b2f30Ssthen testbound_selftest(); 372712b2f30Ssthen checklock_stop(); 373712b2f30Ssthen if(log_get_lock()) { 374b0dfc31bSsthen lock_basic_destroy((lock_basic_type*)log_get_lock()); 375712b2f30Ssthen } 376712b2f30Ssthen exit(0); 377712b2f30Ssthen case '1': 378712b2f30Ssthen #ifdef USE_SHA1 379712b2f30Ssthen printf("SHA1 supported\n"); 380712b2f30Ssthen exit(0); 381712b2f30Ssthen #else 382712b2f30Ssthen printf("SHA1 not supported\n"); 383712b2f30Ssthen exit(1); 384712b2f30Ssthen #endif 385712b2f30Ssthen break; 386712b2f30Ssthen case '2': 387712b2f30Ssthen #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 388712b2f30Ssthen printf("SHA256 supported\n"); 389712b2f30Ssthen exit(0); 390712b2f30Ssthen #else 391712b2f30Ssthen printf("SHA256 not supported\n"); 392712b2f30Ssthen exit(1); 393712b2f30Ssthen #endif 394712b2f30Ssthen break; 395712b2f30Ssthen case 'e': 396712b2f30Ssthen #if defined(USE_ECDSA) 397712b2f30Ssthen printf("ECDSA supported\n"); 398712b2f30Ssthen exit(0); 399712b2f30Ssthen #else 400712b2f30Ssthen printf("ECDSA not supported\n"); 401712b2f30Ssthen exit(1); 402712b2f30Ssthen #endif 403712b2f30Ssthen break; 404712b2f30Ssthen case 'g': 405712b2f30Ssthen #ifdef USE_GOST 406712b2f30Ssthen if(sldns_key_EVP_load_gost_id()) { 407712b2f30Ssthen printf("GOST supported\n"); 408712b2f30Ssthen exit(0); 409712b2f30Ssthen } else { 410712b2f30Ssthen printf("GOST not supported\n"); 411712b2f30Ssthen exit(1); 412712b2f30Ssthen } 413712b2f30Ssthen #else 414712b2f30Ssthen printf("GOST not supported\n"); 415712b2f30Ssthen exit(1); 416712b2f30Ssthen #endif 417712b2f30Ssthen break; 418712b2f30Ssthen case 'c': 419712b2f30Ssthen #ifdef CLIENT_SUBNET 420712b2f30Ssthen printf("CLIENT_SUBNET supported\n"); 421712b2f30Ssthen exit(0); 422712b2f30Ssthen #else 423712b2f30Ssthen printf("CLIENT_SUBNET not supported\n"); 424712b2f30Ssthen exit(1); 425712b2f30Ssthen #endif 426712b2f30Ssthen break; 427712b2f30Ssthen case 'i': 428712b2f30Ssthen #ifdef USE_IPSECMOD 429712b2f30Ssthen printf("IPSECMOD supported\n"); 430712b2f30Ssthen exit(0); 431712b2f30Ssthen #else 432712b2f30Ssthen printf("IPSECMOD not supported\n"); 433712b2f30Ssthen exit(1); 434712b2f30Ssthen #endif 435712b2f30Ssthen break; 436712b2f30Ssthen case 'p': 437712b2f30Ssthen playback_file = optarg; 438712b2f30Ssthen break; 439712b2f30Ssthen case 'o': 440712b2f30Ssthen add_opts(optarg, &pass_argc, pass_argv); 441712b2f30Ssthen break; 442712b2f30Ssthen case '?': 443712b2f30Ssthen case 'h': 444712b2f30Ssthen default: 445712b2f30Ssthen testbound_usage(); 4468771e50fSsthen exit(1); 447712b2f30Ssthen } 448712b2f30Ssthen } 449712b2f30Ssthen argc -= optind; 4508771e50fSsthen /* argv += optind; not using further arguments */ 451712b2f30Ssthen if(argc != 0) { 452712b2f30Ssthen testbound_usage(); 4538771e50fSsthen exit(1); 454712b2f30Ssthen } 455712b2f30Ssthen log_info("Start of %s testbound program.", PACKAGE_STRING); 456712b2f30Ssthen if(atexit(&remove_configfile) != 0) 457712b2f30Ssthen fatal_exit("atexit() failed: %s", strerror(errno)); 458712b2f30Ssthen 459712b2f30Ssthen /* setup test environment */ 460712b2f30Ssthen scen = setup_playback(playback_file, &pass_argc, pass_argv); 461712b2f30Ssthen /* init fake event backend */ 462712b2f30Ssthen fake_event_init(scen); 463712b2f30Ssthen 464712b2f30Ssthen pass_argv[pass_argc] = NULL; 465712b2f30Ssthen echo_cmdline(pass_argc, pass_argv); 466712b2f30Ssthen 467712b2f30Ssthen /* reset getopt processing */ 468712b2f30Ssthen optind = init_optind; 469712b2f30Ssthen optarg = init_optarg; 470712b2f30Ssthen 471712b2f30Ssthen /* run the normal daemon */ 472712b2f30Ssthen res = daemon_main(pass_argc, pass_argv); 473712b2f30Ssthen 474712b2f30Ssthen fake_event_cleanup(); 475712b2f30Ssthen for(c=1; c<pass_argc; c++) 476712b2f30Ssthen free(pass_argv[c]); 477712b2f30Ssthen if(res == 0) { 478712b2f30Ssthen log_info("Testbound Exit Success\n"); 479b0dfc31bSsthen /* remove configfile from here, the atexit() is for when 480b0dfc31bSsthen * there is a crash to remove the tmpdir file. 481b0dfc31bSsthen * This one removes the file while alloc and log locks are 482b0dfc31bSsthen * still valid, and can be logged (for memory calculation), 483b0dfc31bSsthen * it leaves the ptr NULL so the atexit does nothing. */ 484b0dfc31bSsthen remove_configfile(); 485712b2f30Ssthen if(log_get_lock()) { 486b0dfc31bSsthen lock_basic_destroy((lock_basic_type*)log_get_lock()); 487712b2f30Ssthen } 488712b2f30Ssthen #ifdef HAVE_PTHREAD 489712b2f30Ssthen /* dlopen frees its thread state (dlopen of gost engine) */ 490712b2f30Ssthen pthread_exit(NULL); 491712b2f30Ssthen #endif 492712b2f30Ssthen } 493712b2f30Ssthen return res; 494712b2f30Ssthen } 495712b2f30Ssthen 496712b2f30Ssthen /* fake remote control */ 497712b2f30Ssthen struct listen_port* daemon_remote_open_ports(struct config_file* 498712b2f30Ssthen ATTR_UNUSED(cfg)) 499712b2f30Ssthen { 500712b2f30Ssthen return NULL; 501712b2f30Ssthen } 502712b2f30Ssthen 503712b2f30Ssthen struct daemon_remote* daemon_remote_create(struct config_file* ATTR_UNUSED(cfg)) 504712b2f30Ssthen { 505712b2f30Ssthen return (struct daemon_remote*)calloc(1,1); 506712b2f30Ssthen } 507712b2f30Ssthen 508712b2f30Ssthen void daemon_remote_delete(struct daemon_remote* rc) 509712b2f30Ssthen { 510712b2f30Ssthen free(rc); 511712b2f30Ssthen } 512712b2f30Ssthen 513712b2f30Ssthen void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc)) 514712b2f30Ssthen { 515712b2f30Ssthen /* nothing */ 516712b2f30Ssthen } 517712b2f30Ssthen 518712b2f30Ssthen int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc), 519*2682a17cSsthen struct listen_port* ATTR_UNUSED(ports), struct worker* worker) 520712b2f30Ssthen { 521*2682a17cSsthen struct replay_runtime* runtime = (struct replay_runtime*)worker->base; 522*2682a17cSsthen runtime->daemon = worker->daemon; 523712b2f30Ssthen return 1; 524712b2f30Ssthen } 525712b2f30Ssthen 526712b2f30Ssthen int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 527712b2f30Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 528712b2f30Ssthen struct comm_reply* ATTR_UNUSED(repinfo)) 529712b2f30Ssthen { 530712b2f30Ssthen log_assert(0); 531712b2f30Ssthen return 0; 532712b2f30Ssthen } 533712b2f30Ssthen 534712b2f30Ssthen int remote_control_callback(struct comm_point* ATTR_UNUSED(c), 535712b2f30Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 536712b2f30Ssthen struct comm_reply* ATTR_UNUSED(repinfo)) 537712b2f30Ssthen { 538712b2f30Ssthen log_assert(0); 539712b2f30Ssthen return 0; 540712b2f30Ssthen } 541712b2f30Ssthen 542712b2f30Ssthen void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) 543712b2f30Ssthen { 544712b2f30Ssthen log_assert(0); 545712b2f30Ssthen } 546712b2f30Ssthen 547cddcdaaaSsthen #ifdef UB_ON_WINDOWS 548712b2f30Ssthen void wsvc_command_option(const char* ATTR_UNUSED(wopt), 549712b2f30Ssthen const char* ATTR_UNUSED(cfgfile), int ATTR_UNUSED(v), 550712b2f30Ssthen int ATTR_UNUSED(c)) 551712b2f30Ssthen { 552712b2f30Ssthen log_assert(0); 553712b2f30Ssthen } 554cddcdaaaSsthen #endif 555712b2f30Ssthen 556cddcdaaaSsthen #ifdef UB_ON_WINDOWS 557712b2f30Ssthen void wsvc_setup_worker(struct worker* ATTR_UNUSED(worker)) 558712b2f30Ssthen { 559712b2f30Ssthen /* do nothing */ 560712b2f30Ssthen } 561cddcdaaaSsthen #endif 562712b2f30Ssthen 563cddcdaaaSsthen #ifdef UB_ON_WINDOWS 564712b2f30Ssthen void wsvc_desetup_worker(struct worker* ATTR_UNUSED(worker)) 565712b2f30Ssthen { 566712b2f30Ssthen /* do nothing */ 567712b2f30Ssthen } 568cddcdaaaSsthen #endif 569712b2f30Ssthen 570712b2f30Ssthen #ifdef UB_ON_WINDOWS 571712b2f30Ssthen void worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), 572712b2f30Ssthen void* ATTR_UNUSED(arg)) 573712b2f30Ssthen { 574712b2f30Ssthen log_assert(0); 575712b2f30Ssthen } 576712b2f30Ssthen 577712b2f30Ssthen void wsvc_cron_cb(void* ATTR_UNUSED(arg)) 578712b2f30Ssthen { 579712b2f30Ssthen log_assert(0); 580712b2f30Ssthen } 581712b2f30Ssthen #endif /* UB_ON_WINDOWS */ 582712b2f30Ssthen 583d7b4a113Ssthen int tcp_connect_errno_needs_log(struct sockaddr* ATTR_UNUSED(addr), 584d7b4a113Ssthen socklen_t ATTR_UNUSED(addrlen)) 585d7b4a113Ssthen { 586d7b4a113Ssthen return 1; 587d7b4a113Ssthen } 588d7b4a113Ssthen 589d7b4a113Ssthen int squelch_err_ssl_handshake(unsigned long ATTR_UNUSED(err)) 590d7b4a113Ssthen { 591d7b4a113Ssthen return 0; 592d7b4a113Ssthen } 59383152a15Ssthen 59483152a15Ssthen void listen_setup_locks(void) 59583152a15Ssthen { 59683152a15Ssthen /* nothing */ 59783152a15Ssthen } 59883152a15Ssthen 59983152a15Ssthen void listen_desetup_locks(void) 60083152a15Ssthen { 60183152a15Ssthen /* nothing */ 60283152a15Ssthen } 603