1/* 2 * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <time.h> 24#include <unistd.h> 25 26#include <isc/app.h> 27#include <isc/buffer.h> 28#include <isc/entropy.h> 29#include <isc/hash.h> 30#include <isc/mem.h> 31#include <isc/os.h> 32#include <isc/string.h> 33#include <isc/socket.h> 34#include <isc/task.h> 35#include <isc/timer.h> 36#include <isc/util.h> 37 38#include <dns/db.h> 39#include <dns/fixedname.h> 40#include <dns/log.h> 41#include <dns/name.h> 42#include <dns/result.h> 43#include <dns/view.h> 44#include <dns/zone.h> 45 46#include <dst/dst.h> 47 48#include "dnstest.h" 49 50isc_mem_t *mctx = NULL; 51isc_entropy_t *ectx = NULL; 52isc_log_t *lctx = NULL; 53isc_taskmgr_t *taskmgr = NULL; 54isc_task_t *maintask = NULL; 55isc_timermgr_t *timermgr = NULL; 56isc_socketmgr_t *socketmgr = NULL; 57dns_zonemgr_t *zonemgr = NULL; 58isc_boolean_t app_running = ISC_FALSE; 59int ncpus; 60 61static isc_boolean_t hash_active = ISC_FALSE, dst_active = ISC_FALSE; 62 63/* 64 * Logging categories: this needs to match the list in bin/named/log.c. 65 */ 66static isc_logcategory_t categories[] = { 67 { "", 0 }, 68 { "client", 0 }, 69 { "network", 0 }, 70 { "update", 0 }, 71 { "queries", 0 }, 72 { "unmatched", 0 }, 73 { "update-security", 0 }, 74 { "query-errors", 0 }, 75 { NULL, 0 } 76}; 77 78static void 79cleanup_managers() { 80 if (app_running) 81 isc_app_finish(); 82 if (socketmgr != NULL) 83 isc_socketmgr_destroy(&socketmgr); 84 if (maintask != NULL) 85 isc_task_destroy(&maintask); 86 if (taskmgr != NULL) 87 isc_taskmgr_destroy(&taskmgr); 88 if (timermgr != NULL) 89 isc_timermgr_destroy(&timermgr); 90} 91 92static isc_result_t 93create_managers() { 94 isc_result_t result; 95#ifdef ISC_PLATFORM_USETHREADS 96 ncpus = isc_os_ncpus(); 97#else 98 ncpus = 1; 99#endif 100 101 CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr)); 102 CHECK(isc_timermgr_create(mctx, &timermgr)); 103 CHECK(isc_socketmgr_create(mctx, &socketmgr)); 104 CHECK(isc_task_create(taskmgr, 0, &maintask)); 105 return (ISC_R_SUCCESS); 106 107 cleanup: 108 cleanup_managers(); 109 return (result); 110} 111 112isc_result_t 113dns_test_begin(FILE *logfile, isc_boolean_t start_managers) { 114 isc_result_t result; 115 116 if (start_managers) 117 CHECK(isc_app_start()); 118 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 119 CHECK(isc_mem_create(0, 0, &mctx)); 120 CHECK(isc_entropy_create(mctx, &ectx)); 121 122 CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)); 123 hash_active = ISC_TRUE; 124 125 CHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING)); 126 dst_active = ISC_TRUE; 127 128 if (logfile != NULL) { 129 isc_logdestination_t destination; 130 isc_logconfig_t *logconfig = NULL; 131 132 CHECK(isc_log_create(mctx, &lctx, &logconfig)); 133 isc_log_registercategories(lctx, categories); 134 isc_log_setcontext(lctx); 135 dns_log_init(lctx); 136 dns_log_setcontext(lctx); 137 138 destination.file.stream = logfile; 139 destination.file.name = NULL; 140 destination.file.versions = ISC_LOG_ROLLNEVER; 141 destination.file.maximum_size = 0; 142 CHECK(isc_log_createchannel(logconfig, "stderr", 143 ISC_LOG_TOFILEDESC, 144 ISC_LOG_DYNAMIC, 145 &destination, 0)); 146 CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL)); 147 } 148 149 dns_result_register(); 150 151 if (start_managers) 152 CHECK(create_managers()); 153 154 /* 155 * atf-run changes us to a /tmp directory, so tests 156 * that access test data files must first chdir to the proper 157 * location. 158 */ 159 if (chdir(TESTS) == -1) 160 CHECK(ISC_R_FAILURE); 161 162 return (ISC_R_SUCCESS); 163 164 cleanup: 165 dns_test_end(); 166 return (result); 167} 168 169void 170dns_test_end() { 171 if (lctx != NULL) 172 isc_log_destroy(&lctx); 173 if (dst_active) { 174 dst_lib_destroy(); 175 dst_active = ISC_FALSE; 176 } 177 if (hash_active) { 178 isc_hash_destroy(); 179 hash_active = ISC_FALSE; 180 } 181 if (ectx != NULL) 182 isc_entropy_detach(&ectx); 183 184 cleanup_managers(); 185 186 if (mctx != NULL) 187 isc_mem_destroy(&mctx); 188} 189 190/* 191 * Create a zone with origin 'name', return a pointer to the zone object in 192 * 'zonep'. If 'view' is set, add the zone to that view; otherwise, create 193 * a new view for the purpose. 194 * 195 * If the created view is going to be needed by the caller subsequently, 196 * then 'keepview' should be set to true; this will prevent the view 197 * from being detached. In this case, the caller is responsible for 198 * detaching the view. 199 */ 200isc_result_t 201dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, 202 isc_boolean_t keepview) 203{ 204 isc_result_t result; 205 dns_zone_t *zone = NULL; 206 isc_buffer_t buffer; 207 dns_fixedname_t fixorigin; 208 dns_name_t *origin; 209 210 if (view == NULL) 211 CHECK(dns_view_create(mctx, dns_rdataclass_in, "view", &view)); 212 else if (!keepview) 213 keepview = ISC_TRUE; 214 215 CHECK(dns_zone_create(&zone, mctx)); 216 217 isc_buffer_init(&buffer, name, strlen(name)); 218 isc_buffer_add(&buffer, strlen(name)); 219 dns_fixedname_init(&fixorigin); 220 origin = dns_fixedname_name(&fixorigin); 221 CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); 222 CHECK(dns_zone_setorigin(zone, origin)); 223 dns_zone_setview(zone, view); 224 dns_zone_settype(zone, dns_zone_master); 225 dns_zone_setclass(zone, view->rdclass); 226 dns_view_addzone(view, zone); 227 228 if (!keepview) 229 dns_view_detach(&view); 230 231 *zonep = zone; 232 233 return (ISC_R_SUCCESS); 234 235 cleanup: 236 if (zone != NULL) 237 dns_zone_detach(&zone); 238 if (view != NULL) 239 dns_view_detach(&view); 240 return (result); 241} 242 243isc_result_t 244dns_test_setupzonemgr() { 245 isc_result_t result; 246 REQUIRE(zonemgr == NULL); 247 248 result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, 249 &zonemgr); 250 return (result); 251} 252 253isc_result_t 254dns_test_managezone(dns_zone_t *zone) { 255 isc_result_t result; 256 REQUIRE(zonemgr != NULL); 257 258 result = dns_zonemgr_setsize(zonemgr, 1); 259 if (result != ISC_R_SUCCESS) 260 return (result); 261 262 result = dns_zonemgr_managezone(zonemgr, zone); 263 return (result); 264} 265 266void 267dns_test_releasezone(dns_zone_t *zone) { 268 REQUIRE(zonemgr != NULL); 269 dns_zonemgr_releasezone(zonemgr, zone); 270} 271 272void 273dns_test_closezonemgr() { 274 REQUIRE(zonemgr != NULL); 275 276 dns_zonemgr_shutdown(zonemgr); 277 dns_zonemgr_detach(&zonemgr); 278} 279 280/* 281 * Sleep for 'usec' microseconds. 282 */ 283void 284dns_test_nap(isc_uint32_t usec) { 285#ifdef HAVE_NANOSLEEP 286 struct timespec ts; 287 288 ts.tv_sec = usec / 1000000; 289 ts.tv_nsec = (usec % 1000000) * 1000; 290 nanosleep(&ts, NULL); 291#elif HAVE_USLEEP 292 usleep(usec); 293#else 294 /* 295 * No fractional-second sleep function is available, so we 296 * round up to the nearest second and sleep instead 297 */ 298 sleep((usec / 1000000) + 1); 299#endif 300} 301 302isc_result_t 303dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, 304 const char *testfile) 305{ 306 isc_result_t result; 307 dns_fixedname_t fixed; 308 dns_name_t *name; 309 310 dns_fixedname_init(&fixed); 311 name = dns_fixedname_name(&fixed); 312 313 result = dns_name_fromstring(name, origin, 0, NULL); 314 if (result != ISC_R_SUCCESS) 315 return(result); 316 317 result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in, 318 0, NULL, db); 319 if (result != ISC_R_SUCCESS) 320 return (result); 321 322 result = dns_db_load(*db, testfile); 323 return (result); 324} 325