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