xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/pipelined/pipequeries.c (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
1 /*	$NetBSD: pipequeries.c,v 1.4 2020/05/24 19:46:17 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 
20 #include <isc/app.h>
21 #include <isc/base64.h>
22 #include <isc/commandline.h>
23 #include <isc/hash.h>
24 #include <isc/log.h>
25 #include <isc/mem.h>
26 #include <isc/net.h>
27 #include <isc/parseint.h>
28 #include <isc/platform.h>
29 #include <isc/print.h>
30 #include <isc/sockaddr.h>
31 #include <isc/socket.h>
32 #include <isc/task.h>
33 #include <isc/timer.h>
34 #include <isc/util.h>
35 
36 #include <dns/dispatch.h>
37 #include <dns/events.h>
38 #include <dns/fixedname.h>
39 #include <dns/message.h>
40 #include <dns/name.h>
41 #include <dns/rdataset.h>
42 #include <dns/request.h>
43 #include <dns/resolver.h>
44 #include <dns/result.h>
45 #include <dns/types.h>
46 #include <dns/view.h>
47 
48 #include <dst/result.h>
49 
50 #define CHECK(str, x)                                        \
51 	{                                                    \
52 		if ((x) != ISC_R_SUCCESS) {                  \
53 			fprintf(stderr, "I:%s: %s\n", (str), \
54 				isc_result_totext(x));       \
55 			exit(-1);                            \
56 		}                                            \
57 	}
58 
59 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
60 
61 #define PORT	5300
62 #define TIMEOUT 30
63 
64 static isc_mem_t *mctx;
65 static dns_requestmgr_t *requestmgr;
66 static bool have_src = false;
67 static isc_sockaddr_t srcaddr;
68 static isc_sockaddr_t dstaddr;
69 static int onfly;
70 
71 static void
72 recvresponse(isc_task_t *task, isc_event_t *event) {
73 	dns_requestevent_t *reqev = (dns_requestevent_t *)event;
74 	isc_result_t result;
75 	dns_message_t *query, *response;
76 	isc_buffer_t outbuf;
77 	char output[1024];
78 
79 	UNUSED(task);
80 
81 	REQUIRE(reqev != NULL);
82 
83 	if (reqev->result != ISC_R_SUCCESS) {
84 		fprintf(stderr, "I:request event result: %s\n",
85 			isc_result_totext(reqev->result));
86 		exit(-1);
87 	}
88 
89 	query = reqev->ev_arg;
90 
91 	response = NULL;
92 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
93 	CHECK("dns_message_create", result);
94 
95 	result = dns_request_getresponse(reqev->request, response,
96 					 DNS_MESSAGEPARSE_PRESERVEORDER);
97 	CHECK("dns_request_getresponse", result);
98 
99 	if (response->rcode != dns_rcode_noerror) {
100 		result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
101 		fprintf(stderr, "I:response rcode: %s\n",
102 			isc_result_totext(result));
103 		exit(-1);
104 	}
105 	if (response->counts[DNS_SECTION_ANSWER] != 1U) {
106 		fprintf(stderr, "I:response answer count (%u!=1)\n",
107 			response->counts[DNS_SECTION_ANSWER]);
108 	}
109 
110 	isc_buffer_init(&outbuf, output, sizeof(output));
111 	result = dns_message_sectiontotext(
112 		response, DNS_SECTION_ANSWER, &dns_master_style_simple,
113 		DNS_MESSAGETEXTFLAG_NOCOMMENTS, &outbuf);
114 	CHECK("dns_message_sectiontotext", result);
115 	printf("%.*s", (int)isc_buffer_usedlength(&outbuf),
116 	       (char *)isc_buffer_base(&outbuf));
117 	fflush(stdout);
118 
119 	dns_message_destroy(&query);
120 	dns_message_destroy(&response);
121 	dns_request_destroy(&reqev->request);
122 	isc_event_free(&event);
123 
124 	if (--onfly == 0) {
125 		isc_app_shutdown();
126 	}
127 	return;
128 }
129 
130 static isc_result_t
131 sendquery(isc_task_t *task) {
132 	dns_request_t *request;
133 	dns_message_t *message;
134 	dns_name_t *qname;
135 	dns_rdataset_t *qrdataset;
136 	isc_result_t result;
137 	dns_fixedname_t queryname;
138 	isc_buffer_t buf;
139 	static char host[256];
140 	int c;
141 
142 	c = scanf("%255s", host);
143 	if (c == EOF) {
144 		return (ISC_R_NOMORE);
145 	}
146 
147 	onfly++;
148 
149 	dns_fixedname_init(&queryname);
150 	isc_buffer_init(&buf, host, strlen(host));
151 	isc_buffer_add(&buf, strlen(host));
152 	result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
153 				   dns_rootname, 0, NULL);
154 	CHECK("dns_name_fromtext", result);
155 
156 	message = NULL;
157 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
158 	CHECK("dns_message_create", result);
159 
160 	message->opcode = dns_opcode_query;
161 	message->flags |= DNS_MESSAGEFLAG_RD;
162 	message->rdclass = dns_rdataclass_in;
163 	message->id = (unsigned short)(random() & 0xFFFF);
164 
165 	qname = NULL;
166 	result = dns_message_gettempname(message, &qname);
167 	CHECK("dns_message_gettempname", result);
168 
169 	qrdataset = NULL;
170 	result = dns_message_gettemprdataset(message, &qrdataset);
171 	CHECK("dns_message_gettemprdataset", result);
172 
173 	dns_name_init(qname, NULL);
174 	dns_name_clone(dns_fixedname_name(&queryname), qname);
175 	dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
176 				  dns_rdatatype_a);
177 	ISC_LIST_APPEND(qname->list, qrdataset, link);
178 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
179 
180 	request = NULL;
181 	result = dns_request_createvia(
182 		requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, -1,
183 		DNS_REQUESTOPT_TCP | DNS_REQUESTOPT_SHARE, NULL, TIMEOUT, 0, 0,
184 		task, recvresponse, message, &request);
185 	CHECK("dns_request_create", result);
186 
187 	return (ISC_R_SUCCESS);
188 }
189 
190 static void
191 sendqueries(isc_task_t *task, isc_event_t *event) {
192 	isc_result_t result;
193 
194 	isc_event_free(&event);
195 
196 	do {
197 		result = sendquery(task);
198 	} while (result == ISC_R_SUCCESS);
199 
200 	if (onfly == 0) {
201 		isc_app_shutdown();
202 	}
203 	return;
204 }
205 
206 int
207 main(int argc, char *argv[]) {
208 	isc_sockaddr_t bind_any;
209 	struct in_addr inaddr;
210 	isc_result_t result;
211 	isc_log_t *lctx;
212 	isc_logconfig_t *lcfg;
213 	isc_taskmgr_t *taskmgr;
214 	isc_task_t *task;
215 	isc_timermgr_t *timermgr;
216 	isc_socketmgr_t *socketmgr;
217 	dns_dispatchmgr_t *dispatchmgr;
218 	unsigned int attrs, attrmask;
219 	dns_dispatch_t *dispatchv4;
220 	dns_view_t *view;
221 	uint16_t port = PORT;
222 	int c;
223 
224 	RUNCHECK(isc_app_start());
225 
226 	isc_commandline_errprint = false;
227 	while ((c = isc_commandline_parse(argc, argv, "p:r:")) != -1) {
228 		switch (c) {
229 		case 'p':
230 			result = isc_parse_uint16(&port,
231 						  isc_commandline_argument, 10);
232 			if (result != ISC_R_SUCCESS) {
233 				fprintf(stderr, "bad port '%s'\n",
234 					isc_commandline_argument);
235 				exit(1);
236 			}
237 			break;
238 		case 'r':
239 			fprintf(stderr, "The -r option has been deprecated.\n");
240 			break;
241 		case '?':
242 			fprintf(stderr, "%s: invalid argument '%c'", argv[0],
243 				c);
244 			break;
245 		default:
246 			break;
247 		}
248 	}
249 
250 	argc -= isc_commandline_index;
251 	argv += isc_commandline_index;
252 	POST(argv);
253 
254 	if (argc > 0) {
255 		have_src = true;
256 	}
257 
258 	dns_result_register();
259 
260 	isc_sockaddr_any(&bind_any);
261 
262 	result = ISC_R_FAILURE;
263 	if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) {
264 		CHECK("inet_pton", result);
265 	}
266 	isc_sockaddr_fromin(&srcaddr, &inaddr, 0);
267 
268 	result = ISC_R_FAILURE;
269 	if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) {
270 		CHECK("inet_pton", result);
271 	}
272 	isc_sockaddr_fromin(&dstaddr, &inaddr, port);
273 
274 	mctx = NULL;
275 	isc_mem_create(&mctx);
276 
277 	lctx = NULL;
278 	lcfg = NULL;
279 	isc_log_create(mctx, &lctx, &lcfg);
280 
281 	RUNCHECK(dst_lib_init(mctx, NULL));
282 
283 	taskmgr = NULL;
284 	RUNCHECK(isc_taskmgr_create(mctx, 1, 0, NULL, &taskmgr));
285 	task = NULL;
286 	RUNCHECK(isc_task_create(taskmgr, 0, &task));
287 	timermgr = NULL;
288 
289 	RUNCHECK(isc_timermgr_create(mctx, &timermgr));
290 	socketmgr = NULL;
291 	RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
292 	dispatchmgr = NULL;
293 	RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
294 
295 	attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY |
296 		DNS_DISPATCHATTR_IPV4;
297 	attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP |
298 		   DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
299 	dispatchv4 = NULL;
300 	RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
301 				     have_src ? &srcaddr : &bind_any, 4096, 4,
302 				     2, 3, 5, attrs, attrmask, &dispatchv4));
303 	requestmgr = NULL;
304 	RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
305 				       dispatchmgr, dispatchv4, NULL,
306 				       &requestmgr));
307 
308 	view = NULL;
309 	RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
310 
311 	RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL));
312 
313 	(void)isc_app_run();
314 
315 	dns_view_detach(&view);
316 
317 	dns_requestmgr_shutdown(requestmgr);
318 	dns_requestmgr_detach(&requestmgr);
319 
320 	dns_dispatch_detach(&dispatchv4);
321 	dns_dispatchmgr_destroy(&dispatchmgr);
322 
323 	isc_socketmgr_destroy(&socketmgr);
324 	isc_timermgr_destroy(&timermgr);
325 
326 	isc_task_shutdown(task);
327 	isc_task_detach(&task);
328 	isc_taskmgr_destroy(&taskmgr);
329 
330 	dst_lib_destroy();
331 
332 	isc_log_destroy(&lctx);
333 
334 	isc_mem_destroy(&mctx);
335 
336 	isc_app_finish();
337 
338 	return (0);
339 }
340