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