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