1/* 2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: byname_test.c,v 1.33 2009/09/02 23:48:01 tbox Exp $ */ 19 20/*! \file 21 * \author 22 * Principal Author: Bob Halley 23 */ 24 25#include <config.h> 26 27#include <stdlib.h> 28#include <string.h> 29 30#include <isc/app.h> 31#include <isc/commandline.h> 32#include <isc/entropy.h> 33#include <isc/hash.h> 34#include <isc/netaddr.h> 35#include <isc/task.h> 36#include <isc/timer.h> 37#include <isc/util.h> 38 39#include <dns/adb.h> 40#include <dns/cache.h> 41#include <dns/dispatch.h> 42#include <dns/events.h> 43#include <dns/forward.h> 44#include <dns/log.h> 45#include <dns/resolver.h> 46#include <dns/result.h> 47 48static isc_mem_t *mctx = NULL; 49static isc_entropy_t *ectx = NULL; 50static isc_taskmgr_t *taskmgr; 51static dns_view_t *view = NULL; 52static dns_adbfind_t *find = NULL; 53static isc_task_t *task = NULL; 54static dns_fixedname_t name; 55static dns_fixedname_t target; 56static isc_log_t *lctx; 57static isc_logconfig_t *lcfg; 58static unsigned int level = 0; 59 60static void adb_callback(isc_task_t *task, isc_event_t *event); 61 62static void 63log_init(void) { 64 isc_logdestination_t destination; 65 unsigned int flags; 66 67 /* 68 * Setup a logging context. 69 */ 70 RUNTIME_CHECK(isc_log_create(mctx, &lctx, &lcfg) == ISC_R_SUCCESS); 71 isc_log_setcontext(lctx); 72 dns_log_init(lctx); 73 dns_log_setcontext(lctx); 74 75 /* 76 * Create and install the default channel. 77 */ 78 destination.file.stream = stderr; 79 destination.file.name = NULL; 80 destination.file.versions = ISC_LOG_ROLLNEVER; 81 destination.file.maximum_size = 0; 82 flags = ISC_LOG_PRINTTIME; 83 RUNTIME_CHECK(isc_log_createchannel(lcfg, "_default", 84 ISC_LOG_TOFILEDESC, 85 ISC_LOG_DYNAMIC, 86 &destination, flags) == 87 ISC_R_SUCCESS); 88 RUNTIME_CHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL) == 89 ISC_R_SUCCESS); 90 isc_log_setdebuglevel(lctx, level); 91} 92 93static void 94print_addresses(dns_adbfind_t *find) { 95 dns_adbaddrinfo_t *address; 96 97 for (address = ISC_LIST_HEAD(find->list); 98 address != NULL; 99 address = ISC_LIST_NEXT(address, publink)) { 100 isc_netaddr_t netaddr; 101 char text[ISC_NETADDR_FORMATSIZE]; 102 isc_netaddr_fromsockaddr(&netaddr, &address->sockaddr); 103 isc_netaddr_format(&netaddr, text, sizeof(text)); 104 printf("%s\n", text); 105 } 106} 107 108static void 109print_name(dns_name_t *name) { 110 char text[DNS_NAME_FORMATSIZE]; 111 112 dns_name_format(name, text, sizeof(text)); 113 printf("%s\n", text); 114} 115 116static void 117do_find(isc_boolean_t want_event) { 118 isc_result_t result; 119 isc_boolean_t done = ISC_FALSE; 120 unsigned int options; 121 122 options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6; 123 if (want_event) 124 options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT; 125 dns_fixedname_init(&target); 126 result = dns_adb_createfind(view->adb, task, adb_callback, NULL, 127 dns_fixedname_name(&name), 128 dns_rootname, 0, options, 0, 129 dns_fixedname_name(&target), 0, 130 &find); 131 if (result == ISC_R_SUCCESS) { 132 if (!ISC_LIST_EMPTY(find->list)) { 133 /* 134 * We have at least some of the addresses for the 135 * name. 136 */ 137 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0); 138 print_addresses(find); 139 done = ISC_TRUE; 140 } else { 141 /* 142 * We don't know any of the addresses for this 143 * name. 144 */ 145 if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) { 146 /* 147 * And ADB isn't going to send us any events 148 * either. This query loses. 149 */ 150 done = ISC_TRUE; 151 } 152 /* 153 * If the DNS_ADBFIND_WANTEVENT flag was set, we'll 154 * get an event when something happens. 155 */ 156 } 157 } else if (result == DNS_R_ALIAS) { 158 print_name(dns_fixedname_name(&target)); 159 done = ISC_TRUE; 160 } else { 161 printf("dns_adb_createfind() returned %s\n", 162 isc_result_totext(result)); 163 done = ISC_TRUE; 164 } 165 166 if (done) { 167 if (find != NULL) 168 dns_adb_destroyfind(&find); 169 isc_app_shutdown(); 170 } 171} 172 173static void 174adb_callback(isc_task_t *etask, isc_event_t *event) { 175 unsigned int type = event->ev_type; 176 177 REQUIRE(etask == task); 178 179 isc_event_free(&event); 180 dns_adb_destroyfind(&find); 181 182 if (type == DNS_EVENT_ADBMOREADDRESSES) 183 do_find(ISC_FALSE); 184 else if (type == DNS_EVENT_ADBNOMOREADDRESSES) { 185 printf("no more addresses\n"); 186 isc_app_shutdown(); 187 } else { 188 printf("unexpected ADB event type %u\n", type); 189 isc_app_shutdown(); 190 } 191} 192 193static void 194run(isc_task_t *task, isc_event_t *event) { 195 UNUSED(task); 196 do_find(ISC_TRUE); 197 isc_event_free(&event); 198} 199 200int 201main(int argc, char *argv[]) { 202 isc_boolean_t verbose = ISC_FALSE; 203 unsigned int workers = 2; 204 isc_timermgr_t *timermgr; 205 int ch; 206 isc_socketmgr_t *socketmgr; 207 dns_dispatchmgr_t *dispatchmgr; 208 dns_cache_t *cache; 209 isc_buffer_t b; 210 211 RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS); 212 213 dns_result_register(); 214 215 mctx = NULL; 216 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); 217 218 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS); 219 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE) 220 == ISC_R_SUCCESS); 221 222 while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) { 223 switch (ch) { 224 case 'd': 225 level = (unsigned int)atoi(isc_commandline_argument); 226 break; 227 case 'v': 228 verbose = ISC_TRUE; 229 break; 230 case 'w': 231 workers = (unsigned int)atoi(isc_commandline_argument); 232 break; 233 } 234 } 235 236 log_init(); 237 238 if (verbose) { 239 printf("%u workers\n", workers); 240 printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4())); 241 printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6())); 242 } 243 244 taskmgr = NULL; 245 RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) == 246 ISC_R_SUCCESS); 247 task = NULL; 248 RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) == 249 ISC_R_SUCCESS); 250 isc_task_setname(task, "byname", NULL); 251 252 dispatchmgr = NULL; 253 RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr) 254 == ISC_R_SUCCESS); 255 256 timermgr = NULL; 257 RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS); 258 socketmgr = NULL; 259 RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS); 260 261 cache = NULL; 262 RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr, 263 dns_rdataclass_in, "rbt", 0, NULL, 264 &cache) == ISC_R_SUCCESS); 265 266 view = NULL; 267 RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default", 268 &view) == ISC_R_SUCCESS); 269 270 { 271 unsigned int attrs; 272 dns_dispatch_t *disp4 = NULL; 273 dns_dispatch_t *disp6 = NULL; 274 275 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 276 isc_sockaddr_t any4; 277 isc_sockaddr_any(&any4); 278 279 attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; 280 RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, 281 socketmgr, 282 taskmgr, &any4, 283 512, 6, 1024, 284 17, 19, attrs, 285 attrs, &disp4) 286 == ISC_R_SUCCESS); 287 INSIST(disp4 != NULL); 288 } 289 290 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 291 isc_sockaddr_t any6; 292 293 isc_sockaddr_any6(&any6); 294 295 attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP; 296 RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, 297 socketmgr, 298 taskmgr, &any6, 299 512, 6, 1024, 300 17, 19, attrs, 301 attrs, &disp6) 302 == ISC_R_SUCCESS); 303 INSIST(disp6 != NULL); 304 } 305 306 RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 307 socketmgr, 308 timermgr, 0, 309 dispatchmgr, 310 disp4, disp6) == 311 ISC_R_SUCCESS); 312 313 if (disp4 != NULL) 314 dns_dispatch_detach(&disp4); 315 if (disp6 != NULL) 316 dns_dispatch_detach(&disp6); 317 } 318 319 { 320 struct in_addr ina; 321 isc_sockaddr_t sa; 322 isc_sockaddrlist_t sal; 323 324 ISC_LIST_INIT(sal); 325 ina.s_addr = inet_addr("127.0.0.1"); 326 isc_sockaddr_fromin(&sa, &ina, 53); 327 ISC_LIST_APPEND(sal, &sa, link); 328 329 RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname, 330 &sal, dns_fwdpolicy_only) 331 == ISC_R_SUCCESS); 332 } 333 334 dns_view_setcache(view, cache); 335 dns_view_freeze(view); 336 337 dns_cache_detach(&cache); 338 339 printf("name = %s\n", argv[isc_commandline_index]); 340 isc_buffer_init(&b, argv[isc_commandline_index], 341 strlen(argv[isc_commandline_index])); 342 isc_buffer_add(&b, strlen(argv[isc_commandline_index])); 343 dns_fixedname_init(&name); 344 dns_fixedname_init(&target); 345 RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&name), &b, 346 dns_rootname, 0, NULL) == 347 ISC_R_SUCCESS); 348 349 RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS); 350 351 (void)isc_app_run(); 352 353 dns_view_detach(&view); 354 isc_task_shutdown(task); 355 isc_task_detach(&task); 356 357 dns_dispatchmgr_destroy(&dispatchmgr); 358 359 isc_taskmgr_destroy(&taskmgr); 360 361 isc_socketmgr_destroy(&socketmgr); 362 isc_timermgr_destroy(&timermgr); 363 364 isc_log_destroy(&lctx); 365 366 isc_hash_destroy(); 367 isc_entropy_detach(&ectx); 368 369 if (verbose) 370 isc_mem_stats(mctx, stdout); 371 isc_mem_destroy(&mctx); 372 373 isc_app_finish(); 374 375 return (0); 376} 377